├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── _vApp
├── .htaccess
├── add.vue
├── assets
│ └── style.scss
├── components
│ ├── Drawer.vue
│ ├── File.vue
│ ├── GeoComplete.vue
│ ├── Header.vue
│ ├── LeftColumn.vue
│ ├── Listing.vue
│ ├── MediaDialog.vue
│ ├── Paginate.vue
│ ├── RichTextarea.vue
│ ├── SEO.vue
│ └── Table.vue
├── css
│ ├── app.scss
│ └── main.css
├── pages
│ ├── Index.vue
│ ├── layout.vue
│ ├── login.vue
│ ├── page
│ │ ├── add.vue
│ │ ├── index.vue
│ │ └── list.vue
│ ├── post
│ │ ├── add.vue
│ │ ├── index.vue
│ │ └── list.vue
│ └── postCategory
│ │ ├── add.vue
│ │ └── list.vue
├── plugins
│ ├── Axios.js
│ └── Vuetify.js
├── routes.js
├── store
│ └── index.js
└── vApp.js
├── composer.json
├── config
├── adlara.php
└── auth.php
├── controllers
├── AdminController.php
└── AdminControllers
│ ├── AdminUserController.php
│ ├── MediaController.php
│ ├── PageController.php
│ ├── PostCategoryController.php
│ └── PostController.php
├── database
├── factories
│ ├── PostCategoryFactory.php
│ └── PostFactory.php
├── migrations
│ ├── 2014_10_12_100000_create_password_resets_table.php
│ ├── 2018_01_18_112915_create_users_table.php
│ ├── 2018_01_19_053208_create_admin_users_table.php
│ ├── 2018_01_19_053208_create_page_table.php
│ ├── 2018_01_19_053514_create_admin_password_reset_table.php
│ ├── 2018_01_19_054151_create_component_table.php
│ ├── 2019_01_21_051412_post_category.php
│ ├── 2019_01_21_051423_post.php
│ ├── 2019_01_21_051441_post_category_assign.php
│ ├── 2019_01_21_051657_media.php
│ └── 2019_01_21_051833_media_image_size.php
└── seeds
│ └── PostSeeder.php
├── middleware
├── AdminUser.php
└── VerifyCSRFToken.php
├── objects
├── AdminUser.php
├── IDB.php
├── Media.php
├── MediaImageSize.php
├── Page.php
├── Post.php
├── PostCategory.php
└── PostCategoryAssigned.php
├── package.json
├── providers
├── RouteServiceProvider.php
└── kernel.php
├── routes
└── admin.php
├── src
├── Bootable.php
├── RoutesProvider.php
└── helper.php
├── views
├── admin
│ └── dashboard.blade.php
└── front
│ └── welcome.blade.php
└── webpack.mix.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package-lock.json
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | rvm:
3 | - 7.2
4 | - 7.1
5 | - 7.0
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Jigesh Raval
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AdLara Bootstrap
2 |
3 | Laravel VueJS/Vuetify Powered admin, booting up required components that separates Admin and Front and provides rich tools such as Media Library
4 |
5 | # What will this bootstraping do? (List of Functions)
6 |
7 | - Ready to go Laravel/Vue/Vuetify Admin
8 | - Sample Blog, ready to extend or use
9 | - Provides Multiple Authentication for the Front end and the Back end (Admin)
10 | - Creates Separate Controllers Folders (AdminControllers and FrontControllers)
11 | - Separate Route files, for admin -> admin.php and for front-end web.php
12 | - Separte views for admin and front end so that the application remains organized and flows well
13 | - Media Management: Manage static assets of your application through database. It provides boiler plate to record every upload in the database. Of course, it has Rich Media Library built with VueJs (https://vuejs.org) and Uppy.io (https://uppy.io/).
14 | - The media library reduces the time consuming tasks of creating uploading functionality and manage it and speed-up the other tasks
15 | - Image resizing (Powered by http://image.intervention.io/)
16 |
17 | # Installation
18 |
19 | ``` bash
20 | composer require jigeshraval/laravel-admin-dashboard
21 | ```
22 |
23 | # Installation Steps
24 |
25 | 1. composer require jigeshraval/laravel-admin-dashboard
26 | 2. Add "JigeshRaval\Bootable::class" in the providers array in config/app.php
27 | 3. Make sure database credentials are added in .env file and database is connected with the Laravel Application
28 | 4. Delete all the migrations from database/migrations folder
29 | 5. php artisan vendor:publish --tag=adlarafullsetup --force
30 | 6. php artisan migrate
31 | 7. php artisan storage:link (For Media and Static Resources)
32 | 8. npm install
33 | 9. npm run watch (for the dev mode) or npm run production (if you're ready to deploy)
34 | 10. Now go to http://127.0.0.1:8000/admin and you will be able to see login screen, use jigesh@jigeshraval.com and password: adlaraera1 for your initial login
35 |
36 | # This step is only if you want database seeding to be done
37 | 11. php artisan db:seed --class=PostSeeder
38 |
39 | # Documentation
40 |
41 | - https://jigeshraval.com/en/blog/laravel-admin-dashboard
42 |
--------------------------------------------------------------------------------
/_vApp/.htaccess:
--------------------------------------------------------------------------------
1 |
11 |
19 |
20 |
21 |
16 |
17 | Action
18 |
22 |
42 |
26 |
40 |
41 |
43 |
83 |
84 |
44 |
56 |
57 |
82 |
39 |
43 |
7 |
15 |
16 |
17 |
12 |
13 | Action
14 |
18 |
34 |
22 |
32 |
33 |
35 |
65 |
66 |
36 | {{ d[index] }}
37 |
38 |
39 |
64 | AdLara Admin
5 | 3.0.4
6 |
' . $faker->paragraph(10) . '
'; 18 | } 19 | 20 | return [ 21 | 'title' => $title, 22 | 'url' => \Str::slug($title), 23 | 'content' => $paragraph, 24 | 'meta_title' => $title, 25 | 'meta_description' => $title, 26 | 'post_date' => date('Y-m-d h:i:s'), 27 | 'published' => 0 28 | ]; 29 | }); 30 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 23 | $table->string('email', 250)->index(); 24 | $table->string('token'); 25 | $table->timestamp('created_at')->nullable(); 26 | $table->engine = 'InnoDB'; 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::hasTable('password_resets'); 38 | Schema::dropIfExists('password_resets'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2018_01_18_112915_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('email'); 20 | $table->string('password'); 21 | $table->string('mobile')->nullable(); 22 | $table->rememberToken(); 23 | $table->timestamps(); 24 | $table->softDeletes(); 25 | $table->engine = 'InnoDB'; 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::hasTable('users'); 37 | Schema::dropIfExists('users'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2018_01_19_053208_create_admin_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 19 | $table->string('name'); 20 | $table->string('email'); 21 | $table->string('password'); 22 | $table->string('mobile')->nullable(); 23 | $table->rememberToken(); 24 | $table->timestamps(); 25 | $table->softDeletes(); 26 | $table->engine = 'InnoDB'; 27 | }); 28 | 29 | $data = [ 30 | 'name' => 'Jigesh Raval', 31 | 'email' => 'jigesh@jigeshraval.com', 32 | 'password' => Hash::make('adlaraera1') 33 | ]; 34 | \Illuminate\Support\Facades\DB::table('admin_users')->insert($data); 35 | } 36 | 37 | /** 38 | * Reverse the migrations. 39 | * 40 | * @return void 41 | */ 42 | public function down() 43 | { 44 | Schema::dropIfExists('admin_users'); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /database/migrations/2018_01_19_053208_create_page_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->longText('content')->nullable(); 20 | $table->string('url')->nullable(); 21 | $table->integer('status')->unsigned()->default(0); 22 | $table->integer('id_featured_image')->unsigned()->nullable(); 23 | $table->integer('id_lang')->unsigned()->default(1); 24 | $table->string('meta_title')->nullable(); 25 | $table->string('meta_description')->nullable(); 26 | $table->timestamps(); 27 | $table->softDeletes(); 28 | $table->engine = 'InnoDB'; 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('page'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2018_01_19_053514_create_admin_password_reset_table.php: -------------------------------------------------------------------------------- 1 | string('email', 250)->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | $table->engine = 'InnoDB'; 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('admin_password_reset'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2018_01_19_054151_create_component_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('table'); 20 | $table->string('variable'); 21 | $table->string('slug'); 22 | $table->string('controller'); 23 | $table->integer('is_front_create')->unsigned(); 24 | $table->integer('is_front_view')->unsigned(); 25 | $table->integer('is_front_list')->unsigned(); 26 | $table->integer('is_admin_create')->unsigned(); 27 | $table->integer('is_admin_list')->unsigned(); 28 | $table->integer('is_admin_delete')->unsigned(); 29 | $table->integer('is_login_needed')->unsigned()->nullable(); 30 | $table->integer('is_meta_needed')->unsigned(); 31 | $table->timestamps(); 32 | $table->softDeletes(); 33 | $table->engine = 'InnoDB'; 34 | }); 35 | 36 | Schema::create('component_fields', function (Blueprint $table) { 37 | $table->increments('id'); 38 | $table->integer('id_component')->unsigned(); 39 | $table->string('field_name'); 40 | $table->string('field_text'); 41 | $table->string('column_type'); 42 | $table->string('input_type'); 43 | $table->integer('use_in_listing')->unsigned(); 44 | $table->integer('is_fillable')->unsigned(); 45 | $table->integer('required')->unsigned(); 46 | $table->integer('default')->nullable(); 47 | $table->string('class')->nullable(); 48 | $table->string('relationship_type')->nullable(); 49 | $table->string('reference_name')->nullable(); 50 | $table->string('relational_component_name')->nullable(); 51 | $table->string('foreign_key')->nullable(); 52 | $table->string('local_key')->nullable(); 53 | $table->string('mediator_table')->nullable(); 54 | $table->string('mediator_table_key')->nullable(); 55 | $table->timestamps(); 56 | $table->softDeletes(); 57 | $table->engine = 'InnoDB'; 58 | }); 59 | } 60 | 61 | /** 62 | * Reverse the migrations. 63 | * 64 | * @return void 65 | */ 66 | public function down() 67 | { 68 | Schema::dropIfExists('component'); 69 | Schema::dropIfExists('component_fields'); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /database/migrations/2019_01_21_051412_post_category.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('title')->default()->nullable(); 19 | $table->string('url')->default()->nullable(); 20 | $table->integer('id_media')->default()->nullable(); 21 | $table->integer('id_lang')->default()->nullable(); 22 | $table->integer('status')->default()->nullable(); 23 | $table->string('meta_title')->default()->nullable(); 24 | $table->string('meta_description')->default()->nullable(); 25 | $table->timestamps(); 26 | $table->softDeletes(); 27 | $table->engine = 'InnoDB'; 28 | }); 29 | } 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::dropIfExists('post_category'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2019_01_21_051423_post.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('title')->nullable(); 19 | $table->string('url')->nullable(); 20 | $table->longText('content')->nullable(); 21 | $table->integer('id_website')->nullable(); 22 | $table->integer('id_media')->nullable(); 23 | $table->tinyInteger('id_author')->nullable(); 24 | $table->tinyInteger('published')->default(0)->nullable(); 25 | $table->date('post_date')->useCurrent(); 26 | $table->string('meta_title')->nullable(); 27 | $table->string('meta_description')->nullable(); 28 | $table->timestamps(); 29 | $table->softDeletes(); 30 | $table->engine = 'InnoDB'; 31 | }); 32 | } 33 | 34 | /** 35 | * Reverse the migrations. 36 | * 37 | * @return void 38 | */ 39 | public function down() 40 | { 41 | Schema::dropIfExists('post'); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /database/migrations/2019_01_21_051441_post_category_assign.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('id_post')->default()->nullable(); 19 | $table->string('id_category')->default()->nullable(); 20 | $table->integer('id_lang')->default()->nullable(); 21 | $table->timestamps(); 22 | $table->softDeletes(); 23 | $table->engine = 'InnoDB'; 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('post_category_assign'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2019_01_21_051657_media.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name')->default()->nullable(); 19 | $table->string('path')->default()->nullable(); 20 | $table->string('media_type')->default()->nullable(); 21 | $table->string('type')->default()->nullable(); 22 | $table->string('title')->default()->nullable(); 23 | $table->string('format')->default()->nullable(); 24 | $table->integer('status')->unsigned()->default()->nullable(); 25 | $table->timestamps(); 26 | $table->softDeletes(); 27 | $table->engine = 'InnoDB'; 28 | }); 29 | } 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::dropIfExists('media'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2019_01_21_051833_media_image_size.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->integer('id_media')->unsigned()->default()->nullable(); 19 | $table->string('size')->nullable(); 20 | $table->smallInteger('webp')->default(0)->nullable(); 21 | $table->timestamps(); 22 | $table->softDeletes(); 23 | $table->engine = 'InnoDB'; 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('media_image_size'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/seeds/PostSeeder.php: -------------------------------------------------------------------------------- 1 | create() 24 | ->each(function ($post) { 25 | $post->post_category()->save(factory(App\Objects\PostCategory::class)->make()); 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /middleware/AdminUser.php: -------------------------------------------------------------------------------- 1 | user()) { 14 | 15 | $admin_route = config('adlara.admin_route') . '/app'; 16 | 17 | if (!request()->ajax()) { 18 | 19 | return redirect($admin_route . '/login'); 20 | 21 | } 22 | 23 | $data = array( 24 | 'status' => 'redirect', 25 | 'message' => url($admin_route . '/login') 26 | ); 27 | 28 | echo json_encode($data); 29 | exit(); 30 | 31 | } 32 | 33 | return $next($request); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /middleware/VerifyCSRFToken.php: -------------------------------------------------------------------------------- 1 | hasMany('App\Objects\Post', 'id_author'); 36 | } 37 | 38 | public function getAdminUser($id = null) 39 | { 40 | if ($id) { 41 | return $this->find($id); 42 | } 43 | 44 | if (Auth::guard('admin')->check()) { 45 | return Auth::guard('admin')->user(); 46 | } 47 | 48 | return $this; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /objects/IDB.php: -------------------------------------------------------------------------------- 1 | status = (int) $status; 13 | $this->save(); 14 | } 15 | 16 | public function updateColumn($column, $val) 17 | { 18 | $this->$column = (int) $val; 19 | $this->save(); 20 | } 21 | 22 | public function getSql() 23 | { 24 | $builder = $this->getBuilder(); 25 | $sql = $builder->toSql(); 26 | foreach($builder->getBindings() as $binding) 27 | { 28 | $value = is_numeric($binding) ? $binding : "'".$binding."'"; 29 | $sql = preg_replace('/\?/', $value, $sql, 1); 30 | } 31 | return $sql; 32 | } 33 | 34 | public function check($key, $val) 35 | { 36 | $data = $this->where($key, $val); 37 | if (isset($data->id) && $data->id) { 38 | return true; 39 | } 40 | 41 | return false; 42 | } 43 | 44 | public function findByURL($url) 45 | { 46 | $this->primaryKey = 'url'; 47 | return $this->find($url); 48 | } 49 | 50 | public function joinMediaURL($size1 = null, $size2 = null, $webp = true) 51 | { 52 | $obj = $this; 53 | $obj->url = $this->retrieve($size1, $size2, $webp); 54 | return $obj; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /objects/Media.php: -------------------------------------------------------------------------------- 1 | disk = config('filesystems.default'); 31 | } 32 | 33 | public function saveImageSize() 34 | { 35 | if (!$this->id) { 36 | return; 37 | } 38 | 39 | $mis = new MediaImageSize; 40 | $size_folder = trim($this->size1) . trim($this->size2); 41 | 42 | $size_db = $mis->where('id_media', $this->id) 43 | ->where('size', $size_folder) 44 | ->first(); 45 | 46 | if ($size_db) { 47 | return; 48 | } 49 | 50 | $mis->id_media = $this->id; 51 | $mis->size = $size_folder; 52 | $mis->save(); 53 | } 54 | 55 | public function saveWebpImageSize() 56 | { 57 | if (!$this->id) { 58 | return; 59 | } 60 | 61 | $mis = new MediaImageSize; 62 | $size_folder = trim($this->size1) . trim($this->size2); 63 | 64 | $size_db = $mis->where('id_media', $this->id) 65 | ->where('size', $size_folder) 66 | ->where('webp', 1) 67 | ->first(); 68 | 69 | if ($size_db) { 70 | return; 71 | } 72 | 73 | $mis->id_media = $this->id; 74 | $mis->size = $size_folder; 75 | $mis->webp = 1; 76 | $mis->save(); 77 | } 78 | 79 | public function getOriginalImageURL() 80 | { 81 | if (!$this->path) { 82 | //Log here 83 | } 84 | 85 | $disk = $this->disk; 86 | $storage = Storage::disk($disk); 87 | 88 | if (!$this->webp_path) { 89 | $this->generateWebpImage(); 90 | } 91 | 92 | return [ 93 | 'webp' => $storage->url($this->webp_path), 94 | 'jpg' => $storage->url($this->path) 95 | ]; 96 | } 97 | 98 | public function getStorageFolder($webp = false) 99 | { 100 | $type = $this->type; 101 | $folder = ''; 102 | 103 | // if (config('filesystems.cloud') == 'local') { 104 | // $folder .= 'app/'; 105 | // } 106 | 107 | if (!$webp) { 108 | 109 | $folder = 'public/image/jpg'; 110 | 111 | } else { 112 | 113 | $folder = 'public/image/webp'; 114 | 115 | } 116 | 117 | if ($this->size1 && $this->size2) { 118 | $folder .= '/' . trim($this->size1) . trim($this->size2); 119 | } 120 | 121 | return $folder . '/'; 122 | } 123 | 124 | // This function is temporary to move files f 125 | public function getOldStorageFolder() 126 | { 127 | $type = $this->type; 128 | $folder = ''; 129 | 130 | // if (config('filesystems.cloud') == 'local') { 131 | // $folder .= 'app/'; 132 | // } 133 | 134 | $folder = 'public/image'; 135 | 136 | if ($this->size1 && $this->size2) { 137 | $folder .= '/' . trim($this->size1) . trim($this->size2); 138 | } 139 | 140 | return $folder . '/'; 141 | } 142 | 143 | public function makeWebpImage($image_path = null, $max_size) 144 | { 145 | $pathinfo = pathinfo($this->path); 146 | $ext = $pathinfo['extension']; 147 | $filename = $pathinfo['filename']; 148 | $new_name = $filename . '.webp'; 149 | 150 | if ($ext == 'webp') { 151 | return; 152 | } 153 | 154 | $this->moveImageToLocalStorage(); 155 | 156 | $storage = Storage::disk('local'); 157 | 158 | $localPath = storage_path('app/public/image/' . $new_name); 159 | $bytes = $storage->size($this->path); 160 | 161 | $image_path = $storage->path($this->path); 162 | 163 | if ($bytes) { 164 | 165 | $size_in_kb = ceil($bytes/1000); 166 | 167 | if ($size_in_kb > $max_size) { 168 | 169 | //Optimizing image for its size and replacing at its destination 170 | $this->optimizeImage($image_path, false); 171 | 172 | } 173 | 174 | } 175 | 176 | $image_type = image_type_to_mime_type(exif_imagetype($image_path)); 177 | 178 | if ($image_type == 'image/png') { 179 | $img1 = imagecreatefrompng($image_path); 180 | } 181 | 182 | if ($image_type == 'image/jpg' || $image_type == 'image/jpeg') { 183 | $img1 = imagecreatefromjpeg($image_path); 184 | imagepalettetotruecolor($img1); 185 | } 186 | 187 | if ($image_type == 'image/gif') { 188 | $img1 = imagecreatefromgif($image_path); 189 | } 190 | 191 | if ( 192 | $image_type == 'image/png' || 193 | $image_type == 'image/jpeg' || 194 | $image_type == 'image/jpg' || 195 | $image_type == 'image/gif' 196 | ) { 197 | imagepalettetotruecolor($img1); 198 | $create = imagewebp($img1, $localPath, 100); 199 | imagedestroy($img1); 200 | 201 | $nameinfo = pathinfo($this->name); 202 | $new_real_name = $pathinfo['filename'] . '.webp'; 203 | 204 | $this->name = $new_real_name; 205 | $this->realname = $new_real_name; 206 | $this->path = 'image/' . $new_name; 207 | $this->format = 'webp'; 208 | $this->save(); 209 | $this->localStorageToS3Storage(); 210 | } 211 | 212 | } 213 | 214 | public function retrieve($size1 = null, $size2 = null, $webp = false) 215 | { 216 | if ($this->type == 'image') { 217 | if (!$size1 || !$size2) { 218 | return $this->getOriginalImageURL(); 219 | } 220 | 221 | return $this->resizeImage($size1, $size2, $webp); 222 | } 223 | 224 | if ($this->format == 'embeded') { 225 | return $this->name; 226 | } 227 | 228 | $disk = $this->disk; 229 | $url = Storage::disk($disk)->url($this->path); 230 | return $url; 231 | } 232 | 233 | public function getSizeFolder() 234 | { 235 | if (!$this->size1 || !$this->size2) { 236 | return; 237 | } 238 | 239 | return $this->size1 . $this->size2; 240 | } 241 | 242 | /* 243 | | 244 | | Variable $filePath is the key variable which will be used to define the path 245 | | 246 | */ 247 | 248 | public function resizeImage($size1, $size2, $webp = false) 249 | { 250 | $this->size1 = $size1; 251 | $this->size2 = $size2; 252 | 253 | //Cleaning name 254 | $this->cleanName($this->name); 255 | 256 | if ($webp) { 257 | 258 | return [ 259 | 'jpg' => $this->resizeOtherImage(), 260 | 'webp' => $this->resizeWebpImage() 261 | ]; 262 | 263 | } else { 264 | 265 | return $this->resizeOtherImage(); 266 | 267 | } 268 | } 269 | 270 | protected function getFileNameWithoutExtension($file) 271 | { 272 | $name = pathinfo($file); 273 | return $name['filename']; 274 | } 275 | 276 | protected function getFileExtension($file) 277 | { 278 | $name = pathinfo($file); 279 | return $name['extension']; 280 | } 281 | 282 | 283 | protected function resizeWebpImage() 284 | { 285 | $disk = $this->disk; 286 | $storage = Storage::disk($disk); 287 | 288 | $resizeNotRequireFormats = [ 289 | 'svg+xml', 290 | 'svg', 291 | 'xml' 292 | ]; 293 | 294 | // If unsupported format is there, then it should not resize 295 | if (in_array($this->format, $resizeNotRequireFormats)) { 296 | 297 | return $storage->url($this->path); 298 | 299 | } 300 | 301 | $folder = $this->getStorageFolder(true); 302 | 303 | //File path means folder + original path (i.e. 250250/filename.jpg) & $this->path is the real path 304 | $filePath = $folder . $this->getFileNameWithoutExtension($this->name) . '.webp'; 305 | 306 | // If file exists then return it 307 | if ($this->sizeTableHasTheWebpImage()) { 308 | // if ($storage->exists($filePath)) { 309 | 310 | // $this->moveImage($filePath); 311 | 312 | $url = $storage->url($filePath); 313 | 314 | return $url; 315 | 316 | } 317 | 318 | if (!$this->webp_path) { 319 | $this->generateWebpImage(); 320 | } 321 | 322 | //Image content used to resize image through intervention 323 | $storedImage = $storage->get($this->webp_path); 324 | 325 | if (!$storedImage) { 326 | 327 | $mesage = 'Content missing for Image (Webp) ID - ' . $this->id; 328 | 329 | triggerException($message, E_USER_WARNING); 330 | 331 | return ''; 332 | } 333 | 334 | // Since we have to resize from the webp_format, we have to move file to the local storage to create binary data from the given path 335 | 336 | // Moving image to local storage 337 | $this->moveWebpImageToLocalStorage(); 338 | 339 | // getting path of the moved image 340 | $local_path = Storage::disk('local')->path($this->webp_path); 341 | 342 | // Binary data of webp image 343 | $storedImage = imagecreatefromwebp($local_path); 344 | 345 | // Since the image processing is done, we should delete it to clear space 346 | Storage::disk('local')->delete($this->webp_path); 347 | 348 | //Making it ready for resizing with Intervention 349 | $img = Image::make($storedImage); 350 | $img->resize($this->size1, $this->size2, function ($constraint) { 351 | $constraint->aspectRatio(); 352 | }); 353 | 354 | // We need a path where resized image can be stored 355 | if ($this->disk == 's3') { 356 | 357 | $file = storage_path('app/tmp/webp/' . $this->getFileNameWithoutExtension($this->name) . '.webp'); //tmp path 358 | 359 | } else { 360 | 361 | $localStorage = Storage::disk('local'); 362 | $localPath = $localStorage->path(''); 363 | $localFolder = $localPath . $folder; 364 | 365 | if (!file_exists($localFolder)) { 366 | 367 | $localStorage->makeDirectory($folder); 368 | 369 | } 370 | 371 | $file = storage_path('app/' . $filePath); 372 | 373 | } 374 | 375 | //Finally saving a file 376 | $img->save($file); 377 | 378 | //Now move local file to s3 bucket 379 | if ($this->disk == 's3') { 380 | 381 | $fetchTmpFile = Storage::disk('local')->get('tmp/webp/' . $this->getFileNameWithoutExtension($this->name) . '.webp'); 382 | 383 | //Moving local file to s3 bucket after resizing 384 | $storage->put($filePath, $fetchTmpFile, 'public'); 385 | 386 | //delete local file 387 | Storage::disk('local')->delete('tmp/webp/' . $this->getFileNameWithoutExtension($this->name) . '.webp'); 388 | 389 | } 390 | 391 | $this->saveWebpImageSize(); 392 | return $storage->url($filePath); 393 | } 394 | 395 | protected function moveImage($newPath) 396 | { 397 | $storage = Storage::disk($this->disk); 398 | $filePath = $this->getOldStorageFolder() . $this->name; 399 | 400 | if ($storage->exists($filePath) && !$storage->exists($newPath)) { 401 | 402 | $storage->move($filePath, $newPath); 403 | 404 | } 405 | 406 | } 407 | 408 | protected function resizeOtherImage() 409 | { 410 | $disk = $this->disk; 411 | $storage = Storage::disk($disk); 412 | 413 | $resizeNotRequireFormats = [ 414 | 'svg+xml', 415 | 'svg', 416 | 'xml' 417 | ]; 418 | 419 | // If unsupported format is there, then it should not resize 420 | if (in_array($this->format, $resizeNotRequireFormats)) { 421 | 422 | return $storage->url($this->path); 423 | 424 | } 425 | 426 | $folder = $this->getStorageFolder(); 427 | 428 | //File path means folder + original path (i.e. 250250/filename.jpg) & $this->path is the real path 429 | $filePath = $folder . $this->name; 430 | 431 | // If file exists then return it 432 | if ($this->sizeTableHasTheImage()) { 433 | 434 | // if ($storage->exists($filePath)) { 435 | 436 | // $this->moveImage($filePath); 437 | 438 | $url = $storage->url($filePath); 439 | return $url; 440 | 441 | } 442 | 443 | //Image content used to resize image through intervention 444 | if ($storage->exists($this->path)) { 445 | 446 | $mime = $storage->mimeType($this->path); 447 | 448 | if (!in_array($mime, [ 449 | 'image/jpeg', 450 | 'image/png', 451 | 'image/bmp', 452 | 'image/gd2', 453 | 'image/xbm', 454 | 'image/xpm', 455 | 'image/webp' 456 | ])) { 457 | 458 | return notFoundImage(); 459 | 460 | } 461 | 462 | $storedImage = $storage->get($this->path); 463 | 464 | } else { 465 | 466 | $message = 'Content missing for Image ID - ' . $this->id; 467 | 468 | // triggerException($message, E_USER_WARNING); 469 | 470 | return notFoundImage(); 471 | 472 | } 473 | 474 | //Making it ready for resizing with Intervention 475 | $img = Image::make($storedImage); 476 | $img->resize($this->size1, $this->size2, function ($constraint) { 477 | $constraint->aspectRatio(); 478 | }); 479 | 480 | // We need a path where resized image can be stored 481 | if ($this->disk == 's3') { 482 | 483 | $file = storage_path('app/tmp/' . $this->name); //tmp path 484 | 485 | } else { 486 | 487 | $localStorage = Storage::disk('local'); 488 | $localPath = $localStorage->path(''); 489 | $localFolder = $localPath . $folder; 490 | 491 | if (!file_exists($localFolder)) { 492 | 493 | $localStorage->makeDirectory($folder); 494 | 495 | } 496 | 497 | $file = storage_path('app/' . $filePath); 498 | 499 | } 500 | 501 | //Finally saving a file 502 | $img->save($file); 503 | 504 | //Now move local file to s3 bucket 505 | if ($this->disk == 's3') { 506 | 507 | $fetchTmpFile = Storage::disk('local')->get('tmp/' . $this->name); 508 | 509 | //Moving local file to s3 bucket after resizing 510 | $storage->put($filePath, $fetchTmpFile, 'public'); 511 | 512 | //delete local file 513 | Storage::disk('local')->delete('tmp/' . $this->name); 514 | 515 | } 516 | 517 | $this->saveImageSize(); 518 | return $storage->url($filePath); 519 | } 520 | 521 | public function moveImageToLocalStorage() 522 | { 523 | //Check if file exists locally 524 | $exists = Storage::disk('local')->exists($this->path); 525 | 526 | if (!$exists) { 527 | 528 | if (!Storage::disk('s3')->exists($this->path)) { 529 | pre($this); 530 | } 531 | 532 | //Fetch content from the s3 bucket 533 | $cloud_file = Storage::disk('s3')->get($this->path); 534 | 535 | //storing the file locally 536 | $test = Storage::disk('local')->put($this->path, $cloud_file, 'public'); 537 | } 538 | } 539 | 540 | protected function moveWebpImageToLocalStorage() 541 | { 542 | //Check if file exists locally 543 | $exists = Storage::disk('local')->exists($this->webp_path); 544 | 545 | if (!$exists) { 546 | //Fetch content from the s3 bucket 547 | $cloud_file = Storage::disk('s3')->get($this->webp_path); 548 | 549 | //storing the file locally 550 | $test = Storage::disk('local')->put($this->webp_path, $cloud_file, 'public'); 551 | } 552 | } 553 | 554 | public function compress($source, $destination, $quality = 90) 555 | { 556 | $info = getimagesize($source); 557 | 558 | if ($info['mime'] == 'image/jpeg') { 559 | $image = imagecreatefromjpeg($source); 560 | } 561 | 562 | elseif ($info['mime'] == 'image/gif') { 563 | $image = imagecreatefromgif($source); 564 | } 565 | 566 | elseif ($info['mime'] == 'image/png') { 567 | $image = imagecreatefrompng($source); 568 | } 569 | 570 | imagejpeg($image, $destination, $quality); 571 | imagedestroy($image); 572 | 573 | return $destination; 574 | } 575 | 576 | public function optimizeImage($src_path = null, $sync_image = false) 577 | { 578 | if (!$this->id) { 579 | return; 580 | } 581 | 582 | if ($this->disk == 's3' && $sync_image) { 583 | $this->moveImageToLocalStorage(); 584 | } 585 | 586 | if (!$src_path) { 587 | 588 | $src = $src_path; 589 | $dest = $src_path; 590 | 591 | } else { 592 | 593 | $src = storage_path('app/' . $this->path); 594 | $dest = storage_path('app/' . $this->path); 595 | 596 | } 597 | 598 | 599 | $this->compress($src, $dest, 90); 600 | 601 | $this->localStorageToS3Storage(); 602 | 603 | \Log::info('Image optimized - ' . $this->id); 604 | } 605 | 606 | public function localStorageToS3Storage($delete = true) 607 | { 608 | //Fetching local file 609 | $locallyStoredFile = Storage::disk('local')->get($this->path); 610 | 611 | //Putting local file into s3 bucket 612 | Storage::disk('s3')->put($this->path, $locallyStoredFile, 'public'); 613 | 614 | if ($delete) { 615 | //Deleting local file 616 | Storage::disk('local')->delete($this->path); 617 | } 618 | 619 | return Storage::disk('s3')->url($this->path); 620 | } 621 | 622 | public function moveLocalWebpImagetoS3Storage($delete = true) 623 | { 624 | if (!$this->webp_path) { 625 | return; 626 | } 627 | 628 | //Fetching local file 629 | $locallyStoredFile = Storage::disk('local')->get($this->webp_path); 630 | 631 | //Putting local file into s3 bucket 632 | $putted = Storage::disk('s3')->put($this->webp_path, $locallyStoredFile, 'public'); 633 | 634 | if ($delete) { 635 | //Deleting local file 636 | Storage::disk('local')->delete($this->webp_path); 637 | } 638 | } 639 | 640 | public function sizeTableHasTheImage() 641 | { 642 | if ( 643 | !$this->size1 || 644 | !$this->size2 || 645 | !$this->id || 646 | $this->force_resize 647 | ) { 648 | return false; //Log 649 | } 650 | 651 | $size = $this->size1 . $this->size2; 652 | return \App\Objects\MediaImageSize::where('size', $size) 653 | ->where('id_media', $this->id) 654 | ->first(); 655 | } 656 | 657 | public function sizeTableHasTheWebpImage() 658 | { 659 | if ( 660 | !$this->size1 || 661 | !$this->size2 || 662 | !$this->id || 663 | $this->force_webp_resize 664 | ) { 665 | return false; //Log 666 | } 667 | 668 | $size = $this->size1 . $this->size2; 669 | 670 | return \App\Objects\MediaImageSize::where('size', $size) 671 | ->where('webp', 1) 672 | ->where('id_media', $this->id) 673 | ->first(); 674 | } 675 | 676 | private function storeMedia($file, $folder, $disk, $type) 677 | { 678 | if ($type == 'image') { 679 | 680 | $size = ceil($file->getSize()/1000); 681 | 682 | if ($size >= 200) { 683 | 684 | $tmpStoredFilePath = $file->store($folder, 'local'); 685 | 686 | $source = Storage::disk('local')->path($tmpStoredFilePath); 687 | $destination = $source; 688 | 689 | $this->compress($source, $destination); 690 | 691 | if (config('filesystems.default') == 's3') { 692 | 693 | $tmp_file = new File(Storage::disk('local')->path($tmpStoredFilePath)); 694 | 695 | $path = Storage::disk('s3')->putFile($folder, $tmp_file, 'public'); 696 | 697 | Storage::disk('local')->delete($tmpStoredFilePath); 698 | 699 | } else { 700 | 701 | $path = $tmpStoredFilePath; 702 | 703 | } 704 | 705 | return $path; 706 | } 707 | 708 | } 709 | 710 | return $file->storePublicly($folder, $disk); 711 | } 712 | 713 | public function store($file) 714 | { 715 | $disk = $this->disk; 716 | $name = $file->getClientOriginalName(); 717 | $format = $file->getClientMimeType(); 718 | $type = explode('/', $format)[0]; 719 | 720 | if ($type == 'image' && $format != 'image/webp') { 721 | 722 | $folder = 'public/' . $type . '/jpg'; 723 | 724 | } else { 725 | 726 | $folder = 'public/' . $format; 727 | 728 | } 729 | 730 | //Storing file 731 | $storedFilePath = $this->storeMedia( 732 | $file, 733 | $folder, 734 | $disk, 735 | $type 736 | ); 737 | 738 | $error = $file->getError(); 739 | 740 | if ($error) { 741 | return array( 742 | 'status' => 'error', 743 | 'message' => $error 744 | ); 745 | } 746 | 747 | if (!$storedFilePath) { 748 | return array( 749 | 'status' => 'error', 750 | 'message' => 'File ' . $name . ' could not be uploaded' 751 | ); 752 | } 753 | 754 | $url = Storage::disk($disk)->url($storedFilePath); 755 | 756 | $this->name = $name; 757 | $this->path = $storedFilePath; 758 | 759 | if ($format == 'image/webp') { 760 | 761 | $this->webp_path = $storedFilePath; 762 | 763 | } 764 | 765 | $this->type = $type; 766 | $this->format = $format; 767 | $this->save(); 768 | $this->name = $this->id . '-' . $this->name; 769 | $this->save(); 770 | 771 | if ($type == 'image') { 772 | 773 | $this->imageMirroring(); 774 | $this->generateCommonSizes(); 775 | 776 | } 777 | 778 | return array( 779 | 'url' => $url, 780 | 'id' => $this->id 781 | ); 782 | } 783 | 784 | private function generateCommonSizes() 785 | { 786 | $this->retrieve(250, 250); 787 | } 788 | 789 | private function imageMirroring() 790 | { 791 | if (config('filesystems.default') != 's3') { 792 | return; 793 | } 794 | 795 | if ($this->format == 'webp' || $this->format == 'image/webp') { 796 | 797 | $this->generateJpgImage(); 798 | 799 | } else { 800 | 801 | $this->generateWebpImage(); 802 | 803 | } 804 | } 805 | 806 | private function storage() 807 | { 808 | return Storage::disk($this->disk); 809 | } 810 | 811 | public function cleanName($name) 812 | { 813 | $pathinfo = pathinfo($name); 814 | $ext = $pathinfo['extension']; 815 | $filename = preg_replace('/[^\w\-]/', '', $pathinfo['filename']); 816 | $new_name = $filename . '.' . $ext; 817 | 818 | if ($new_name != $name) { 819 | $this->name = $new_name; 820 | $this->save(); 821 | 822 | //Delete sizes 823 | $mis = MediaImageSize::where('id_media', $this->id) 824 | ->delete(); 825 | } 826 | } 827 | 828 | public function adjustPathForWebp() 829 | { 830 | $this->moveImageToLocalStorage(); 831 | 832 | $image = storage_path('app/' . $this->path); 833 | 834 | $pathinfo = pathinfo($this->path); 835 | $ext = $pathinfo['extension']; 836 | $filename = $pathinfo['filename']; 837 | 838 | $local_jpg_path = storage_path('app/public/image/jpg/' . $filename . '.jpg'); 839 | $local_webp_path = storage_path('app/public/image/webp/' . $filename . '.webp'); 840 | 841 | $format = image_type_to_mime_type(exif_imagetype($image)); 842 | 843 | $type_ex = explode('/' , $format); 844 | 845 | $type_of_image = end($type_ex); 846 | 847 | if ($format == 'image/webp') { 848 | 849 | $image = imagecreatefromwebp($image); 850 | imagejpeg($image, $local_jpg_path, 100); 851 | imagedestroy($image); 852 | $this->path = 'image/jpg/' . $filename . '.jpg'; 853 | $this->save(); 854 | $this->webp_path = 'image/webp/' . $filename . '.webp'; 855 | 856 | } else { 857 | 858 | if (!in_array($type_of_image, [ 859 | 'jpeg', 860 | 'png', 861 | 'bmp', 862 | 'gd2', 863 | 'xbm', 864 | 'xpm' 865 | ])) { 866 | 867 | return; 868 | 869 | } 870 | 871 | $fun = 'imagecreatefrom' . $type_of_image; 872 | $image = $fun($image); 873 | imagewebp($image, $local_webp_path, 100); 874 | 875 | $this->webp_path = 'image/webp/' . $filename . '.webp'; 876 | $this->save(); 877 | pre($this->id, false); 878 | $this->moveLocalWebpImagetoS3Storage(); 879 | 880 | } 881 | 882 | $this->localStorageToS3Storage(); 883 | } 884 | 885 | /* 886 | | 887 | | This function was created to remove webp extension from the name column which was added | previously by mistake 888 | | 889 | */ 890 | public function adjustExtension() 891 | { 892 | $filename = $this->getFileNameWithoutExtension($this->name); 893 | $finalName = $filename . '.jpg'; 894 | $this->name = $finalName; 895 | $this->format = 'jpg'; 896 | $this->save(); 897 | pre($this->id, false); 898 | } 899 | 900 | protected function generateWebpImage() 901 | { 902 | //Moving image to local storage 903 | $this->moveImageToLocalStorage(); 904 | 905 | // Local storage path 906 | $image = Storage::disk('local')->path($this->path); 907 | 908 | // Fetching Format from the above path 909 | $format = image_type_to_mime_type(exif_imagetype($image)); 910 | 911 | // Exploding the format 912 | $type_ex = explode('/' , $format); 913 | 914 | // Taking the last key from the array to determin the image type 915 | $type_of_image = end($type_ex); 916 | 917 | // getting file name without extension to save image with extension webp 918 | $filename = $this->getFileNameWithoutExtension($this->name); 919 | $local_webp_path = storage_path('app/public/image/webp/' . $filename . '.webp'); 920 | 921 | if (!in_array($type_of_image, [ 922 | 'jpeg', 923 | 'png', 924 | 'bmp', 925 | 'gd2', 926 | 'xbm', 927 | 'xpm' 928 | ])) { 929 | 930 | return; 931 | 932 | } 933 | 934 | // As per the image type coverting it into the webp image without loosing quality 935 | $fun = 'imagecreatefrom' . $type_of_image; 936 | $image = $fun($image); 937 | imagepalettetotruecolor($image); 938 | imagewebp($image, $local_webp_path, 95); 939 | imagedestroy($image); 940 | 941 | // Saving webp path 942 | $this->webp_path = 'image/webp/' . $filename . '.webp'; 943 | $this->save(); 944 | 945 | // Finally moving file to the s3 storage 946 | $this->moveLocalWebpImagetoS3Storage(); 947 | } 948 | 949 | protected function generateJpgImage() 950 | { 951 | //Moving image to local storage 952 | $this->moveImageToLocalStorage(); 953 | 954 | // Local storage path 955 | $image = Storage::disk('local')->path($this->path); 956 | 957 | // getting file name without extension to save image with extension webp 958 | $filename = $this->getFileNameWithoutExtension($this->name) . '.jpg'; 959 | $local_jpg_path = storage_path('app/public/image/jpg/' . $filename); 960 | // As per the image type coverting it into the webp image without loosing quality 961 | $image = imagecreatefromwebp($image); 962 | imagepalettetotruecolor($image); 963 | imagejpeg($image, $local_jpg_path, 100); 964 | imagedestroy($image); 965 | 966 | // Saving webp path 967 | $this->path = 'image/jpg/' . $filename; 968 | $this->save(); 969 | 970 | // Finally moving file to the s3 storage 971 | $this->localStorageToS3Storage(); 972 | } 973 | 974 | public function remove($with_sizes = true) 975 | { 976 | $storage = Storage::disk($this->disk); 977 | 978 | if ($with_sizes && $this->type == 'image') { 979 | 980 | $sizes = MediaImageSize::where('id_media', $this->id) 981 | ->get(); 982 | 983 | foreach ($sizes as $size) { 984 | 985 | $path1 = 'image/jpg/' . $size->size . '/' . $this->name; 986 | 987 | if ($storage->exists($path1)) { 988 | // $storage->delete($path1); 989 | } 990 | 991 | if ($size->webp) { 992 | 993 | $path2 = 'image/webp/' . $size->size . '/' . $this->getFileNameWithoutExtension($this->name) . '.webp'; 994 | 995 | if ($storage->exists($path2)) { 996 | $storage->delete($path2); 997 | } 998 | 999 | } 1000 | 1001 | // Delete from the table 1002 | $size->delete(); 1003 | 1004 | } 1005 | 1006 | // Forcing the object to be deleted from the table 1007 | $this->forceDelete(); 1008 | 1009 | } 1010 | } 1011 | 1012 | public function githubTest() 1013 | { 1014 | return 'test'; 1015 | } 1016 | 1017 | public function fixNaming() 1018 | { 1019 | $this->moveImageToLocalStorage(); 1020 | 1021 | $filename = \Str::slug($this->getFileNameWithoutExtension($this->name)); 1022 | $ext = $this->getFileExtension($this->name); 1023 | 1024 | $new_name = $filename . '.' . $ext; 1025 | 1026 | $path_e = explode('/', $this->path); 1027 | $last_key = array_key_last($path_e); 1028 | if (isset($path_e[$last_key])) { 1029 | 1030 | $path_e[$last_key] = $new_name; 1031 | $new_path = implode('/', $path_e); 1032 | 1033 | //Renaming to new path 1034 | Storage::disk('local')->move($this->path, $new_path); 1035 | 1036 | $this->name = $new_name; 1037 | $this->path = $new_path; 1038 | $this->save(); 1039 | 1040 | $this->localStorageToS3Storage(); 1041 | } 1042 | } 1043 | 1044 | public function fixWebpNaming() 1045 | { 1046 | if (!$this->webp_path) { 1047 | return; 1048 | } 1049 | 1050 | $this->moveWebpImageToLocalStorage(); 1051 | 1052 | $filename = \Str::slug($this->getFileNameWithoutExtension($this->name)); 1053 | $ext = $this->getFileExtension($this->name); 1054 | 1055 | $new_name = $filename . '.' . $ext; 1056 | 1057 | $path_e = explode('/', $this->webp_path); 1058 | $last_key = array_key_last($path_e); 1059 | 1060 | if (isset($path_e[$last_key])) { 1061 | 1062 | $path_e[$last_key] = $new_name; 1063 | $new_path = implode('/', $path_e); 1064 | 1065 | //Renaming to new path 1066 | // Storage::disk('local')->move($this->webp_path, $new_path); 1067 | 1068 | $this->name = $new_name; 1069 | $this->webp_path = $new_path; 1070 | $this->save(); 1071 | 1072 | $this->localStorageToS3Storage(); 1073 | 1074 | pre(Storage::disk('s3')->url($this->webp_path)); 1075 | } 1076 | } 1077 | } 1078 | -------------------------------------------------------------------------------- /objects/MediaImageSize.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Objects\Media', 'id_media'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /objects/Page.php: -------------------------------------------------------------------------------- 1 | belongsToMany('App\Objects\PostCategory', 'post_category_assign', 'id_post', 'id_category'); 15 | } 16 | 17 | public function image() 18 | { 19 | return $this->belongsTo('App\Objects\Media', 'id_media'); 20 | } 21 | 22 | public function author() 23 | { 24 | return $this->belongsTo('App\Objects\AdminUser', 'id_author'); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /objects/PostCategory.php: -------------------------------------------------------------------------------- 1 | belongsToMany('App\Objects\Post', 'post_category_assigned', 'id_category', 'id_post'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /objects/PostCategoryAssigned.php: -------------------------------------------------------------------------------- 1 | belongsTo('App\Objects\Post', 'id_post'); 16 | } 17 | 18 | public function category() 19 | { 20 | return $this->belongsTo('App\Objects\PostCategory', 'id_category'); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 7 | "prod": "npm run production", 8 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "watch": "npm run development -- --watch", 10 | "watch-poll": "npm run watch -- --watch-poll" 11 | }, 12 | "dependencies": { 13 | "@mdi/font": "^4.4.95", 14 | "@uppy/core": "^1.4.0", 15 | "@uppy/dashboard": "^1.3.0", 16 | "@uppy/xhr-upload": "^1.3.0", 17 | "babel-runtime": "^6.26.0", 18 | "debounce": "^1.2.0", 19 | "jquery": "^3.5.0", 20 | "module": "^1.2.5", 21 | "summernote": "^0.8.16", 22 | "vue-server-renderer": "^2.6.10", 23 | "vuetify": "^2.0.0", 24 | "vuetify-google-autocomplete": "^2.0.0-beta.6" 25 | }, 26 | "devDependencies": { 27 | "fs": "0.0.1-security", 28 | "axios": ">=0.21.1", 29 | "cross-env": "^5.1", 30 | "laravel-mix": "^4.0.7", 31 | "resolve-url-loader": "^2.3.1", 32 | "sass": "^1.17.4", 33 | "sass-loader": "^7.1.0", 34 | "vue": "^2.6.10", 35 | "vue-cli-plugin-vuetify": "^0.6.3", 36 | "vue-router": "^3.1.3", 37 | "vue-template-compiler": "^2.6.10", 38 | "vuetify-loader": "^1.2.2", 39 | "vuex": "^3.1.1" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | mapApiRoutes(); 48 | 49 | $this->mapWebRoutes(); 50 | 51 | // 52 | } 53 | 54 | /** 55 | * Define the "web" routes for the application. 56 | * 57 | * These routes all receive session state, CSRF protection, etc. 58 | * 59 | * @return void 60 | */ 61 | protected function mapWebRoutes() 62 | { 63 | $this->mapRoutes(); 64 | } 65 | 66 | /** 67 | * Define the "api" routes for the application. 68 | * 69 | * These routes are typically stateless. 70 | * 71 | * @return void 72 | */ 73 | protected function mapApiRoutes() 74 | { 75 | Route::prefix('api') 76 | ->middleware('api') 77 | ->namespace($this->namespace) 78 | ->group(base_path('routes/api.php')); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /providers/kernel.php: -------------------------------------------------------------------------------- 1 | [ 33 | \App\Http\Middleware\EncryptCookies::class, 34 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 35 | \Illuminate\Session\Middleware\StartSession::class, 36 | // \Illuminate\Session\Middleware\AuthenticateSession::class, 37 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 38 | \App\Http\Middleware\VerifyCsrfToken::class, 39 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 40 | ], 41 | 42 | 'api' => [ 43 | 'throttle:api', 44 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 45 | ], 46 | ]; 47 | 48 | /** 49 | * The application's route middleware. 50 | * 51 | * These middleware may be assigned to groups or used individually. 52 | * 53 | * @var array 54 | */ 55 | protected $routeMiddleware = [ 56 | 'auth' => \App\Http\Middleware\Authenticate::class, 57 | 'admin_user' => \App\Http\Middleware\AdminUser::class, 58 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 59 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 60 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 61 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 62 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 63 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 64 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 65 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 66 | ]; 67 | } 68 | -------------------------------------------------------------------------------- /routes/admin.php: -------------------------------------------------------------------------------- 1 | 'api', 'middleware' => 'admin_user'], function () { 21 | 22 | Route::get('post/category/add', 'PostCategoryController@initContentCreate')->name('post_category.add'); 23 | Route::post('post/category/add', 'PostCategoryController@initProcessCreate'); 24 | Route::get('post/category/edit/{id}', 'PostCategoryController@initContentCreate')->name('post_category.edit'); 25 | Route::post('post/category/edit/{id}', 'PostCategoryController@initProcessCreate'); 26 | Route::get('post/category', 'PostCategoryController@initListing')->name('post_category.list'); 27 | Route::get('post/category/delete/{id}', 'PostCategoryController@initProcessDelete')->name('post_category.delete'); 28 | 29 | Route::get('post/add', 'PostController@initContentCreate')->name('post.add'); 30 | Route::post('post/add', 'PostController@initProcessCreate'); 31 | Route::get('post/edit/{id}', 'PostController@initContentCreate')->name('post.edit'); 32 | Route::post('post/edit/{id}', 'PostController@initProcessCreate'); 33 | Route::get('post', 'PostController@initListing')->name('post.list'); 34 | Route::get('post/delete/{id}', 'PostController@initProcessDelete')->name('post.delete'); 35 | 36 | Route::get('page/add', 'PageController@initContentCreate')->name('page.add'); 37 | Route::post('page/add', 'PageController@initProcessCreate'); 38 | Route::get('page/edit/{id}', 'PageController@initContentCreate')->name('page.edit'); 39 | Route::post('page/edit/{id}', 'PageController@initProcessCreate'); 40 | Route::get('page', 'PageController@initListing')->name('page.list'); 41 | 42 | Route::post('change/status', 'PageController@initProcessChangeStatus'); 43 | Route::post('{component}/delete/{id}', 'PageController@initProcessDelete'); 44 | 45 | Route::get('media', 'MediaController@initProcessListing'); 46 | Route::post('media/upload', 'MediaController@initProcessUpload'); 47 | 48 | Route::get('logout', function () { 49 | 50 | \Auth::guard('admin_user')->logout(); 51 | 52 | return redirect('/' . config('adlara.admin_route') . '/app/login'); 53 | 54 | }); 55 | }); -------------------------------------------------------------------------------- /src/Bootable.php: -------------------------------------------------------------------------------- 1 | segments(); 14 | $adminRoute = config('adlara.admin_route'); 15 | 16 | if (isset($urlSegements[0]) && ($urlSegements[0] == $adminRoute)) { 17 | 18 | $this->app->app_scope = 'admin'; 19 | config(['adlara.app_scope' => 'admin']); 20 | view()->addLocation(resource_path('views/admin')); 21 | 22 | } else { 23 | 24 | $this->app->app_scope = 'front'; 25 | view()->addLocation(resource_path('views/front')); 26 | 27 | } 28 | 29 | } 30 | 31 | public function boot() 32 | { 33 | $this->publishes([ 34 | __DIR__.'/../config/adlara.php' => config_path('adlara.php'), 35 | __DIR__.'/../config/auth.php' => config_path('auth.php'), 36 | __DIR__.'/../routes/admin.php' => base_path('routes/admin.php'), 37 | __DIR__.'/../views/admin/dashboard.blade.php' => base_path('resources/views/admin/dashboard.blade.php'), 38 | __DIR__.'/../views/front/welcome.blade.php' => base_path('resources/views/front/welcome.blade.php'), 39 | __DIR__.'/../database/migrations/' => database_path('/migrations'), 40 | __DIR__.'/../database/seeds/' => database_path('/seeds'), 41 | __DIR__.'/../database/factories/' => database_path('/factories'), 42 | __DIR__.'/../controllers/' => base_path('app/Http/Controllers'), 43 | __DIR__.'/../middleware/AdminUser.php' => base_path('app/Http/Middleware/AdminUser.php'), 44 | __DIR__.'/../middleware/VerifyCSRFToken.php' => base_path('app/Http/Middleware/VerifyCSRFToken.php'), 45 | __DIR__.'/../objects/' => base_path('app/Objects'), 46 | __DIR__.'/../providers/RouteServiceProvider.php' => base_path('app/Providers/RouteServiceProvider.php'), 47 | __DIR__.'/../providers/kernel.php' => base_path('app/Http/Kernel.php'), 48 | __DIR__.'/../_vApp/' => base_path('_vApp'), 49 | __DIR__.'/../package.json' => base_path('package.json'), 50 | __DIR__.'/helper.php' => base_path('app/helper.php'), 51 | __DIR__.'/../webpack.mix.js' => base_path('webpack.mix.js') 52 | ], 'adlarafullsetup'); 53 | } 54 | } -------------------------------------------------------------------------------- /src/RoutesProvider.php: -------------------------------------------------------------------------------- 1 | app_scope == 'admin') { 14 | 15 | $namespace = 'App\Http\Controllers\AdminControllers'; 16 | 17 | Route::middleware('web') 18 | ->prefix(config('adlara.admin_route')) 19 | ->namespace($namespace) 20 | ->group(base_path('routes/admin.php')); 21 | 22 | } else { 23 | 24 | $namespace = 'App\Http\Controllers\FrontControllers'; 25 | 26 | Route::middleware('web') 27 | ->namespace($namespace) 28 | ->group(base_path('routes/web.php')); 29 | 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/helper.php: -------------------------------------------------------------------------------- 1 | '; 6 | print_r($array); 7 | echo ''; 8 | 9 | if ($exit) { 10 | exit(); 11 | } 12 | } 13 | 14 | function removeStyle($content) 15 | { 16 | $output = preg_replace('/(<[^>]+) class=".*?"/i', '$1', $content); 17 | $output = str_ireplace('', '', $output); 18 | $output = str_ireplace('
]*>[\s| ]*<\/p>/', '', $output);
21 |
22 | // $output = preg_replace('/style[^>]*/', '', $output);
23 | // $output = preg_replace('/class[^>]*/', '', $output);
24 | $output = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $output);
25 | $output = preg_replace('/(<[^>]+) dir=".*?"/i', '$1', $output);
26 |
27 | return $output;
28 |
29 | }
30 |
31 | function protectedString($content)
32 | {
33 | $h = removeStyle($content);
34 | $h = strip_tags($h, '