master 529ea15a18c4 cached
37 files
65.2 KB
17.2k tokens
89 symbols
1 requests
Download .txt
Repository: ahmed-aliraqi/laravel-media-uploader
Branch: master
Commit: 529ea15a18c4
Files: 37
Total size: 65.2 KB

Directory structure:
gitextract_84fnq49y/

├── .editorconfig
├── .gitattributes
├── .github/
│   └── workflows/
│       └── tests.yml
├── .gitignore
├── .styleci.yml
├── README.md
├── _ide_helper.php
├── changelog.md
├── composer.json
├── phpunit.xml
├── src/
│   ├── Config/
│   │   └── laravel-media-uploader.php
│   ├── Console/
│   │   └── TemporaryClearCommand.php
│   ├── Database/
│   │   └── Migrations/
│   │       └── 2020_06_03_131044_create_temporary_files_table.php
│   ├── Entities/
│   │   ├── Concerns/
│   │   │   └── HasUploader.php
│   │   └── TemporaryFile.php
│   ├── Http/
│   │   ├── Controllers/
│   │   │   └── MediaController.php
│   │   └── Requests/
│   │       └── MediaRequest.php
│   ├── Listeners/
│   │   └── ProcessUploadedMedia.php
│   ├── Providers/
│   │   ├── EventServiceProvider.php
│   │   ├── RouteServiceProvider.php
│   │   └── UploaderServiceProvider.php
│   ├── Resources/
│   │   └── lang/
│   │       ├── ar/
│   │       │   └── validation.php
│   │       └── en/
│   │           └── validation.php
│   ├── Routes/
│   │   └── api.php
│   ├── Rules/
│   │   └── MediaRule.php
│   ├── Support/
│   │   ├── FFmpegDriver.php
│   │   └── Uploader.php
│   └── Transformers/
│       └── MediaResource.php
└── tests/
    ├── Feature/
    │   └── UploaderFeatureTest.php
    ├── Models/
    │   └── Blog.php
    ├── TestCase.php
    ├── Unit/
    │   └── UploaderUnitTest.php
    ├── config/
    │   ├── laravel-media-uploader.php
    │   └── media-library.php
    └── database/
        └── migrations/
            ├── 2020_06_03_131044_create_temporary_files_table.php
            ├── 2020_06_03_131049_create_blogs_table.php
            └── 2020_06_26_194753_create_media_table.php

================================================
FILE CONTENTS
================================================

================================================
FILE: .editorconfig
================================================
; This file is for unifying the coding style for different editors and IDEs.
; More information at http://editorconfig.org

root = true

[*]
charset = utf-8
indent_size = 4
indent_style = space
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.blade.php]
insert_final_newline = false
trim_trailing_whitespace = false

[*.md]
trim_trailing_whitespace = false

================================================
FILE: .gitattributes
================================================

# Path-based git attributes
# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html

# Ignore all test and documentation with "export-ignore".
/.github            export-ignore
/.gitattributes     export-ignore
/.gitignore         export-ignore
/.travis.yml        export-ignore
/phpunit.xml.dist   export-ignore
/.styleci.yml       export-ignore
/tests              export-ignore
/.editorconfig      export-ignore
/changelog.md       export-ignore
/phpunit.xml        export-ignore
/README.md          export-ignore


================================================
FILE: .github/workflows/tests.yml
================================================
name: tests
on:
    push:
    pull_request:
    schedule:
        - cron: '0 0 * * *'

jobs:
    run-tests:
        runs-on: ubuntu-latest
        strategy:
            fail-fast: false
            matrix:
                php: [8.0, 8.1, 8.2, 8.3]
                laravel: [9.*]
                dependency-version: [prefer-lowest, prefer-stable]
                include:
                    - laravel: 9.*
                      testbench: 7.*
                      laravel-medialibrary: 10.*

        name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }}

        steps:
            - name: Update apt
              run: sudo apt-get update --fix-missing

            - name: Install ffmpeg
              run: sudo apt-get install ffmpeg

            - name: Checkout code
              uses: actions/checkout@v2

            - name: Setup PHP
              uses: shivammathur/setup-php@v2
              with:
                  php-version: ${{ matrix.php }}
                  extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick
                  coverage: none

            - name: Setup Problem Matches
              run: |
                  echo "::add-matcher::${{ runner.tool_cache }}/php.json"
                  echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
            - name: Fix Imagick Policy
              run: sudo sed -i 's/none/read|write/g' /etc/ImageMagick-6/policy.xml

            - name: Install dependencies
              run: |
                  composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
                  composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest
            - name: Execute tests
              run: vendor/bin/phpunit
              env:
                  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
                  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
                  AWS_DEFAULT_REGION: ${{ secrets.AWS_DEFAULT_REGION }}
                  AWS_BUCKET: ${{ secrets.AWS_BUCKET }}


================================================
FILE: .gitignore
================================================
.idea
vendor
.phpunit.result.cache
composer.lock

================================================
FILE: .styleci.yml
================================================
preset: laravel


================================================
FILE: README.md
================================================
# Laravel Media Uploader
<p align="center">
<a href="https://github.com/ahmed-aliraqi/laravel-media-uploader/actions"><img src="https://github.com/ahmed-aliraqi/laravel-media-uploader/workflows/tests/badge.svg" alt="Build Status"></a>
	<a href="https://github.styleci.io/repos/275045511"><img src="https://github.styleci.io/repos/275045511/shield?style=flat" alt="StyleCI"></a>
	<a href="https://packagist.org/packages/ahmed-aliraqi/laravel-media-uploader"><img src="https://poser.pugx.org/ahmed-aliraqi/laravel-media-uploader/d/total.svg" alt="Total Downloads"></a>
	<a href="https://packagist.org/packages/ahmed-aliraqi/laravel-media-uploader"><img src="https://poser.pugx.org/ahmed-aliraqi/laravel-media-uploader/v/stable.svg" alt="Latest Stable Version"></a>
	<a href="https://packagist.org/packages/ahmed-aliraqi/laravel-media-uploader"><img src="https://poser.pugx.org/ahmed-aliraqi/laravel-media-uploader/license.svg" alt="License"></a>
</p>

> This package used to upload files using laravel-media-library before saving model.

![Uploader](https://github.com/ahmed-aliraqi/laravel-file-uploader/blob/master/screenshots/uploader-v2.gif?raw=true)

> In this package all uploaded media will be processed.
* All videos will converted to `mp4`.
* All audios will converted to `mp3`.
* All images `width` & `height` & `ratio` will be saved as custom property. 
* All videos & audios `duration` will be saved as custom property. 
#### Requirements
- PHP >= 7.4
- You should be ensured that the [ffmpeg](https://ffmpeg.org) was installed on your server

#### Installation
```bash
composer require ahmed-aliraqi/laravel-media-uploader
```
> The package will automatically register a service provider.
  
> You need to publish and run the migration:

```bash
php artisan vendor:publish --provider="AhmedAliraqi\LaravelMediaUploader\Providers\UploaderServiceProvider" --tag="migrations"

php artisan migrate
```
> Publish [laravel-media-library](https://github.com/spatie/laravel-medialibrary) migrations:

```bash
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="migrations"
php artisan migrate
```

> If you want to customize `attachments` validation rules, you should publish the config file:

```bash
php artisan vendor:publish --provider="AhmedAliraqi\LaravelMediaUploader\Providers\UploaderServiceProvider" --tag="config"
```

> If you want to customize validation translations, you should publish the `lang` files:

```bash
php artisan vendor:publish --provider="AhmedAliraqi\LaravelMediaUploader\Providers\UploaderServiceProvider" --tag="uploader:translations"
```

> This is the default content of the config file:

```php
<?php

return [
    /*
     * Regenerate uploaded media after assign to model
     */
    'regenerate-after-assigning' => true,

    'documents_mime_types' => [
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .doc & .docx
        'application/vnd.ms-powerpoint',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .ppt & .pptx
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xls & .xlsx
        'text/plain',
        'application/pdf',
        'application/zip',
        'application/x-rar',
        'application/x-rar-compressed',
        'application/octet-stream',
    ],
];
```

> Use `HasUploader` trait in your model:

```php
<?php

namespace App;


use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\MediaLibrary\HasMedia;
use AhmedAliraqi\LaravelMediaUploader\Entities\Concerns\HasUploader;

class Blog extends Model implements HasMedia
{
    use InteractsWithMedia, HasUploader;
    ...
}
```
> In your controller use `addAllMediaFromTokens()` method to assign the uploaded media to model using the generated tokens:

```php
class BlogController extends Controller
{
        public function store(Request $request)
        {
            $blog = Blog::create($request->all());
            
            $blog->addAllMediaFromTokens();
    
            return back();
        }
}
``` 
> If you do not add any arguments in `addAllMediaFromTokens()` method will add all tokens in `request('media')` with any collection.
>
>If you want to save specific collection name add it to the second argument.
```php
// specified collection name
$blog->addAllMediaFromTokens([], 'pictures');

// specified tokens
$blog->addAllMediaFromTokens($request->input('tokens', []), 'pictures');
```

#### Front End Basic Usage
```blade
<div id="app">
    <file-uploader
            :unlimited="true"
            collection="avatars"
            :tokens="{{ json_encode(old('media', [])) }}"
            label="Upload Avatar"
            notes="Supported types: jpeg, png,jpg,gif"
            accept="image/jpeg,image/png,image/jpg,image/gif"
    ></file-uploader>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/laravel-file-uploader"></script>
<script>
  new Vue({
    el: '#app'
  })
</script>
```
###### Or Install Component Via NPM

```bash
npm i laravel-file-uploader --save-dev
``` 
> Now you should register the component in your `resources/js/app.js`:

```js
// app.js

import FileUploader from 'laravel-file-uploader';

Vue.use(FileUploader);
```

#### Usage
```blade
<file-uploader :media="{{ $user->getMediaResource('avatars') }}"
               :unlimited="true"
               collection="avatars"
               :tokens="{{ json_encode(old('media', [])) }}"
               label="Upload Avatar"
               notes="Supported types: jpeg, png,jpg,gif"
               accept="image/jpeg,image/png,image/jpg,image/gif"
></file-uploader>
```
##### Attributes
| Attribute |Rule | Type  |Description |
|--|--|--|--|
| media | optional - default: `[]`  |array | used to display an existing files  |
| unlimited |optional - default:`false`| boolean| upload unlimited files - if let it `false` will not be multiple select|
| max|optional - default:`12`| int| the maximum uploaded files - if `1` will not me multiple select|
|accept| optional - default: `*`| string| the accepted mime types|
|form| optional - default: `false`| string| the form id of the uploaded media|
|notes| optional - default `null`| string| the help-block that will be displayed under the files|
|label| optional - default `null`| string| the label of the uploader|
|collection| optional - default `default`|string| the media library collection that the file will store in|
|tokens| optional - default: `[]`|array|the recently uploaded files tokens, used to display recently uploaded files in validation case|
|max-width| optional - default: `1200`|string|The maximum width of uploaded image|
|max-height| optional - default: `1200`|string|The maximum height of uploaded image|

#### API
* Upload Files
    * endpoint: /api/uploader/media/upload
    * method: POST
    * body: 
        * files[]: multipart form data
    * response:
        * ![upload response](https://i.imgur.com/dvPX9Wa.png)
* Display Recently Uploaded Files
    * endpoint: /api/uploader/media
    * method: GET
    * params:
        * tokens[]: temporary token
    * response:
        * ![response](https://i.imgur.com/0xaaDPK.png)
* Delete Files
    * endpoint: /api/uploader/media/{id}
    * method: DELETE
    * response:
        * ![response](https://i.imgur.com/dghxe47.png)


================================================
FILE: _ide_helper.php
================================================
<?php
// @formatter:off

/**
 * A helper file for Laravel, to provide autocomplete information to your IDE
 **
 * @author Ahmed Fathy <aliraqi.dev@gmail.com>
 */

/**
 * @method static \AhmedAliraqi\LaravelMediaUploader\Forms\Components\ImageComponent image($name = null)
 * @method static \AhmedAliraqi\LaravelMediaUploader\Forms\Components\AudioComponent audio($name = null)
 * @method static \AhmedAliraqi\LaravelMediaUploader\Forms\Components\VideoComponent video($name = null)
 * @method static \AhmedAliraqi\LaravelMediaUploader\Forms\Components\MediaComponent media($name = null)
 */
class BsForm extends \Laraeast\LaravelBootstrapForms\Facades\BsForm {}

================================================
FILE: changelog.md
================================================
# Release Notes for Laravel Media Uploader
### v8.0.0
* **Fixes**
  - Remove support for BsForm package [2d17c04](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/2d17c04831f52838a7c1bc9157e57940030f81a8)
### v6.3.3
* **Fixes**
  - Run the artisan command once after saving the media instead of running in loop [22](https://github.com/ahmed-aliraqi/laravel-media-uploader/pull/22) by [AbdullahFaqeir](https://github.com/AbdullahFaqeir)
  - Fix base64 validation issue [05fed33](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/05fed333a5b96196cc78b4fa4aa1e533aef4f1e9)
### v6.3.0
* **Added**
  - Add Support for laravel 9.x [18](https://github.com/ahmed-aliraqi/laravel-media-uploader/pull/18) by [AbdullahFaqeir](https://github.com/AbdullahFaqeir)
  ### v6.2.0
* **Fixes**
  - Clean the temporary files every six hours [b132699](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/b1326999f3cac6a548bad11c00cf2d7da0287b0d)
* **Added**
  - Add Uploader helper [4e743bf](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/4e743bfefdcf03e6d9b3e0d05966f2c08e71ddda)
### v6.1.2
* **Fixes**
  - Replace Hindu-Arabic numerals to Arabic numerals [4e45b49](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/4e45b4945a8311eecb53e3fd26062934b43aeea4)
### v6.1.0
* **Added**
  - Optimize and Upload images as base64.
### v6.0.1
* **Fixes**
  - Add ability to filter by collection with token to avoid duplicate the old media.
### v6.0.0
* **Added**
  - Add support for php 8.0
* **Changes**
  - Use `MediaHasBeenAdded` Event instead of `PerformConversionsJob`
  - Bump `laravel media library` from ^8.0 to ^9.0
### v5.1.0
* **Added**
  - Add `AudioComponent` for `laravel-bootstrap-forms`,
  - Add `VideoComponent` for `laravel-bootstrap-forms`,
  - Add `Audioomponent` for `laravel-bootstrap-forms`,
  - Add `Mediaomponent` for `laravel-bootstrap-forms`,
  - Add `_ide_helper.php` file to provide autocomplete information to your IDE.

### v5.0.1
* **Fixes**
    - Keep only configured latest media [4e3f6e6](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/4e3f6e6c4b25797fafa1cae3173e89a93e260339).
### v5.0.0
* **Added**
    - Add `form` and `unlimited` option to form component.
### v4.1.1
* **Fixes**
    - Fix support for laravel 8.x [678f06d](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/678f06d8441c2cbd8923bc3f0c6aa7b831c36f78)
### v4.1.0
* **Added**
    - Add support for laravel 8.x
### v4.0.0
* **Changes**
    - Upgraded media-library to ^8.0. [c7f1e8e](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/c7f1e8eda602d4b377cb33c98cf244c200dd1cf1)
### v3.0.0
* **Changes**
    - change vendor name of laravel-bootstrap-forms. [d09599d](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/d09599d07d8e6ca92f393de0dd0a47cc1c934b32)
### v2.1.0
* **Added**
    - Add "regenerate-after-assigning" option in config file [4fb569b](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/4fb569ba99dafd3098698e4aa274c1868d0d9206)
* **Changes**
    - The first argument of `addAllMediaFromTokens($tokens)` now support `string`, `array`, `null` value. [a451ebb](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/a451ebbdfac6e94ca1c588977a4ada4c489a48bf)
### v2.0.1
* **Fixes**
    - Register and publish translations [b5b7dd3](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/b5b7dd3efd11a6c0c6aeac82e83003da645a1a09)
### v2.0.0
* **Changes**
    - Remove built in migration and use published instead [8611ac6](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/8611ac6bbb9b8833c8231ae8d03e4cf1cb7d6866).
    - Remove `uploader:install` command line [7f0bb58](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/7f0bb58b45f634ba4937ff7cdfee025e8a6e021b).
    - Optional `preview` flag in MediaResource [e16344d](https://github.com/ahmed-aliraqi/laravel-media-uploader/commit/e16344de7eed1fdd33c33186fc4c0b21df23f835).
### v1.0.1
* **Changes**
    - Add tow optional arguments in `addAllMediaFromTokens()`
        - $tokens = []
        - $collection = 'default'


================================================
FILE: composer.json
================================================
{
    "name": "ahmed-aliraqi/laravel-media-uploader",
    "description": "This package used to upload files using laravel-media-library",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Ahmed Fathy",
            "email": "aliraqi.dev@gmail.com"
        }
    ],
    "require": {
        "php": "^7.4|^8.0",
        "laravel/framework": "~5.7|~5.8|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0",
        "spatie/laravel-medialibrary": "^9.0|^10.0|^11.0",
        "php-ffmpeg/php-ffmpeg": "^1.0"
    },
    "require-dev": {
        "orchestra/testbench": "~3.0|~5.3|~6.0|~7.0",
        "mockery/mockery": "^1.4"
    },
    "autoload": {
        "psr-4": {
            "AhmedAliraqi\\LaravelMediaUploader\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "AhmedAliraqi\\LaravelMediaUploader\\Tests\\": "tests/"
        }
    },
    "extra": {
        "laravel": {
            "providers": [
                "AhmedAliraqi\\LaravelMediaUploader\\Providers\\UploaderServiceProvider"
            ]
        }
    }
}


================================================
FILE: phpunit.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" backupStaticAttributes="false" colors="true" verbose="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
  <coverage>
    <include>
      <directory suffix=".php">src/</directory>
    </include>
  </coverage>
  <testsuites>
    <testsuite name="Laravel Media Uploader Test Suite">
      <directory>tests</directory>
    </testsuite>
  </testsuites>
</phpunit>


================================================
FILE: src/Config/laravel-media-uploader.php
================================================
<?php

return [
    /*
     * Regenerate uploaded media after assign to model
     */
    'regenerate-after-assigning' => true,

    'documents_mime_types' => [
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .doc & .docx
        'application/vnd.ms-powerpoint',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .ppt & .pptx
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xls & .xlsx
        'text/plain',
        'application/pdf',
        'application/zip',
        'application/x-rar',
        'application/x-rar-compressed',
        'application/octet-stream',
    ],
];


================================================
FILE: src/Console/TemporaryClearCommand.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Console;

use AhmedAliraqi\LaravelMediaUploader\Entities\TemporaryFile;
use Illuminate\Console\Command;

class TemporaryClearCommand extends Command
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'temporary:clean';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Clean expired uploaded temporary files.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        TemporaryFile::whereDate('created_at', '<=', today()->subHours(6))
            ->each(function (TemporaryFile $file) {
                $file->delete();
            });

        $this->info(
            "\nThe temporary files has been cleaned successfully. "
            .now()->toDateTimeString()
        );
    }
}


================================================
FILE: src/Database/Migrations/2020_06_03_131044_create_temporary_files_table.php
================================================
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTemporaryFilesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('temporary_files', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('token');
            $table->string('collection')->default('default');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('temporary_files');
    }
}


================================================
FILE: src/Entities/Concerns/HasUploader.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Entities\Concerns;

use AhmedAliraqi\LaravelMediaUploader\Entities\TemporaryFile;
use AhmedAliraqi\LaravelMediaUploader\Transformers\MediaResource;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Config;

trait HasUploader
{
    /**
     * Assign all uploaded temporary files to the model.
     *
     * @param  string|array|null  $tokens
     * @param  string|null  $collection
     * @return void
     */
    public function addAllMediaFromTokens($tokens = null, $collection = null)
    {
        $tokens = Arr::wrap($tokens);

        if (count($tokens) == 0) {
            $tokens = Arr::wrap(request('media'));
        }

        $query = TemporaryFile::query();

        if ($collection) {
            $query->where('collection', $collection);
        }

        $mediaIds = [];

        $query->whereIn('token', $tokens)
            ->each(function (TemporaryFile $file) use (&$mediaIds) {
                foreach ($file->getMedia($file->collection) as $media) {
                    $media->forceFill([
                        'model_type' => $this->getMorphClass(),
                        'model_id' => $this->getKey(),
                    ])->save();
                    $mediaIds[] = $media->id;
                }

                $file->delete();
            });

        if (count($mediaIds) > 0 && Config::get('laravel-media-uploader.regenerate-after-assigning')) {
            Artisan::call('media-library:regenerate', [
                '--ids' => implode(',', $mediaIds),
                '--force' => true,
            ]);
        }

        $collection = $collection ?: 'default';

        if ($collectionSizeLimit = optional($this->getMediaCollection($collection))->collectionSizeLimit) {
            $collectionMedia = $this->refresh()->getMedia($collection);

            if ($collectionMedia->count() > $collectionSizeLimit) {
                $this->clearMediaCollectionExcept(
                    $collection,
                    $collectionMedia
                        ->reverse()
                        ->take($collectionSizeLimit)
                );
            }
        }
    }

    /**
     * Get all the model media of the given collection using "MediaResource".
     *
     * @param  string  $collection
     * @return \Illuminate\Support\Collection
     */
    public function getMediaResource($collection = 'default')
    {
        return collect(
            MediaResource::collection(
                $this->getMedia($collection)
            )->jsonSerialize()
        );
    }
}


================================================
FILE: src/Entities/TemporaryFile.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Entities;

use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class TemporaryFile extends Model implements HasMedia
{
    use InteractsWithMedia;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'token',
        'collection',
    ];

    /**
     * Register the conversions for the specified model.
     *
     *
     * @throws \Spatie\Image\Exceptions\InvalidManipulation
     */
    public function registerMediaConversions(?Media $media = null): void
    {
        $this->addMediaConversion('thumb')
            ->width(70)
            ->format('png');

        $this->addMediaConversion('small')
            ->width(120)
            ->format('png');

        $this->addMediaConversion('medium')
            ->width(160)
            ->format('png');

        $this->addMediaConversion('large')
            ->width(320)
            ->format('png');
    }
}


================================================
FILE: src/Http/Controllers/MediaController.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Http\Controllers;

use AhmedAliraqi\LaravelMediaUploader\Entities\TemporaryFile;
use AhmedAliraqi\LaravelMediaUploader\Http\Requests\MediaRequest;
use AhmedAliraqi\LaravelMediaUploader\Support\Uploader;
use AhmedAliraqi\LaravelMediaUploader\Transformers\MediaResource;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Str;

class MediaController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
     */
    public function index()
    {
        $modelClass = Config::get(
            'media-library.media_model',
            \Spatie\MediaLibrary\MediaCollections\Models\Media::class
        );

        $tokens = is_array(request('tokens')) ? request('tokens') : [];

        $media = $modelClass::whereHasMorph(
            'model',
            [TemporaryFile::class],
            function (Builder $builder) use ($tokens) {
                $builder->whereIn('token', $tokens);
                $builder->when(request('collection'), function (Builder $builder) {
                    $builder->where(request()->only('collection'));
                });
            }
        )->get();

        return MediaResource::collection($media);
    }

    /**
     * Store a newly created resource in storage.
     *
     * @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
     *
     * @throws \Spatie\MediaLibrary\MediaCollections\Exceptions\FileDoesNotExist
     * @throws \Spatie\MediaLibrary\MediaCollections\Exceptions\FileIsTooBig
     */
    public function store(MediaRequest $request)
    {
        /** @var \AhmedAliraqi\LaravelMediaUploader\Entities\TemporaryFile $temporaryFile */
        $temporaryFile = TemporaryFile::create([
            'token' => Str::random(60),
            'collection' => $request->input('collection', 'default'),
        ]);

        if (is_string($request->file) && base64_decode(base64_encode($request->file)) === $request->file) {
            $temporaryFile->addMediaFromBase64($request->file)
                ->usingFileName(time().'.png')
                ->toMediaCollection($temporaryFile->collection);
        }

        if ($request->hasFile('file')) {
            $temporaryFile->addMedia($request->file)
                ->usingFileName(Uploader::formatName($request->file))
                ->toMediaCollection($temporaryFile->collection);
        }

        foreach ($request->file('files', []) as $file) {
            $temporaryFile->addMedia($file)
                ->usingFileName(Uploader::formatName($file))
                ->toMediaCollection($temporaryFile->collection);
        }

        return MediaResource::collection(
            $temporaryFile->getMedia(
                $temporaryFile->collection ?: 'default'
            )
        )->additional([
            'token' => $temporaryFile->token,
        ]);
    }

    /**
     * @return \Illuminate\Http\JsonResponse
     */
    public function destroy($media)
    {
        $modelClass = Config::get(
            'media-library.media_model',
            \Spatie\MediaLibrary\MediaCollections\Models\Media::class
        );

        $media = $modelClass::findOrFail($media);

        $media->delete();

        return response()->json([
            'message' => 'deleted',
        ]);
    }
}


================================================
FILE: src/Http/Requests/MediaRequest.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Http\Requests;

use AhmedAliraqi\LaravelMediaUploader\Rules\MediaRule;
use Illuminate\Foundation\Http\FormRequest;

class MediaRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'file' => ['sometimes', 'required', new MediaRule('image', 'video', 'audio', 'document')],
            'files' => ['sometimes', 'required', 'array'],
            'files.*' => ['sometimes', 'required', new MediaRule('image', 'video', 'audio', 'document')],
            'collection' => ['nullable', 'string'],
        ];
    }

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }
}


================================================
FILE: src/Listeners/ProcessUploadedMedia.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Listeners;

use FFMpeg\Format\Audio\Mp3;
use FFMpeg\Format\Video\X264;
use FFMpeg\Media\Audio;
use FFMpeg\Media\Video;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Config;
use Intervention\Image\Facades\Image;
use RuntimeException;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Image as ImageGenerator;
use Spatie\MediaLibrary\MediaCollections\Events\MediaHasBeenAdded;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class ProcessUploadedMedia implements ShouldQueue
{
    /**
     * Handle the event.
     *
     * @return void
     *
     * @throws \Exception
     */
    public function handle(MediaHasBeenAdded $event)
    {
        if (app()->runningUnitTests()) {
            return;
        }

        if ($event->media->getCustomProperty('status') == 'processed') {
            // Skipped Processing Media File
            return;
        }

        try {
            if ($this->isImage($event->media)) {
                $path = $this->processImage($event->media);
            } elseif ($this->isDocument($event->media)) {
                $path = $this->processDocument($event->media);
            } elseif ($this->isVideo($event->media)) {
                $path = $this->processVideo($event->media);
            } elseif ($this->isAudio($event->media)) {
                $path = $this->processAudio($event->media);
            } else {
                $path = null;
            }
            $this->processingDone($event->media, $path);
        } catch (RuntimeException $e) {
            $this->processingFailed($event->media);
        }

        $event->media->setCustomProperty('status', 'processing')->save();
    }

    /**
     * Determine if the media file is an image.
     *
     * @return bool
     */
    protected function isImage(Media $media)
    {
        return (new ImageGenerator)->canHandleMime($media->mime_type);
    }

    /**
     * Determine if the media file is a document.
     *
     * @return bool
     */
    protected function isDocument(Media $media)
    {
        return in_array(
            $media->mime_type,
            Config::get('laravel-media-uploader.documents_mime_types')
        );
    }

    /**
     * Determine if the media file is a video and initiate the required driver.
     *
     * @return bool
     */
    protected function isVideo(Media $media)
    {
        return app('ffmpeg-driver')->open($media->getPath()) instanceof Video;
    }

    /**
     * Determine if the media file is an audio and the initiate required driver.
     *
     * @return bool
     */
    protected function isAudio(Media $media)
    {
        return app('ffmpeg-driver')->open($media->getPath()) instanceof Audio;
    }

    /**
     * Process Image File.
     *
     * @return null
     */
    protected function processImage(Media $media)
    {
        $image = Image::make($media->getPath())->orientate();

        $media
            ->setCustomProperty('type', 'image')
            ->setCustomProperty('width', $image->width())
            ->setCustomProperty('height', $image->height())
            ->setCustomProperty('ratio', (string) round($image->width() / $image->height(), 3))
            ->save();
    }

    /**
     * Process Document File.
     *
     * @return null
     */
    protected function processDocument(Media $media)
    {
        $media->setCustomProperty('type', 'document')->save();
    }

    /**
     * Process Video File.
     *
     * @return string
     */
    protected function processVideo(Media $media)
    {
        $media->setCustomProperty('type', 'video')->save();

        $video = app('ffmpeg-driver')->open($media->getPath());

        $format = new X264;

        $format->on('progress', $this->increaseProcessProgress($media));

        $format->setAudioCodec('aac');

        $format->setAdditionalParameters(['-vf', 'pad=ceil(iw/2)*2:ceil(ih/2)*2']);

        $video->save($format, $processedFile = $this->generatePathForProcessedFile($media, 'mp4'));

        return $processedFile;
    }

    /**
     * Process Audio File.
     *
     * @return string
     */
    protected function processAudio(Media $media)
    {
        $media->setCustomProperty('type', 'audio')->save();

        $audio = app('ffmpeg-driver')->open($media->getPath());

        $format = new Mp3;

        $format->on('progress', $this->increaseProcessProgress($media));

        $audio->save($format, $processedFile = $this->generatePathForProcessedFile($media, 'mp3'));

        return $processedFile;
    }

    protected function increaseProcessProgress(Media $media): \Closure
    {
        return function (
            $file,
            $format,
            $percentage
        ) use ($media) {
            // Progress Percentage is $percentage
            $media->setCustomProperty('progress', $percentage);
            $media->save();
        };
    }

    /**
     * @param  null  $processedFilePath
     * @return void
     *
     * @throws \Exception
     */
    protected function processingDone(Media $media, $processedFilePath = null)
    {
        // If the processing does not ended with generating a new file.
        if (is_null($processedFilePath)) {
            $media->setCustomProperty('status', 'processed')
                ->setCustomProperty('progress', 100)
                ->save();
        } else {
            // New Converted Media Will Be Added
            $duration = app('ffmpeg-driver')
                ->getFFProbe()
                ->format($processedFilePath)
                ->get('duration');

            $media->model
                ->addMedia($processedFilePath)
                ->withCustomProperties([
                    'type' => $media->getCustomProperty('type'),
                    'status' => 'processed',
                    'progress' => 100,
                    'duration' => $duration,
                ])
                ->preservingOriginal()
                ->toMediaCollection($media->collection_name);

            (clone $media)->delete();
        }
    }

    /**
     * Mark media status as failed.
     */
    protected function processingFailed(Media $media)
    {
        $media->setCustomProperty('status', 'failed')->save();
    }

    /**
     * @param  null  $extension
     * @return string
     */
    protected function generatePathForProcessedFile(Media $media, $extension = null)
    {
        $path = $media->getPath();

        return pathinfo($path, PATHINFO_DIRNAME)
            .DIRECTORY_SEPARATOR.pathinfo($path, PATHINFO_FILENAME)
            .'.processed.'.$extension;
    }
}


================================================
FILE: src/Providers/EventServiceProvider.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Providers;

use AhmedAliraqi\LaravelMediaUploader\Listeners\ProcessUploadedMedia;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Spatie\MediaLibrary\MediaCollections\Events\MediaHasBeenAdded;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        MediaHasBeenAdded::class => [
            ProcessUploadedMedia::class,
        ],
    ];
}


================================================
FILE: src/Providers/RouteServiceProvider.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Providers;

use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;

class RouteServiceProvider extends ServiceProvider
{
    /**
     * The namespace to assume when generating URLs to actions.
     *
     * @var string
     */
    protected $namespace = 'AhmedAliraqi\LaravelMediaUploader\Http\Controllers';

    /**
     * Called before routes are registered.
     *
     * Register any model bindings or pattern based filters.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
    }

    /**
     * Define the routes for the application.
     *
     * @return void
     */
    public function map()
    {
        $this->mapApiRoutes();
    }

    /**
     * Define the "api" routes for the application.
     *
     * These routes are typically stateless.
     *
     * @return void
     */
    protected function mapApiRoutes()
    {
        Route::prefix('api')
            ->middleware('api')
            ->namespace($this->namespace)
            ->group(__DIR__.'/../Routes/api.php');
    }
}


================================================
FILE: src/Providers/UploaderServiceProvider.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Providers;

use AhmedAliraqi\LaravelMediaUploader\Console\TemporaryClearCommand;
use AhmedAliraqi\LaravelMediaUploader\Support\FFmpegDriver;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Support\ServiceProvider;

class UploaderServiceProvider extends ServiceProvider
{
    /**
     * Boot the application events.
     *
     * @return void
     */
    public function boot()
    {
        if (! defined('STDIN')) {
            define('STDIN', fopen('php://stdin', 'r'));
        }

        $this->registerConfig();

        $this->registerTranslations();

        $this->publishes([
            __DIR__.'/../Database/Migrations' => database_path('/migrations'),
        ], 'migrations');

        $this->commands([
            TemporaryClearCommand::class,
        ]);

        if (! $this->app->runningUnitTests()) {
            $this->app->booted(function () {
                $schedule = $this->app->make(Schedule::class);
                $schedule->command('temporary:clean')->everySixHours();
            });
        }
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->register(RouteServiceProvider::class);
        $this->app->register(EventServiceProvider::class);

        $this->app->singleton('ffmpeg-driver', function () {
            return (new FFmpegDriver)->driver();
        });
    }

    /**
     * Register config.
     *
     * @return void
     */
    protected function registerConfig()
    {
        $this->publishes([
            __DIR__.'/../Config/laravel-media-uploader.php' => config_path('laravel-media-uploader.php'),
        ], 'config');
        $this->mergeConfigFrom(
            __DIR__.'/../Config/laravel-media-uploader.php',
            'laravel-media-uploader'
        );
    }

    /**
     * Register translations.
     *
     * @return void
     */
    public function registerTranslations()
    {
        $this->publishes([
            __DIR__.'/../Resources/lang' => resource_path('lang/vendor/uploader'),
        ], 'uploader:translations');

        $this->loadTranslationsFrom(__DIR__.'/../Resources/lang', 'uploader');
    }
}


================================================
FILE: src/Resources/lang/ar/validation.php
================================================
<?php

return [
    'invalid' => 'قيمة حقل :attribute غير مدعومة',
];


================================================
FILE: src/Resources/lang/en/validation.php
================================================
<?php

return [
    'invalid' => 'The :attribute is not supported.',
];


================================================
FILE: src/Routes/api.php
================================================
<?php

Route::get('uploader/media', 'MediaController@index')->name('uploader.media.index');
Route::post('uploader/media/upload', 'MediaController@store')->name('uploader.media.store');
Route::delete('uploader/media/{media}', 'MediaController@destroy')->name('uploader.media.destroy');


================================================
FILE: src/Rules/MediaRule.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Rules;

use FFMpeg\Exception\RuntimeException;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Config;
use Spatie\MediaLibrary\Conversions\ImageGenerators\Image;

class MediaRule implements Rule
{
    /**
     * @var array
     */
    private $types;

    /**
     * @var \FFMpeg\FFMpeg
     */
    private $driver;

    /**
     * Create a new rule instance.
     */
    public function __construct(...$types)
    {
        $this->types = $types;
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  UploadedFile|mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        if (! $value instanceof UploadedFile && ! $this->isBase64($value)) {
            return false;
        }

        try {
            $type = $this->getTypeString($value);
        } catch (RuntimeException $e) {
            return false;
        }

        return in_array($type, $this->types);
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return trans('uploader::validation.invalid');
    }

    /**
     * @param  UploadedFile|mixed  $value
     */
    protected function getTypeString($value): string
    {
        if ($this->isBase64($value)) {
            return 'image';
        }

        $fileFullPath = $value->getRealPath();

        if ((new Image)->canHandleMime($value->getMimeType())) {
            $type = 'image';
        } elseif (in_array($value->getMimeType(), $this->documentsMimeTypes())) {
            $type = 'document';
        } else {
            $type = strtolower(class_basename(get_class(
                app('ffmpeg-driver')->open($fileFullPath)
            )));
        }

        return $type; // either: image, video or audio.
    }

    /**
     * The supported mime types for document files.
     *
     * @return string[]
     */
    protected function documentsMimeTypes()
    {
        return Config::get('laravel-media-uploader.documents_mime_types');
    }

    /**
     * Determine whither the value is base64 image.
     *
     * @return bool
     */
    protected function isBase64($value)
    {
        return is_string($value) && base64_decode(base64_encode($value)) === $value;
    }
}


================================================
FILE: src/Support/FFmpegDriver.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Support;

use FFMpeg\FFMpeg;
use Illuminate\Support\Facades\Config;

class FFmpegDriver
{
    /**
     * @var \FFMpeg\FFMpeg
     */
    private $driver;

    /**
     * Create driver instance.
     */
    public function __construct()
    {
        $this->driver = FFMpeg::create([
            'ffmpeg.binaries' => Config::get('media-library.ffmpeg_path'),
            'ffprobe.binaries' => Config::get('media-library.ffprobe_path'),
            'timeout' => 3600,
            'ffmpeg.threads' => 12,
        ]);
    }

    /**
     * @return \FFMpeg\FFMpeg
     */
    public function driver()
    {
        return $this->driver;
    }
}


================================================
FILE: src/Support/Uploader.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Support;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;

class Uploader
{
    /**
     * Get the formatted name of the given file.
     */
    public static function formatName(UploadedFile $file): string
    {
        $extension = '.'.$file->getClientOriginalExtension();

        $name = trim($file->getClientOriginalName(), $extension);

        $name = self::replaceNumbers($name);

        return Str::slug($name).$extension;
    }

    /**
     * Convert arabic & persian decimal to valid decimal.
     */
    public static function replaceNumbers(string $string): string
    {
        $newNumbers = range(0, 9);

        // 1. Persian HTML decimal
        $persianDecimal = [
            '&#1776;',
            '&#1777;',
            '&#1778;',
            '&#1779;',
            '&#1780;',
            '&#1781;',
            '&#1782;',
            '&#1783;',
            '&#1784;',
            '&#1785;',
        ];
        // 2. Arabic HTML decimal
        $arabicDecimal = [
            '&#1632;',
            '&#1633;',
            '&#1634;',
            '&#1635;',
            '&#1636;',
            '&#1637;',
            '&#1638;',
            '&#1639;',
            '&#1640;',
            '&#1641;',
        ];
        // 3. Arabic Numeric
        $arabic = ['٠', '١', '٢', '٣', '٤', '٥', '٦', '٧', '٨', '٩'];
        // 4. Persian Numeric
        $persian = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];

        $string = str_replace($persianDecimal, $newNumbers, $string);
        $string = str_replace($arabicDecimal, $newNumbers, $string);
        $string = str_replace($arabic, $newNumbers, $string);

        return str_replace($persian, $newNumbers, $string);
    }
}


================================================
FILE: src/Transformers/MediaResource.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Transformers;

use Illuminate\Http\Resources\Json\JsonResource;
use Spatie\MediaLibrary\Conversions\Conversion;
use Spatie\MediaLibrary\Conversions\ConversionCollection;

class MediaResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'url' => $this->getFullUrl(),
            'preview' => $this->getPreviewUrl(),
            'name' => $this->name,
            'file_name' => $this->file_name,
            'type' => $this->getType(),
            'mime_type' => $this->mime_type,
            'size' => $this->size,
            'human_readable_size' => $this->human_readable_size,
            'details' => $this->mediaDetails(),
            'status' => $this->mediaStatus(),
            'progress' => $this->when($this->mediaStatus() == 'processing', $this->getCustomProperty('progress')),
            'conversions' => $this->when(
                ($this->isImage() || $this->isVideo()) && ! empty($this->getConversions()),
                $this->getConversions()
            ),
            'links' => [
                'delete' => [
                    'href' => url('api/uploader/media/'.$this->getRouteKey()),
                    'method' => 'DELETE',
                ],
            ],
        ];
    }

    /**
     * Get the generated conversions links.
     *
     * @return array
     */
    public function getConversions()
    {
        $results = [];

        foreach (array_keys($this->getGeneratedConversions()->toArray()) as $conversionName) {
            $conversion = ConversionCollection::createForMedia($this->resource)
                ->first(fn (Conversion $conversion) => $conversion->getName() === $conversionName);

            if ($conversion) {
                $results[$conversionName] = $this->getFullUrl($conversionName);
            }
        }

        return $results;
    }

    /**
     * Determine if the media type is video.
     *
     * @return bool
     */
    public function isVideo()
    {
        return $this->getType() == 'video';
    }

    /**
     * Determine if the media type is image.
     *
     * @return bool
     */
    public function isImage()
    {
        return $this->getType() == 'image';
    }

    /**
     * Determine if the media type is audio.
     *
     * @return bool
     */
    public function isAudio()
    {
        return $this->getType() == 'audio';
    }

    /**
     * Get the media type.
     *
     * @return mixed|string
     */
    public function getType()
    {
        return $this->getCustomProperty('type') ?: $this->type;
    }

    /**
     * Get the preview url.
     *
     * @return string|void
     */
    public function getPreviewUrl()
    {
        if ($this->getType() == 'image') {
            return $this->getFullUrl();
        }

        return 'https://cdn.jsdelivr.net/npm/laravel-file-uploader/dist/img/attach.png';
    }

    protected function mediaDetails(): array
    {
        $duration = (float) $this->getCustomProperty('duration');

        return [
            $this->mergeWhen($this->isImage(), [
                'width' => $this->getCustomProperty('width'),
                'height' => $this->getCustomProperty('height'),
                'ratio' => (float) $this->getCustomProperty('ratio'),
            ]),
            'duration' => $this->when($this->isVideo() || $this->isAudio(), $duration),
        ];
    }

    /**
     * @return mixed
     */
    protected function mediaStatus()
    {
        return $this->getCustomProperty('status');
    }
}


================================================
FILE: tests/Feature/UploaderFeatureTest.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Tests\Feature;

use AhmedAliraqi\LaravelMediaUploader\Tests\Models\Blog;
use AhmedAliraqi\LaravelMediaUploader\Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

class UploaderFeatureTest extends TestCase
{
    /** @test */
    public function it_can_upload_and_display_temporary_files()
    {
        Storage::fake('public');

        $response = $this->postJson(url('/api/uploader/media/upload'), [
            'files' => [UploadedFile::fake()->image('thumbnail.jpg', 200)],
            'collection' => 'images',
        ]);

        $response->assertSuccessful();

        $response->assertJsonStructure([
            'data' => [
                [
                    'id',
                    'url',
                    'name',
                    'file_name',
                    'type',
                    'type',
                    'mime_type',
                    'size',
                    'human_readable_size',
                    'status',
                    'links',
                ],
            ],
        ]);

        // Display recently uploaded files via token.

        $response = $this->getJson(
            url('/api/uploader/media').'?tokens[]='.$response->json('token')
        );

        $response->assertSuccessful();

        $this->assertEquals(1, count($response->json('data')));
    }

    /** @test */
    public function it_can_delete_uploaded_files()
    {
        Storage::fake('public');

        /** @var Blog $blog */
        $blog = Blog::create();

        $blog->addMedia(
            UploadedFile::fake()
                ->create('thumbnail.jpg', 200)
        )->toMediaCollection();

        $this->assertEquals(1, $blog->getMedia()->count());

        $this->deleteJson(url('/api/uploader/media/'.$blog->getFirstMedia()->id));

        $blog->refresh();

        $this->assertEquals(0, $blog->getMedia()->count());
    }
}


================================================
FILE: tests/Models/Blog.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Tests\Models;

use AhmedAliraqi\LaravelMediaUploader\Entities\Concerns\HasUploader;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

class Blog extends Model implements HasMedia
{
    use HasUploader, InteractsWithMedia;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'blogs';

    /**
     * Define the media collections.
     */
    public function registerMediaCollections(): void
    {
        $this
            ->addMediaCollection('default')
            ->onlyKeepLatest(2);
    }
}


================================================
FILE: tests/TestCase.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Tests;

use AhmedAliraqi\LaravelMediaUploader\Providers\UploaderServiceProvider;
use Illuminate\Console\Application;
use Orchestra\Testbench\TestCase as OrchestraTestCase;
use Spatie\MediaLibrary\Conversions\Commands\RegenerateCommand;

class TestCase extends OrchestraTestCase
{
    /**
     * Set up the test environment.
     */
    protected function setUp(): void
    {
        parent::setUp();

        $this->loadLaravelMigrations(['--database' => 'testbench']);

        $this->loadMigrationsFrom(__DIR__.'/database/migrations');

        Application::starting(function ($artisan) {
            $artisan->resolveCommands([
                RegenerateCommand::class,
            ]);
        });
    }

    /**
     * Load package service provider.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return array
     */
    protected function getPackageProviders($app)
    {
        return [
            UploaderServiceProvider::class,
        ];
    }

    /**
     * Define environment setup.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return void
     */
    protected function getEnvironmentSetUp($app)
    {
        $app['config']->set('media-library', require __DIR__.'/config/media-library.php');
        $app['config']->set('laravel-media-uploader', require __DIR__.'/config/laravel-media-uploader.php');
        // Setup default database to use sqlite :memory:
        $app['config']->set('database.default', 'testbench');
        $app['config']->set('database.connections.testbench', [
            'driver' => 'sqlite',
            'database' => ':memory:',
            'prefix' => '',
        ]);
    }
}


================================================
FILE: tests/Unit/UploaderUnitTest.php
================================================
<?php

namespace AhmedAliraqi\LaravelMediaUploader\Tests\Unit;

use AhmedAliraqi\LaravelMediaUploader\Entities\TemporaryFile;
use AhmedAliraqi\LaravelMediaUploader\Support\Uploader;
use AhmedAliraqi\LaravelMediaUploader\Tests\Models\Blog;
use AhmedAliraqi\LaravelMediaUploader\Tests\TestCase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class UploaderUnitTest extends TestCase
{
    public function test_get_media_resource()
    {
        Storage::fake('public');

        /** @var Blog $blog */
        $blog = Blog::create();

        $blog->addMedia(
            UploadedFile::fake()
                ->create('thumbnail.jpg', 200)
        )->toMediaCollection();

        $this->assertInstanceOf(Collection::class, $blog->getMediaResource());
    }

    public function test_add_all_media_from_token()
    {
        Storage::fake('public');

        /** @var Blog $blog */
        $blog = Blog::create();

        $tmp = TemporaryFile::create([
            'token' => 123,
            'collection' => 'default',
        ]);

        $tmp->addMedia(
            UploadedFile::fake()
                ->image('thumbnail.jpg', 200)
        )->toMediaCollection();

        $media = $tmp->getFirstMedia('default');

        $this->assertEquals($media->model_type, TemporaryFile::class);
        $this->assertEquals($media->model_id, $tmp->id);

        $blog->addAllMediaFromTokens([123], 'avatars');

        $media->refresh();

        $this->assertEquals($media->model_type, TemporaryFile::class);
        $this->assertEquals($media->model_id, $tmp->id);

        $blog->addAllMediaFromTokens([123]);

        $media->refresh();

        $this->assertEquals($media->model_type, Blog::class);
        $this->assertEquals($media->model_id, $blog->id);
    }

    /** @test */
    public function it_keep_only_configured_latest_media()
    {
        $blog = Blog::create();

        $blog->addMedia(UploadedFile::fake()->image('thumbnail.jpg', 200))->toMediaCollection();

        $this->assertCount(1, $blog->refresh()->getMedia());

        $tmp = TemporaryFile::create(['token' => 123, 'collection' => 'default']);

        $tmp->addMedia(UploadedFile::fake()->image('thumbnail.jpg', 200))->toMediaCollection();

        $blog->addAllMediaFromTokens([123]);

        $this->assertCount(2, $blog->refresh()->getMedia());

        $tmp = TemporaryFile::create(['token' => 123, 'collection' => 'default']);

        $tmp->addMedia(UploadedFile::fake()->image('thumbnail.jpg', 200))->toMediaCollection();
        $tmp->addMedia(UploadedFile::fake()->image('thumbnail.jpg', 200))->toMediaCollection();

        $blog->addAllMediaFromTokens([123]);

        $this->assertCount(2, $blog->refresh()->getMedia());
    }

    public function test_uploader_helper()
    {
        $this->assertEquals(
            Str::slug('صورة').'.jpg',
            Uploader::formatName(UploadedFile::fake()->image('صورة.jpg', 200))
        );

        $this->assertEquals(
            '123.jpg',
            Uploader::formatName(UploadedFile::fake()->image('١٢٣.jpg', 200))
        );
    }
}


================================================
FILE: tests/config/laravel-media-uploader.php
================================================
<?php

return [
    'documents_mime_types' => [
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .doc & .docx
        'application/vnd.ms-powerpoint',
        'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .ppt & .pptx
        'application/vnd.ms-excel',
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xls & .xlsx
        'text/plain',
        'application/pdf',
        'application/zip',
        'application/x-rar',
        'application/x-rar-compressed',
        'application/octet-stream',
    ],
];


================================================
FILE: tests/config/media-library.php
================================================
<?php

return [

    /*
     * The disk on which to store added files and derived images by default. Choose
     * one or more of the disks you've configured in config/filesystems.php.
     */
    'disk_name' => env('MEDIA_DISK', 'public'),

    /*
     * The maximum file size of an item in bytes.
     * Adding a larger file will result in an exception.
     */
    'max_file_size' => 1024 * 1024 * 10,

    /*
     * This queue will be used to generate derived and responsive images.
     * Leave empty to use the default queue.
     */
    'queue_name' => '',

    /*
     * By default all conversions will be performed on a queue.
     */
    'queue_conversions_by_default' => env('QUEUE_CONVERSIONS_BY_DEFAULT', true),

    /*
     * The fully qualified class name of the media model.
     */
    'media_model' => Spatie\MediaLibrary\MediaCollections\Models\Media::class,

    /*
     * The fully qualified class name of the model used for temporary uploads.
     *
     * This model is only used in Media Library Pro (https://medialibrary.pro)
     */
    'temporary_upload_model' => Spatie\MediaLibraryPro\Models\TemporaryUpload::class,

    /*
     * When enabled, Media Library Pro will only process temporary uploads there were uploaded
     * in the same session. You can opt to disable this for stateless usage of
     * the pro components.
     */
    'enable_temporary_uploads_session_affinity' => true,

    /*
     * When enabled, Media Library pro will generate thumbnails for uploaded file.
     */
    'generate_thumbnails_for_temporary_uploads' => true,

    /*
     * This is the class that is responsible for naming generated files.
     */
    'file_namer' => Spatie\MediaLibrary\Support\FileNamer\DefaultFileNamer::class,

    /*
     * The class that contains the strategy for determining a media file's path.
     */
    'path_generator' => Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator::class,

    /*
     * When urls to files get generated, this class will be called. Use the default
     * if your files are stored locally above the site root or on s3.
     */
    'url_generator' => Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator::class,

    /*
     * Moves media on updating to keep path consistent. Enable it only with a custom
     * PathGenerator that uses, for example, the media UUID.
     */
    'moves_media_on_update' => false,

    /*
     * Whether to activate versioning when urls to files get generated.
     * When activated, this attaches a ?v=xx query string to the URL.
     */
    'version_urls' => false,

    /*
     * The media library will try to optimize all converted images by removing
     * metadata and applying a little bit of compression. These are
     * the optimizers that will be used by default.
     */
    'image_optimizers' => [
        Spatie\ImageOptimizer\Optimizers\Jpegoptim::class => [
            '-m85', // set maximum quality to 85%
            '--strip-all', // this strips out all text information such as comments and EXIF data
            '--all-progressive', // this will make sure the resulting image is a progressive one
        ],
        Spatie\ImageOptimizer\Optimizers\Pngquant::class => [
            '--force', // required parameter for this package
        ],
        Spatie\ImageOptimizer\Optimizers\Optipng::class => [
            '-i0', // this will result in a non-interlaced, progressive scanned image
            '-o2', // this set the optimization level to two (multiple IDAT compression trials)
            '-quiet', // required parameter for this package
        ],
        Spatie\ImageOptimizer\Optimizers\Svgo::class => [
            '--disable=cleanupIDs', // disabling because it is known to cause troubles
        ],
        Spatie\ImageOptimizer\Optimizers\Gifsicle::class => [
            '-b', // required parameter for this package
            '-O3', // this produces the slowest but best results
        ],
        Spatie\ImageOptimizer\Optimizers\Cwebp::class => [
            '-m 6', // for the slowest compression method in order to get the best compression.
            '-pass 10', // for maximizing the amount of analysis pass.
            '-mt', // multithreading for some speed improvements.
            '-q 90', // quality factor that brings the least noticeable changes.
        ],
    ],

    /*
     * These generators will be used to create an image of media files.
     */
    'image_generators' => [
        Spatie\MediaLibrary\Conversions\ImageGenerators\Image::class,
        Spatie\MediaLibrary\Conversions\ImageGenerators\Webp::class,
        Spatie\MediaLibrary\Conversions\ImageGenerators\Pdf::class,
        Spatie\MediaLibrary\Conversions\ImageGenerators\Svg::class,
        Spatie\MediaLibrary\Conversions\ImageGenerators\Video::class,
    ],

    /*
     * The path where to store temporary files while performing image conversions.
     * If set to null, storage_path('media-library/temp') will be used.
     */
    'temporary_directory_path' => null,

    /*
     * The engine that should perform the image conversions.
     * Should be either `gd` or `imagick`.
     */
    'image_driver' => env('IMAGE_DRIVER', 'gd'),

    /*
     * FFMPEG & FFProbe binaries paths, only used if you try to generate video
     * thumbnails and have installed the php-ffmpeg/php-ffmpeg composer
     * dependency.
     */
    'ffmpeg_path' => env('FFMPEG_PATH', '/usr/bin/ffmpeg'),
    'ffprobe_path' => env('FFPROBE_PATH', '/usr/bin/ffprobe'),

    /*
     * Here you can override the class names of the jobs used by this package. Make sure
     * your custom jobs extend the ones provided by the package.
     */
    'jobs' => [
        'perform_conversions' => Spatie\MediaLibrary\Conversions\Jobs\PerformConversionsJob::class,
        'generate_responsive_images' => Spatie\MediaLibrary\ResponsiveImages\Jobs\GenerateResponsiveImagesJob::class,
    ],

    /*
     * When using the addMediaFromUrl method you may want to replace the default downloader.
     * This is particularly useful when the url of the image is behind a firewall and
     * need to add additional flags, possibly using curl.
     */
    'media_downloader' => Spatie\MediaLibrary\Downloaders\DefaultDownloader::class,

    'remote' => [
        /*
         * Any extra headers that should be included when uploading media to
         * a remote disk. Even though supported headers may vary between
         * different drivers, a sensible default has been provided.
         *
         * Supported by S3: CacheControl, Expires, StorageClass,
         * ServerSideEncryption, Metadata, ACL, ContentEncoding
         */
        'extra_headers' => [
            'CacheControl' => 'max-age=604800',
        ],
    ],

    'responsive_images' => [
        /*
         * This class is responsible for calculating the target widths of the responsive
         * images. By default we optimize for filesize and create variations that each are 20%
         * smaller than the previous one. More info in the documentation.
         *
         * https://docs.spatie.be/laravel-medialibrary/v9/advanced-usage/generating-responsive-images
         */
        'width_calculator' => Spatie\MediaLibrary\ResponsiveImages\WidthCalculator\FileSizeOptimizedWidthCalculator::class,

        /*
         * By default rendering media to a responsive image will add some javascript and a tiny placeholder.
         * This ensures that the browser can already determine the correct layout.
         */
        'use_tiny_placeholders' => true,

        /*
         * This class will generate the tiny placeholder used for progressive image loading. By default
         * the media library will use a tiny blurred jpg image.
         */
        'tiny_placeholder_generator' => Spatie\MediaLibrary\ResponsiveImages\TinyPlaceholderGenerator\Blurred::class,
    ],

    /*
     * When enabling this option, a route will be registered that will enable
     * the Media Library Pro Vue and React components to move uploaded files
     * in a S3 bucket to their right place.
     */
    'enable_vapor_uploads' => env('ENABLE_MEDIA_LIBRARY_VAPOR_UPLOADS', false),

    /*
     * When converting Media instances to response the media library will add
     * a `loading` attribute to the `img` tag. Here you can set the default
     * value of that attribute.
     *
     * Possible values: 'lazy', 'eager', 'auto' or null if you don't want to set any loading instruction.
     *
     * More info: https://css-tricks.com/native-lazy-loading/
     */
    'default_loading_attribute_value' => null,
];


================================================
FILE: tests/database/migrations/2020_06_03_131044_create_temporary_files_table.php
================================================
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTemporaryFilesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('temporary_files', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('token');
            $table->string('collection')->default('default');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('temporary_files');
    }
}


================================================
FILE: tests/database/migrations/2020_06_03_131049_create_blogs_table.php
================================================
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateBlogsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('blogs', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('blogs');
    }
}


================================================
FILE: tests/database/migrations/2020_06_26_194753_create_media_table.php
================================================
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateMediaTable extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('media', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->morphs('model');
            $table->uuid('uuid')->nullable()->unique();
            $table->string('collection_name');
            $table->string('name');
            $table->string('file_name');
            $table->string('mime_type')->nullable();
            $table->string('disk');
            $table->string('conversions_disk')->nullable();
            $table->unsignedBigInteger('size');
            $table->json('manipulations');
            $table->json('custom_properties');
            $table->json('generated_conversions');
            $table->json('responsive_images');
            $table->unsignedInteger('order_column')->nullable();
            $table->nullableTimestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down()
    {
        Schema::dropIfExists('media');
    }
}
Download .txt
gitextract_84fnq49y/

├── .editorconfig
├── .gitattributes
├── .github/
│   └── workflows/
│       └── tests.yml
├── .gitignore
├── .styleci.yml
├── README.md
├── _ide_helper.php
├── changelog.md
├── composer.json
├── phpunit.xml
├── src/
│   ├── Config/
│   │   └── laravel-media-uploader.php
│   ├── Console/
│   │   └── TemporaryClearCommand.php
│   ├── Database/
│   │   └── Migrations/
│   │       └── 2020_06_03_131044_create_temporary_files_table.php
│   ├── Entities/
│   │   ├── Concerns/
│   │   │   └── HasUploader.php
│   │   └── TemporaryFile.php
│   ├── Http/
│   │   ├── Controllers/
│   │   │   └── MediaController.php
│   │   └── Requests/
│   │       └── MediaRequest.php
│   ├── Listeners/
│   │   └── ProcessUploadedMedia.php
│   ├── Providers/
│   │   ├── EventServiceProvider.php
│   │   ├── RouteServiceProvider.php
│   │   └── UploaderServiceProvider.php
│   ├── Resources/
│   │   └── lang/
│   │       ├── ar/
│   │       │   └── validation.php
│   │       └── en/
│   │           └── validation.php
│   ├── Routes/
│   │   └── api.php
│   ├── Rules/
│   │   └── MediaRule.php
│   ├── Support/
│   │   ├── FFmpegDriver.php
│   │   └── Uploader.php
│   └── Transformers/
│       └── MediaResource.php
└── tests/
    ├── Feature/
    │   └── UploaderFeatureTest.php
    ├── Models/
    │   └── Blog.php
    ├── TestCase.php
    ├── Unit/
    │   └── UploaderUnitTest.php
    ├── config/
    │   ├── laravel-media-uploader.php
    │   └── media-library.php
    └── database/
        └── migrations/
            ├── 2020_06_03_131044_create_temporary_files_table.php
            ├── 2020_06_03_131049_create_blogs_table.php
            └── 2020_06_26_194753_create_media_table.php
Download .txt
SYMBOL INDEX (89 symbols across 22 files)

FILE: _ide_helper.php
  class BsForm (line 16) | class BsForm extends \Laraeast\LaravelBootstrapForms\Facades\BsForm {}

FILE: src/Console/TemporaryClearCommand.php
  class TemporaryClearCommand (line 8) | class TemporaryClearCommand extends Command
    method __construct (line 29) | public function __construct()
    method handle (line 39) | public function handle()

FILE: src/Database/Migrations/2020_06_03_131044_create_temporary_files_table.php
  class CreateTemporaryFilesTable (line 7) | class CreateTemporaryFilesTable extends Migration
    method up (line 14) | public function up()
    method down (line 29) | public function down()

FILE: src/Entities/Concerns/HasUploader.php
  type HasUploader (line 11) | trait HasUploader
    method addAllMediaFromTokens (line 20) | public function addAllMediaFromTokens($tokens = null, $collection = null)
    method getMediaResource (line 78) | public function getMediaResource($collection = 'default')

FILE: src/Entities/TemporaryFile.php
  class TemporaryFile (line 10) | class TemporaryFile extends Model implements HasMedia
    method registerMediaConversions (line 30) | public function registerMediaConversions(?Media $media = null): void

FILE: src/Http/Controllers/MediaController.php
  class MediaController (line 14) | class MediaController extends Controller
    method index (line 21) | public function index()
    method store (line 52) | public function store(MediaRequest $request)
    method destroy (line 90) | public function destroy($media)

FILE: src/Http/Requests/MediaRequest.php
  class MediaRequest (line 8) | class MediaRequest extends FormRequest
    method rules (line 15) | public function rules()
    method authorize (line 30) | public function authorize()

FILE: src/Listeners/ProcessUploadedMedia.php
  class ProcessUploadedMedia (line 17) | class ProcessUploadedMedia implements ShouldQueue
    method handle (line 26) | public function handle(MediaHasBeenAdded $event)
    method isImage (line 62) | protected function isImage(Media $media)
    method isDocument (line 72) | protected function isDocument(Media $media)
    method isVideo (line 85) | protected function isVideo(Media $media)
    method isAudio (line 95) | protected function isAudio(Media $media)
    method processImage (line 105) | protected function processImage(Media $media)
    method processDocument (line 122) | protected function processDocument(Media $media)
    method processVideo (line 132) | protected function processVideo(Media $media)
    method processAudio (line 156) | protected function processAudio(Media $media)
    method increaseProcessProgress (line 171) | protected function increaseProcessProgress(Media $media): \Closure
    method processingDone (line 190) | protected function processingDone(Media $media, $processedFilePath = n...
    method processingFailed (line 222) | protected function processingFailed(Media $media)
    method generatePathForProcessedFile (line 231) | protected function generatePathForProcessedFile(Media $media, $extensi...

FILE: src/Providers/EventServiceProvider.php
  class EventServiceProvider (line 9) | class EventServiceProvider extends ServiceProvider

FILE: src/Providers/RouteServiceProvider.php
  class RouteServiceProvider (line 8) | class RouteServiceProvider extends ServiceProvider
    method boot (line 24) | public function boot()
    method map (line 34) | public function map()
    method mapApiRoutes (line 46) | protected function mapApiRoutes()

FILE: src/Providers/UploaderServiceProvider.php
  class UploaderServiceProvider (line 10) | class UploaderServiceProvider extends ServiceProvider
    method boot (line 17) | public function boot()
    method register (line 48) | public function register()
    method registerConfig (line 63) | protected function registerConfig()
    method registerTranslations (line 79) | public function registerTranslations()

FILE: src/Rules/MediaRule.php
  class MediaRule (line 11) | class MediaRule implements Rule
    method __construct (line 26) | public function __construct(...$types)
    method passes (line 38) | public function passes($attribute, $value)
    method message (line 58) | public function message()
    method getTypeString (line 66) | protected function getTypeString($value): string
    method documentsMimeTypes (line 92) | protected function documentsMimeTypes()
    method isBase64 (line 102) | protected function isBase64($value)

FILE: src/Support/FFmpegDriver.php
  class FFmpegDriver (line 8) | class FFmpegDriver
    method __construct (line 18) | public function __construct()
    method driver (line 31) | public function driver()

FILE: src/Support/Uploader.php
  class Uploader (line 8) | class Uploader
    method formatName (line 13) | public static function formatName(UploadedFile $file): string
    method replaceNumbers (line 27) | public static function replaceNumbers(string $string): string

FILE: src/Transformers/MediaResource.php
  class MediaResource (line 9) | class MediaResource extends JsonResource
    method toArray (line 17) | public function toArray($request)
    method getConversions (line 50) | public function getConversions()
    method isVideo (line 71) | public function isVideo()
    method isImage (line 81) | public function isImage()
    method isAudio (line 91) | public function isAudio()
    method getType (line 101) | public function getType()
    method getPreviewUrl (line 111) | public function getPreviewUrl()
    method mediaDetails (line 120) | protected function mediaDetails(): array
    method mediaStatus (line 137) | protected function mediaStatus()

FILE: tests/Feature/UploaderFeatureTest.php
  class UploaderFeatureTest (line 10) | class UploaderFeatureTest extends TestCase
    method it_can_upload_and_display_temporary_files (line 13) | public function it_can_upload_and_display_temporary_files()
    method it_can_delete_uploaded_files (line 54) | public function it_can_delete_uploaded_files()

FILE: tests/Models/Blog.php
  class Blog (line 10) | class Blog extends Model implements HasMedia
    method registerMediaCollections (line 24) | public function registerMediaCollections(): void

FILE: tests/TestCase.php
  class TestCase (line 10) | class TestCase extends OrchestraTestCase
    method setUp (line 15) | protected function setUp(): void
    method getPackageProviders (line 36) | protected function getPackageProviders($app)
    method getEnvironmentSetUp (line 49) | protected function getEnvironmentSetUp($app)

FILE: tests/Unit/UploaderUnitTest.php
  class UploaderUnitTest (line 14) | class UploaderUnitTest extends TestCase
    method test_get_media_resource (line 16) | public function test_get_media_resource()
    method test_add_all_media_from_token (line 31) | public function test_add_all_media_from_token()
    method it_keep_only_configured_latest_media (line 69) | public function it_keep_only_configured_latest_media()
    method test_uploader_helper (line 95) | public function test_uploader_helper()

FILE: tests/database/migrations/2020_06_03_131044_create_temporary_files_table.php
  class CreateTemporaryFilesTable (line 7) | class CreateTemporaryFilesTable extends Migration
    method up (line 14) | public function up()
    method down (line 29) | public function down()

FILE: tests/database/migrations/2020_06_03_131049_create_blogs_table.php
  class CreateBlogsTable (line 7) | class CreateBlogsTable extends Migration
    method up (line 14) | public function up()
    method down (line 27) | public function down()

FILE: tests/database/migrations/2020_06_26_194753_create_media_table.php
  class CreateMediaTable (line 7) | class CreateMediaTable extends Migration
    method up (line 12) | public function up()
    method down (line 37) | public function down()
Condensed preview — 37 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (72K chars).
[
  {
    "path": ".editorconfig",
    "chars": 388,
    "preview": "; This file is for unifying the coding style for different editors and IDEs.\n; More information at http://editorconfig.o"
  },
  {
    "path": ".gitattributes",
    "chars": 532,
    "preview": "\n# Path-based git attributes\n# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html\n\n# Ignore all test an"
  },
  {
    "path": ".github/workflows/tests.yml",
    "chars": 2197,
    "preview": "name: tests\non:\n    push:\n    pull_request:\n    schedule:\n        - cron: '0 0 * * *'\n\njobs:\n    run-tests:\n        runs"
  },
  {
    "path": ".gitignore",
    "chars": 48,
    "preview": ".idea\nvendor\n.phpunit.result.cache\ncomposer.lock"
  },
  {
    "path": ".styleci.yml",
    "chars": 16,
    "preview": "preset: laravel\n"
  },
  {
    "path": "README.md",
    "chars": 7494,
    "preview": "# Laravel Media Uploader\n<p align=\"center\">\n<a href=\"https://github.com/ahmed-aliraqi/laravel-media-uploader/actions\"><i"
  },
  {
    "path": "_ide_helper.php",
    "chars": 661,
    "preview": "<?php\n// @formatter:off\n\n/**\n * A helper file for Laravel, to provide autocomplete information to your IDE\n **\n * @autho"
  },
  {
    "path": "changelog.md",
    "chars": 4129,
    "preview": "# Release Notes for Laravel Media Uploader\n### v8.0.0\n* **Fixes**\n  - Remove support for BsForm package [2d17c04](https:"
  },
  {
    "path": "composer.json",
    "chars": 1077,
    "preview": "{\n    \"name\": \"ahmed-aliraqi/laravel-media-uploader\",\n    \"description\": \"This package used to upload files using larave"
  },
  {
    "path": "phpunit.xml",
    "chars": 695,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" bootstrap=\"vendor/"
  },
  {
    "path": "src/Config/laravel-media-uploader.php",
    "chars": 752,
    "preview": "<?php\n\nreturn [\n    /*\n     * Regenerate uploaded media after assign to model\n     */\n    'regenerate-after-assigning' ="
  },
  {
    "path": "src/Console/TemporaryClearCommand.php",
    "chars": 1072,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Console;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Entities\\TemporaryFil"
  },
  {
    "path": "src/Database/Migrations/2020_06_03_131044_create_temporary_files_table.php",
    "chars": 717,
    "preview": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Fa"
  },
  {
    "path": "src/Entities/Concerns/HasUploader.php",
    "chars": 2618,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Entities\\Concerns;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Entities\\Te"
  },
  {
    "path": "src/Entities/TemporaryFile.php",
    "chars": 1110,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Entities;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Spatie\\MediaLi"
  },
  {
    "path": "src/Http/Controllers/MediaController.php",
    "chars": 3459,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Http\\Controllers;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Entities\\Tem"
  },
  {
    "path": "src/Http/Requests/MediaRequest.php",
    "chars": 875,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Http\\Requests;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Rules\\MediaRule"
  },
  {
    "path": "src/Listeners/ProcessUploadedMedia.php",
    "chars": 6624,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Listeners;\n\nuse FFMpeg\\Format\\Audio\\Mp3;\nuse FFMpeg\\Format\\Video\\X264"
  },
  {
    "path": "src/Providers/EventServiceProvider.php",
    "chars": 561,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Providers;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Listeners\\ProcessUp"
  },
  {
    "path": "src/Providers/RouteServiceProvider.php",
    "chars": 1159,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Providers;\n\nuse Illuminate\\Foundation\\Support\\Providers\\RouteServiceP"
  },
  {
    "path": "src/Providers/UploaderServiceProvider.php",
    "chars": 2234,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Providers;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Console\\TemporaryCl"
  },
  {
    "path": "src/Resources/lang/ar/validation.php",
    "chars": 70,
    "preview": "<?php\n\nreturn [\n    'invalid' => 'قيمة حقل :attribute غير مدعومة',\n];\n"
  },
  {
    "path": "src/Resources/lang/en/validation.php",
    "chars": 72,
    "preview": "<?php\n\nreturn [\n    'invalid' => 'The :attribute is not supported.',\n];\n"
  },
  {
    "path": "src/Routes/api.php",
    "chars": 285,
    "preview": "<?php\n\nRoute::get('uploader/media', 'MediaController@index')->name('uploader.media.index');\nRoute::post('uploader/media/"
  },
  {
    "path": "src/Rules/MediaRule.php",
    "chars": 2415,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Rules;\n\nuse FFMpeg\\Exception\\RuntimeException;\nuse Illuminate\\Contrac"
  },
  {
    "path": "src/Support/FFmpegDriver.php",
    "chars": 691,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Support;\n\nuse FFMpeg\\FFMpeg;\nuse Illuminate\\Support\\Facades\\Config;\n\n"
  },
  {
    "path": "src/Support/Uploader.php",
    "chars": 1764,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Support;\n\nuse Illuminate\\Http\\UploadedFile;\nuse Illuminate\\Support\\St"
  },
  {
    "path": "src/Transformers/MediaResource.php",
    "chars": 3738,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Transformers;\n\nuse Illuminate\\Http\\Resources\\Json\\JsonResource;\nuse S"
  },
  {
    "path": "tests/Feature/UploaderFeatureTest.php",
    "chars": 1963,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Tests\\Feature;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Tests\\Models\\Bl"
  },
  {
    "path": "tests/Models/Blog.php",
    "chars": 673,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Tests\\Models;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Entities\\Concern"
  },
  {
    "path": "tests/TestCase.php",
    "chars": 1721,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Tests;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Providers\\UploaderServi"
  },
  {
    "path": "tests/Unit/UploaderUnitTest.php",
    "chars": 3163,
    "preview": "<?php\n\nnamespace AhmedAliraqi\\LaravelMediaUploader\\Tests\\Unit;\n\nuse AhmedAliraqi\\LaravelMediaUploader\\Entities\\Temporary"
  },
  {
    "path": "tests/config/laravel-media-uploader.php",
    "chars": 639,
    "preview": "<?php\n\nreturn [\n    'documents_mime_types' => [\n        'application/msword',\n        'application/vnd.openxmlformats-of"
  },
  {
    "path": "tests/config/media-library.php",
    "chars": 8593,
    "preview": "<?php\n\nreturn [\n\n    /*\n     * The disk on which to store added files and derived images by default. Choose\n     * one o"
  },
  {
    "path": "tests/database/migrations/2020_06_03_131044_create_temporary_files_table.php",
    "chars": 717,
    "preview": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Fa"
  },
  {
    "path": "tests/database/migrations/2020_06_03_131049_create_blogs_table.php",
    "chars": 589,
    "preview": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Fa"
  },
  {
    "path": "tests/database/migrations/2020_06_26_194753_create_media_table.php",
    "chars": 1210,
    "preview": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Fa"
  }
]

About this extraction

This page contains the full source code of the ahmed-aliraqi/laravel-media-uploader GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 37 files (65.2 KB), approximately 17.2k tokens, and a symbol index with 89 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!