init laravel 10

This commit is contained in:
Alexis Gousseau 2023-03-15 10:31:55 +01:00
parent aa4b5c0fa9
commit 9f95e1e6b5
343 changed files with 26467 additions and 23311 deletions

21
.editorconfig Normal file
View file

@ -0,0 +1,21 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
[*.vue]
indent_size = 2

View file

@ -1,19 +1,18 @@
APP_NAME=
APP_ENV=
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=
ASSET_URL=storage/
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=
DB_PORT=
DB_DATABASE=
DB_USERNAME=
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
@ -23,17 +22,37 @@ QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
LDC_STATUS_CHECKER_API_KEY="MY_KEY"
LDC_STATUS_CHECKER_UUID="UUID_PROJECT"
LDC_WEB_API_KEY="MY_KEY"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
GOOGLE_MAPS_KEY=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

55
.eslintrc.json Normal file
View file

@ -0,0 +1,55 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:vue/vue3-strongly-recommended",
"@vue/eslint-config-typescript"
],
"overrides": [
{
"files": ["*.ts", "*.vue"],
"rules": {
"no-undef": "off"
}
},
{
"files": ["*.vue"],
"rules": {
"indent": "off"
}
}
],
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "@typescript-eslint/parser",
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["vue", "@typescript-eslint"],
"ignorePatterns": ["webpack.mix.js", "**/vendor/*.js", "**/vendor/**/*.js"],
"rules": {
"indent": ["error", 4, { "SwitchCase": 1 }],
"linebreak-style": ["error", "unix"],
"quotes": ["error", "double"],
"semi": ["error", "always"],
"vue/script-indent": ["error", 2, { "baseIndent": 0, "switchCase": 1 }],
"vue/one-component-per-file": "off"
},
"settings": {
"import/resolver": {
"node": {
"extensions": [".js", ".vue", ".ts", ".d.ts"]
},
"alias": {
"extensions": [".vue", ".js", ".ts", ".scss", ".d.ts"],
"map": [
["~", "./resources/assets"],
["@", "./node_modules"]
]
}
}
}
}

11
.gitattributes vendored Normal file
View file

@ -0,0 +1,11 @@
* text=auto eol=lf
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore

26
.gitignore vendored
View file

@ -1,17 +1,25 @@
/node_modules
/public/hot
/public/storage
/public/build
/storage/*.key
/vendor
.env
.env.backup
.env.production
.phpunit.result.cache
.stylelintcache
/.fleet
/.idea
/.phpunit.cache
/.vscode/launch.json
/node_modules
/public/build
/public/cache
/public/hot
/public/medias
/public/sitemap.xml
/public/storage
/public/uploads
/storage/*.key
/vendor
auth.json
docker-compose.override.yml
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
/.idea
/.vscode
auth.json

41
.stylelintrc.json Normal file
View file

@ -0,0 +1,41 @@
{
"extends": [
"stylelint-config-standard-scss",
"stylelint-config-sass-guidelines",
"stylelint-config-idiomatic-order"
],
"plugins": ["stylelint-scss"],
"files": ["**/*.css", "**/*.scss"],
"ignoreFiles": [
"**/vendor/*.css",
"**/vendor/**/*.css",
"**/vendor/*.scss",
"**/vendor/**/*.scss",
"**/vendor/*.sass",
"**/vendor/**/*.sass",
"**/vendor/*.less",
"**/vendor/**/*.less",
"**/vendor/*.vue",
"**/vendor/**/*.vue"
],
"customSyntax": "postcss-scss",
"rules": {
"indentation": 4,
"string-quotes": "double",
"selector-max-id": null,
"color-no-invalid-hex": true,
"order/properties-alphabetical-order": null,
"max-nesting-depth": 5,
"selector-max-compound-selectors": 5,
"scss/double-slash-comment-empty-line-before": [
"always",
{
"ignore": [
"between-comments",
"stylelint-commands",
"inside-block"
]
}
]
}
}

23
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,23 @@
{
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#d6de61",
"activityBar.activeBorder": "#1a1d02",
"activityBar.background": "#d6de61",
"activityBar.foreground": "#15202b",
"activityBar.inactiveForeground": "#15202b99",
"activityBarBadge.background": "#21969e",
"activityBarBadge.foreground": "#e7e7e7",
"sash.hoverBorder": "#d6de61",
"statusBar.background": "#cbd537",
"statusBar.foreground": "#15202b",
"statusBarItem.hoverBackground": "#aab326",
"statusBarItem.remoteBackground": "#cbd537",
"statusBarItem.remoteForeground": "#15202b",
"titleBar.activeBackground": "#cbd537",
"titleBar.activeForeground": "#15202b",
"titleBar.inactiveBackground": "#cbd53799",
"titleBar.inactiveForeground": "#15202b99",
"commandCenter.border": "#15202b99"
},
"peacock.remoteColor": "#CBD537"
}

View file

@ -1,4 +0,0 @@
FROM registry.gitlab.com/service-web-lab/ldc-web-images-docker/ldcweb-production:php8.1.1
COPY --chown=noroot:noroot . /app/srcs
COPY --chown=noroot:noroot ./public/build /app/srcs/public/build
COPY --chown=noroot:noroot ./vendor /app/srcs/vendor

View file

@ -1,16 +1,66 @@
# Wenn dann mit Respekt
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
## Crons
Put every min in PROD :
```
php artisan schedule:run
```
<p align="center">
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
## Available Commands
```
ldc:status-report
ldc:send-status-report
ldcweb:admin-secure-sync
## About Laravel
sentry:test
```
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
Laravel is accessible, powerful, and provides tools required for large, robust applications.
## Learning Laravel
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
You may also try the [Laravel Bootcamp](https://bootcamp.laravel.com), where you will be guided through building a modern Laravel application from scratch.
If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 2000 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
## Laravel Sponsors
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
### Premium Partners
- **[Vehikl](https://vehikl.com/)**
- **[Tighten Co.](https://tighten.co)**
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
- **[64 Robots](https://64robots.com)**
- **[Cubet Techno Labs](https://cubettech.com)**
- **[Cyber-Duck](https://cyber-duck.co.uk)**
- **[Many](https://www.many.co.uk)**
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
- **[DevSquad](https://devsquad.com)**
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
- **[OP.GG](https://op.gg)**
- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)**
- **[Lendio](https://lendio.com)**
## Contributing
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).

View file

@ -1,7 +0,0 @@
PHP 8.0.2
Laravel 9.2
Voyager 1.5
Mysql 5.7.20
nodejs v16.14.2
npm 8.7.0
Composer version 2.2.9

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Concept extends Model
{
}

View file

@ -0,0 +1,177 @@
<?php
namespace App\Console\Commands;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
class CreateAdmin extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'user:create';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a backend admin user';
/**
* The firstname of the new user.
*
* @var string
*/
protected $firstname;
/**
* The lastname of the new user.
*
* @var string
*/
protected $lastname;
/**
* The email of the new user.
*
* @var string
*/
protected $email;
/**
* The password of the new user.
*
* @var string
*/
protected $password;
/**
* Execute the console command.
*
* @return integer
*/
public function handle()
{
$this->firstname = null;
$this->addFirstname();
$this->lastname = null;
$this->addLastname();
$this->email = null;
$this->addEmail();
$this->password = null;
$this->addPassword();
$user = new User([
'firstname' => $this->firstname,
'lastname' => $this->lastname,
'email' => $this->email,
'password' => $this->password,
]);
$user->saveOrFail();
$this->info('User created 👌');
return 0;
}
/**
* Add a firstname to the user.
*
* @return void
*/
private function addFirstname(): void
{
while (is_null($this->firstname)) {
try {
$tmp = $this->ask('Type the wanted user firstname', 'Admin');
$validator = Validator::make(['firstname' => $tmp], [
'firstname' => 'required|min:3|max:255'
]);
$validator->validate();
$this->firstname = $tmp;
} catch (ValidationException $e) {
$this->error(sprintf(
'Please provide a valid firstname %s',
\implode(',', collect($e->errors())->flatten()->all())
));
continue;
} //end try
}; //end while
}
/**
* Add a lastname to the user.
*
* @return void
*/
private function addLastname(): void
{
while (is_null($this->lastname)) {
try {
$tmp = $this->ask('Type the wanted user lastname', 'Saïtama');
$validator = Validator::make(['lastname' => $tmp], [
'lastname' => 'required|min:3|max:255'
]);
$validator->validate();
$this->lastname = $tmp;
} catch (ValidationException $e) {
$this->error(sprintf(
'Please provide a valid lastname %s',
\implode(',', collect($e->errors())->flatten()->all())
));
continue;
} //end try
}; //end while
}
/**
* Add an email to the user.
*
* @return void
*/
private function addEmail(): void
{
while (is_null($this->email)) {
try {
$tmp = $this->ask('Type the wanted user email', 'equipe.web@ldc.fr');
$validator = Validator::make(['email' => $tmp], [
'email' => 'required|unique:users,email|email:rfc,dns'
]);
$validator->validate();
$this->email = $tmp;
} catch (ValidationException $e) {
$this->error(sprintf(
'Please provide a valid email %s',
\implode(',', collect($e->errors())->flatten()->all())
));
continue;
} //end try
}; //end while
}
/**
* Add a password to the user.
*
* @return void
*/
private function addPassword(): void
{
while (
($this->password = $this->secret(
(!\is_null($this->password) ? 'Failed to confirm, ' : '') . 'Type the wanted user password'
)) !== $this->secret('Confirm the password')
) {
continue;
}; //end while
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Content extends Model
{
}

0
app/Enums/.gitkeep Normal file
View file

View file

@ -7,21 +7,12 @@ use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
* @var array<int, class-string<Throwable>>
*/
protected $dontReport = [
];
protected $dontReport = [];
/**
* A list of the inputs that are never flashed for validation exceptions.
@ -42,9 +33,6 @@ class Handler extends ExceptionHandler
public function register()
{
$this->reportable(function (Throwable $e) {
if (app()->bound('sentry')) {
app('sentry')->captureException($e);
}
});
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Home extends Model
{
}

View file

@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
use AuthenticatesUsers;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('guest:backend')->except('logout');
}
/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard('backend');
}
/**
* Show the application's login form.
*
* @return \Illuminate\View\View
*/
public function showLoginForm()
{
return view('bo.auth.login');
}
/**
* Where to redirect users after login.
* @return string
*/
protected function redirectTo(): string
{
return response()->redirectToIntended()->getTargetUrl();
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace App\Http\Controllers\Bo\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Support\Facades\Auth;
class ResetPasswordController extends Controller
{
use ResetsPasswords;
/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard('backend');
}
/**
* Where to redirect users after login.
* @return string
*/
protected function redirectTo(): string
{
return \route('bo.login');
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace App\Http\Controllers\Bo;
use App\Http\Controllers\Controller;
class DashboardController extends Controller
{
/**
* Dashboard Page
*
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
return view('bo.pages.dashboard');
}
}

View file

@ -1,53 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class ContactController extends Controller
{
/**
* Show contact page
*
* @return \Illuminate\Contracts\View\View
*/
public function contactForm()
{
return view('pages.kontakt');
}
/**
* Submit contact form
*
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function sendContactForm(Request $request)
{
$request->validate(
[
'vorname' => 'required',
'nachname' => 'required',
'email' => 'required|email',
'nachricht' => 'required',
'datenschutz' => 'required',
]
);
$mailDatas = [
'vorname' => $request->vorname,
'nachname' => $request->nachname,
'email' => $request->email,
'nachricht' => $request->nachricht,
];
Mail::send('contactMail', $mailDatas, function ($message) {
$message->from('info@wenndannmitrespekt.de', 'Kontaktformular wenndannmitrespekt.de');
$message->to('kontakt@wenndannmitrespekt.de', 'kontakt@wenndannmitrespekt.de')
->subject('Kontaktformular wenndannmitrespekt.de');
});
return redirect()->back()->with(['success' => 'Vielen Dank für Ihre Nachricht.']);
}
}

View file

@ -2,14 +2,124 @@
namespace App\Http\Controllers;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Session;
class Controller extends BaseController
{
use AuthorizesRequests;
use DispatchesJobs;
use ValidatesRequests;
/**
* Build Search query on specified fields
* splitting search into words or using whole sentence
*
* @param \Illuminate\Database\Eloquent\Builder $query The eloquent query builder.
* @param string $search The query string.
* @param callable $searchQuery The query string.
* @param string ...$fields Either a simple array or a string
* in case of a string the two fields
* would be concatenate to make the search.
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function searchQuery(
Builder $query,
string $search,
callable $searchQuery = null,
string ...$fields
): Builder {
if (count($fields)) {
// Search using words.
$words = explode(' ', $search);
$query->where(function ($query) use ($searchQuery, $words, $search, $fields) {
foreach ($words as $word) {
if (!strlen($word)) {
continue;
}
$this->searchOnFields($query, $word, $fields);
} //end foreach
// Search whole using whole sentence.
$this->searchOnFields($query, $search, $fields);
if ($searchQuery) {
$searchQuery($query);
}
});
} //end if
return $query;
}
/**
* Build query search on all fields
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $search
* @param array $fields
* @return \Illuminate\Database\Eloquent\Builder
*/
private function searchOnFields(Builder $query, string $search, array $fields): Builder
{
$table = $query->getModel()->getTable();
foreach ($fields as $f) {
$f = str_replace('?', '\?', $f);
if (is_array($f)) {
$query->orWhereRaw(
sprintf("UPPER(CONCAT(%s)) LIKE UPPER(?)", collect($f)->map(function ($q) use ($table) {
return "`$table`.`$q`";
})->implode(', \' \', ')),
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
);
} else {
$query->orWhereRaw(
"UPPER(`$table`.`$f`) LIKE UPPER(?)",
['%' . filter_var($search, FILTER_SANITIZE_STRING) . '%']
);
}
}
return $query;
}
/**
* Sort columns with a query
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $ignore
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function sortQuery(Builder $query, array $ignore = []): Builder
{
$rName = request()->route()->getName();
$table = $query->getModel()->getTable();
if (request()->sort_col) {
Session::put("$rName.sort_col", request()->sort_col);
Session::put("$rName.sorted", true);
}
if (request()->sort_way) {
Session::put("$rName.sort_way", request()->sort_way);
Session::put("$rName.sorted", true);
}
if (request()->rst) {
Session::remove("$rName.sorted");
Session::remove("$rName.sort_col");
Session::remove("$rName.sort_way");
}
if (request()->sort_col and request()->sort_way and Schema::hasColumn($table, request()->sort_col)) {
if (
!isset($ignore) or
(isset($ignore) and !in_array(request()->sort_col, $ignore))
) {
$query = $query->orderBy(\sprintf("$table.%s", request()->sort_col), request()->sort_way);
}
} elseif (Schema::hasColumn($table, 'order')) {
$query = $query->orderBy('order', 'ASC');
Session::put("$rName.sort_col", 'order');
Session::put("$rName.sort_way", 'asc');
}
return $query;
}
}

View file

@ -0,0 +1,18 @@
<?php
namespace App\Http\Controllers\Fo;
use App\Http\Controllers\Controller;
class HomeController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
return view('fo.pages.home');
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Retailgroup;
class GroupController extends Controller
{
/**
* RetailGroup Show
*
* @param integer $id
* @return \App\Retailgroup
*/
public function show(int $id)
{
return Retailgroup::find($id);
}
}

View file

@ -1,23 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Page;
class PageController extends Controller
{
/**
* Page show
*
* @param string $slug
* @return \Illuminate\Contracts\View\View
*/
public function index(string $slug)
{
$page = Page::where('slug', $slug)->first();
if ($page == null) {
abort(404);
}
return view('pages.page', compact('page'));
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Product;
class ProductController extends Controller
{
/**
* Products index
*
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
$products = Product::all()->sortby('sequence')->reverse()->groupBy('poultry');
$poultries = $products->keys()->sort();
return view('pages.produkte', compact(['products', 'poultries']));
}
/**
* Product show
*
* @param mixed $id
* @return \Illuminate\Contracts\View\View
*/
public function show(mixed $id)
{
$product = Product::where('id', $id)->first();
if ($product == null) {
$product = Product::where('slug', $id)->first();
if ($product == null) {
abort(404);
}
}
return view('pages.produkt', compact('product'));
}
}

View file

@ -1,42 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Recipe;
class RecipeController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
// Get recipies.
$recipes = Recipe::where('live', '1')->get();
// Filter poultry.
$poultries = $recipes->unique('cat')->pluck('cat');
// Filter difficulty.
$difficulties = $recipes->unique('difficulty')->pluck('difficulty');
return view('pages.rezepte', compact(['recipes', 'poultries', 'difficulties']));
}
/**
* Recipe show
*
* @param mixed $id
* @return \Illuminate\Contracts\View\View
*/
public function show(mixed $id)
{
$recipe = Recipe::where('id', $id)->first();
if ($recipe == null) {
$recipe = Recipe::where('slug', $id)->first();
if ($recipe == null) {
abort(404);
}
}
return view('pages.rezept', compact(['recipe']));
}
}

View file

@ -1,19 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Retailregion;
class RegionController extends Controller
{
/**
* Show retail region
*
* @param integer $id
* @return \App\Retailregion;
*/
public function show(int $id)
{
return Retailregion::find($id);
}
}

View file

@ -1,48 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
class StoreController extends Controller
{
/**
* Store by city
*
* @param \Illuminate\Http\Request $request
* @param mixed $city
* @return \App\Store;
*/
public function city(Request $request, mixed $city)
{
// CSRF Token check.
if (
!(is_string($request->session()->token()) &&
is_string($request->header('X-CSRF-TOKEN')) &&
hash_equals($request->session()->token(), $request->header('X-CSRF-TOKEN')))
) {
\abort(419);
}
if (is_numeric($city)) {
$stores = DB::table('stores')
->join('retailregions', 'stores.region_id', '=', 'retailregions.id')
->join('retailgroups', 'retailregions.region_group', '=', 'retailgroups.id')
->select('stores.*', 'retailregions.*', 'retailgroups.*')
->where('stores.zipcode', $city)
->get();
return $stores;
} else {
$stores = DB::table('stores')
->join('retailregions', 'stores.region_id', '=', 'retailregions.id')
->join('retailgroups', 'retailregions.region_group', '=', 'retailgroups.id')
->select('stores.*', 'retailregions.*', 'retailgroups.*')
->where('stores.city', $city)
->get();
return $stores;
}
}
}

View file

@ -16,7 +16,6 @@ class Kernel extends HttpKernel
protected $middleware = [
\App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
@ -30,12 +29,14 @@ class Kernel extends HttpKernel
*/
protected $middlewareGroups = [
'web' => [
'htmlsanitize',
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\SecureHeaders::class
],
'api' => [
@ -54,7 +55,6 @@ class Kernel extends HttpKernel
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
@ -62,5 +62,6 @@ class Kernel extends HttpKernel
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
];
}

View file

@ -3,20 +3,35 @@
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Facades\Session;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @param mixed $request
* @return string|null
* @phpcs:disable Squiz.Commenting.FunctionComment.TypeHintMissing
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
$logins = [
'backend' => route('bo.login')
];
if (!$request->expectsJson()) {
// * Notify must login
Session::flash('warning', trans('Veuillez vous connecter pour continuer'));
foreach ($request->route()->gatherMiddleware() as $middleware) {
if (\is_string($middleware) and strpos($middleware, 'auth:') !== false) {
$route = $logins[str_replace('auth:', '', $middleware)] ?? null;
if ($route) {
return $route;
}
}
}
return route('login');
}
abort(401);
}
}

View file

@ -11,6 +11,5 @@ class EncryptCookies extends Middleware
*
* @var array<int, string>
*/
protected $except = [
];
protected $except = [];
}

View file

@ -0,0 +1,53 @@
<?php
namespace App\Http\Middleware;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Http\Request;
class HtmlSanitizer
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param mixed ...$params
* @return mixed
*/
public function handle(Request $request, \Closure $next, ...$params)
{
$inputs = $request->all();
/** @var callable|null */
$cleanInput = null;
$cleanInput = function (&$input, $name, $rootName = null) use ($params, &$cleanInput) {
// * Nested element array
if (is_array($input)) {
array_walk_recursive($input, $cleanInput, $name);
}
if (!is_string($input)) {
return;
}
if (in_array($name, $params) or in_array($rootName ?? $name, $params)) {
// ? Is a json input ?
if ($isJson = \json_decode($input, true) and is_array($isJson)) {
// ! Decode each json field recursive.
\array_walk_recursive($isJson, function (&$item) {
if (\is_string($item)) {
$item = clean($item);
$item = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($item);
}
});
} else {
$input = clean($input);
$input = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($input);
}
} else {
$input = strip_tags($input);
}
};
\array_walk($inputs, $cleanInput);
$request->merge($inputs);
return $next($request);
}
}

View file

@ -11,6 +11,5 @@ class PreventRequestsDuringMaintenance extends Middleware
*
* @var array<int, string>
*/
protected $except = [
];
protected $except = [];
}

View file

@ -2,7 +2,6 @@
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -12,10 +11,13 @@ class RedirectIfAuthenticated
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null ...$guards
* @phpcs:disable Generic.Files.LineLength.TooLong
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @param string|null ...$guards
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
* @throws \RuntimeException If guard is unhandled.
* @phpcs:enable
*/
public function handle(Request $request, Closure $next, ...$guards)
{
@ -23,7 +25,14 @@ class RedirectIfAuthenticated
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
switch ($guard) {
case 'frontend':
return \redirect()->route('home');
case 'backend':
return \redirect()->route('bo.dashboard');
default:
throw new \RuntimeException("Unhandled guard `{$guard}` .");
}
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Vite;
class SecureHeaders
{
/**
* Enumerate headers which you do not want in your application's responses.
* Great starting point would be to go check out @Scott_Helme's:
* https://securityheaders.com/
*
* @var array
*/
private $unwantedHeaderList = [
'X-Powered-By',
'Server',
];
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next)
{
View::share('nonce', $nonce = Vite::useCspNonce());
// * For VueJS dev tool to execute
$jsDev = config('app.debug') ? "'unsafe-eval' 'unsafe-inline'" : "'nonce-{$nonce}' 'strict-dynamic'";
$scheme = config('app.env') === 'local' ? 'http' : 'https';
$reportUri = Route::has('cspReportUri') ?
\sprintf(' report-uri %s ;', \parse_url(route('cspReportUri'), \PHP_URL_PATH)) : '';
$this->removeUnwantedHeaders($this->unwantedHeaderList);
$response = $next($request);
$response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade');
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;');
$cspPolicies = [
"default-src 'none';",
"manifest-src 'self';",
// * CKEDITOR Specific https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/csp.html
"connect-src 'self' blob:;",
"img-src * data: blob:;",
'frame-src ' . implode(' ', [
'https://www.google.com/recaptcha/',
'https://recaptcha.google.com/recaptcha/',
'https://www.google.com/maps/'
]) . ';',
"font-src 'self' data: https://fonts.gstatic.com;",
// ! Using CKEditor will must have unsafe-inline style
// phpcs:ignore Generic.Files.LineLength.TooLong
"style-src 'self' 'unsafe-inline' " . \implode(' ', [
'https://cdnjs.cloudflare.com',
// * File Manager
'https://fonts.googleapis.com',
'https://cdn.jsdelivr.net',
'https://use.fontawesome.com',
'https://fonts.googleapis.com'
]) . ';',
// ! If you dont use ckeditor use this
// "style-src 'self' 'nonce-$nonce';",
// phpcs:ignore Generic.Files.LineLength.TooLong
"script-src 'self' {$jsDev} " . \implode(' ', [
'https: blob:',
'https://www.googletagmanager.com',
'https://cdnjs.cloudflare.com',
"$scheme://www.google-analytics.com",
]) . ';'
];
$response->headers->set(
'Content-Security-Policy',
implode(' ', $cspPolicies) . $reportUri
);
$response->headers->set('Feature-Policy', 'fullscreen \'self\';');
return $response;
}
/**
* Remove unwanted headers
*
* @param array $headerList
* @return void
*/
private function removeUnwantedHeaders(array $headerList)
{
foreach ($headerList as $header) {
header_remove($header);
}
}
}

View file

@ -11,6 +11,5 @@ class VerifyCsrfToken extends Middleware
*
* @var array<int, string>
*/
protected $except = [
];
protected $except = ['/csp-report'];
}

View file

View file

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class LandingPage extends Model
{
}

View file

@ -1,6 +1,6 @@
<?php
namespace App\Lib;
namespace App\Lib\Helpers;
class ExceptionsHelper
{

View file

@ -0,0 +1,444 @@
<?php
namespace App\Lib\Helpers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
/**
* This class is used to handle files in LDC Laravel stack
*
* * The storage strategy will be using date.
* The file name may contain sufix timestamp highresolution time (hrtime or microtime) if is duplicate.
* (function() { return time() . ' ' . Str::slug(microtime(true)) . ' ' . hrtime(true); })();
*
* posts/ - The model table name
* 10/ - Year
* 04/ - Month
* 19/ - Day
* 5f/ - First two letters of md5 file
* black-cat-under-red-car.png - Slugified file name
* black-cat-under-red-car-286071690833400.png - Slugified file name that is duplicated
*
* The final path will be storage/modelfiles/posts/10/04/19/5f/black-cat-under-red-car-286071690833400.png
*
* ! No limits of file per folder will be handled.
*
* @author Munsch Jérémy <jeremy.munsch@ldc.fr>
*/
class FileStorageHelper
{
/**
* Destroy the file associate with the attribute.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $attribute
* @return void
*/
public static function removeFile(Model $model, string $attribute): void
{
$path = \ltrim(\urldecode($model->{$attribute}), '/');
if (\strpos($path, 'storage') !== 0) {
return;
}
$path = ToolboxHelper::mbReplace('storage/', '', $path);
if (Storage::disk('public')->exists($path)) {
Storage::disk('public')->delete($path);
}
}
/**
* Destroy the file associate with the attribute old value (before updated to DB).
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $attribute
* @param boolean $onlyIfUpdated
* @return void
*/
public static function removeOldFile(Model $model, string $attribute, bool $onlyIfUpdated = true): void
{
// * Ignore If removal has to be done only if the field has changed and it actually hasnt.
if ($onlyIfUpdated and $model->{$attribute} === $model->getOriginal($attribute)) {
return;
}
$originalPath = \ltrim(\urldecode($model->getOriginal($attribute)), '/');
if (\strpos($originalPath, 'storage') !== 0) {
return;
}
$originalPath = ToolboxHelper::mbReplace('storage/', '', $originalPath);
if (Storage::disk('public')->exists($originalPath)) {
Storage::disk('public')->delete($originalPath);
}
}
/**
* Store a file using optimized storage strategy
*
* You can use filename param to overload file name.
*
* @param \Illuminate\Database\Eloquent\Model $model The model that will hold the picture.
* @param \Illuminate\Http\UploadedFile|\SplFileInfo|string $file The file, will just return itself is string.
* @param boolean $slugify Force filename slugification.
* @param string|null $filename This string may be used to store the file.
* @param boolean $private To store the file in a private space.
* @return string
* @throws \RuntimeException If file copy fails.
*/
public static function storeFile(
Model $model,
$file,
bool $slugify = false,
string $filename = null,
bool $private = false
): string {
$tableName = $model->getTable();
if (\is_object($file) and $file instanceof \Illuminate\Http\UploadedFile) {
if ($private) {
throw new \RuntimeException('Private storage for uploaded files is unhandled');
}
/** @var \Illuminate\Http\UploadedFile $file */
$filename = $filename ?: $file->getClientOriginalName();
$filename = $slugify ? self::slugifyFileName($filename) : $filename;
$newPath = self::prepareMoveFile($tableName, $filename);
$newPath = str_replace(storage_path('app'), '', $newPath);
$file->storePubliclyAs(
pathinfo($newPath, \PATHINFO_DIRNAME),
pathinfo($newPath, \PATHINFO_BASENAME)
);
return 'storage' . str_replace('/public', '', $newPath);
}
if (\is_object($file) and $file instanceof \SplFileInfo) {
/** @var \SplFileInfo $file */
$filename = $filename ?: $file->getBaseName();
$filename = $slugify ? self::slugifyFileName($filename) : $filename;
$newPath = self::prepareMoveFile($tableName, $filename, $private);
if (!File::copy($file->getRealPath(), $newPath)) {
throw new \RuntimeException(sprintf(
'Failed to copy file %s to %s',
$file->getRealPath(),
$newPath
));
}
return $private ?
\ltrim(str_replace(\storage_path('app/private'), '/storage/app/private', $newPath), '/') :
\ltrim(str_replace(\storage_path('app/public'), '/storage', $newPath), '/');
}
return strval($file);
}
/**
* Store all files from string attribute html
* If oldHtmlString is passed, a diff is done with new and old files
* to keep only files that are present in the new html string.
*
*
* @param \Illuminate\Database\Eloquent\Model $model The model that will hold the picture.
* @param string $htmlString The html string to parse and modify files.
* @param string|null $oldHtmlString The old html string with alreadyParsed
* files using storeModelFilesFromHtml.
* @return string Html with files pathes replaced using storage strategy.
*/
public static function storeModelFilesFromHtml(
Model $model,
string $htmlString,
string $oldHtmlString = null
): string {
\collect(self::onlyUploadedFilesWithFileManager(self::findFilesInHtml($htmlString)))
->each(function (string $path) use ($model, &$htmlString) {
/** @var \Illuminate\Filesystem\FilesystemAdapter */
$disk = Storage::disk('uploads');
$fileInfo = new \SplFileInfo($disk->path(
ToolboxHelper::mbReplace('/uploads/', '', \urldecode($path))
));
$htmlString = ToolboxHelper::mbReplace(
$path,
'/' . self::storeFile($model, $fileInfo, true),
$htmlString
);
});
if ($oldHtmlString) {
self::removeOldModelFilesFromHtml($htmlString, $oldHtmlString);
}
return $htmlString;
}
/**
* Remove all old files from string attribute html that are stored in public that
* are nove present anymore on new html string
*
* @param string $newHtmlString The html string with alreadyParsed files using storeModelFilesFromHtml.
* @param string $oldHtmlString The old html string with alreadyParsed files using storeModelFilesFromHtml.
* @return void
*/
public static function removeOldModelFilesFromHtml(string $newHtmlString, string $oldHtmlString): void
{
self::removeOldFiles(self::findFilesInHtml($oldHtmlString), self::findFilesInHtml($newHtmlString));
}
/**
* Remove all old files that are stored in public that
* are not present anymore on new array files
*
* @param string[] $oldFiles The old array files.
* @param string[] $newFiles The new array files.
* @return void
*/
public static function removeOldFiles(array $oldFiles, array $newFiles): void
{
$oldFiles = \collect(self::onlyUploadedFilesWithFileStorageHelper($oldFiles));
$filesToKeep = \collect(self::onlyUploadedFilesWithFileStorageHelper($newFiles));
$filesToRemove = $oldFiles->diff($filesToKeep);
$filesToRemove->each(function (string $publicStorageFilePath) {
$path = ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/'));
if (Storage::disk('public')->exists($path)) {
Storage::disk('public')->delete($path);
}
});
}
/**
* Remove all files from string attribute html that are stored in public
*
* @param string $htmlString The html string with alreadyParsed files using storeModelFilesFromHtml.
* @return void
*/
public static function removeModelFilesOfHtml(string $htmlString): void
{
$filesToRemove = \collect(self::onlyUploadedFilesWithFileStorageHelper(self::findFilesInHtml($htmlString)));
$filesToRemove->each(function (string $publicStorageFilePath) {
$path = ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/'));
if (Storage::disk('public')->exists($path)) {
Storage::disk('public')->delete($path);
}
});
}
/**
* Find all occurence of files in html
* @param string $html
* @return array
*/
public static function findFilesInHtml(string $html): array
{
preg_match_all('/href="(?P<href>.*)"|src="(?P<src>.*)"|url="(?P<url>.*)"/Um', $html, $m, PREG_SET_ORDER, 0);
return collect($m)->pluck('href')->filter()
->concat(collect($m)->pluck('url')->filter())
->concat(collect($m)->pluck('src')->filter())
->all();
}
/**
* Filter array to get only uploaded files that exists
* on disk 'public' (using helper storage strategy)
*
* @param array $urls
* @return array
*/
public static function onlyUploadedFilesWithFileStorageHelper(array $urls): array
{
return \collect($urls)->unique()
// * Filter to get only /uploads and using app url or empty
->filter(function (string $url) {
$path = \parse_url($url, \PHP_URL_PATH);
return \strpos(\ltrim($path, '/'), 'storage/modelfiles') === 0;
})->filter(function (string $url) {
$path = \parse_url($url, \PHP_URL_PATH);
return Storage::disk('public')
->exists(ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($path), '/')));
})->all();
}
/**
* Filter array to get only uploaded files that exists
* on disk 'uploads'
*
* @param array $urls
* @return array
*/
private static function onlyUploadedFilesWithFileManager(array $urls): array
{
return \collect($urls)->unique()
// * Filter to get only /uploads and using app url or empty
->filter(function (string $url) {
$host = \parse_url($url, \PHP_URL_HOST);
$path = \parse_url($url, \PHP_URL_PATH);
return ($host === \parse_url(config('app.url'), PHP_URL_HOST) or \is_null($host)) and
\strpos(\ltrim($path, '/'), 'uploads') === 0;
})->filter(function (string $url) {
$path = \parse_url($url, \PHP_URL_PATH);
return Storage::disk('uploads')
->exists(ToolboxHelper::mbReplace('uploads/', '', \ltrim(\urldecode($path), '/')));
})->all();
}
/**
* Prepare storage path and return
* the file full path
*
* @param string $tableName Model table name.
* @param string $filename The basename for the file.
* @param boolean $private May the file be stored in a private dir.
* @return string
*/
private static function prepareMoveFile(string $tableName, string $filename, bool $private = false): string
{
// * Security filter + beautifier
$filename = self::sanitizeFileName($filename);
// * Security filter
$filename = \filter_var($filename, \FILTER_SANITIZE_STRING);
// * Slugify filename
$ext = \pathinfo($filename, \PATHINFO_EXTENSION);
$filename = Str::slug(\pathinfo($filename, \PATHINFO_FILENAME)) .
(\strlen($ext) ? ".{$ext}" : '');
$folderPath = self::getStoragePath(
$private ? 'app/private/modelfiles' : 'app/public/modelfiles',
$tableName,
$filename,
$private
);
$filename = self::getFileUniqueName($folderPath, $filename);
return "{$folderPath}/{$filename}";
}
/**
* Create sub folders to store files using pattern
* storage/modelfiles/posts/10/04/19/5f
* year/month/day/md5 first 2 letters
*
* @param string $storage_dir
* @param string $table
* @param string $filename
* @return string
*/
private static function getStoragePath(string $storage_dir, string $table, string $filename): string
{
$filenameHash = \md5($filename);
$pathFolder = \storage_path(sprintf(
'%s/%s/%s/%s/%s/%s',
$storage_dir,
$table,
gmdate('y'),
gmdate('m'),
gmdate('d'),
substr($filenameHash, 0, 2)
));
if (!File::exists($pathFolder)) {
File::makeDirectory($pathFolder, 0755, true);
}
return $pathFolder;
}
/**
* Get unique filename if the path is already occupied
*
* @param string $folderPath
* @param string $filename
* @return string
* @throws \RuntimeException If a unique filename cannot be obtained.
*/
private static function getFileUniqueName(string $folderPath, string $filename): string
{
$attempts = 0;
$maxAttempts = 20;
while (File::exists("{$folderPath}/{$filename}")) {
if ($attempts++ >= $maxAttempts) {
throw new \RuntimeException("Failed to has a unique filename for {$folderPath}/{$filename}");
}
$filename = pathinfo($filename, \PATHINFO_FILENAME) .
\uniqid('-') . '.' .
pathinfo($filename, \PATHINFO_EXTENSION);
}
return $filename;
}
/**
* Slugify the filename
*
* @param string $filename
* @return string
*/
public static function slugifyFileName(string $filename): string
{
return Str::slug(pathinfo($filename, \PATHINFO_FILENAME)) . '.' . pathinfo($filename, \PATHINFO_EXTENSION);
}
/**
* Sanitize File name for uploaded files
*
* @param string $filename The original uploaded client file name.
* @param boolean $beautify Beautify the filename.
* @return string The sanitized file name.
*/
public static function sanitizeFileName(string $filename, bool $beautify = true): string
{
// * Sanitize filename
// phpcs:disable Generic.Files.LineLength.TooLong
$filename = preg_replace(
'~
[<>:"/\\\|?*]| # file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
[\x00-\x1F]| # control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
[\x7F\xA0\xAD]| # non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
[#\[\]@!$&\'()+,;=]| # URI reserved https://tools.ietf.org/html/rfc3986#section-2.2
[{}^\~`] # URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
~x',
'-',
$filename
);
// phpcs:enable
// * Avoids '.' '..' or '.hiddenFiles' .
$filename = Str::of($filename)->ltrim('.-');
// * Optional beautification
if ($beautify) {
$filename = static::beautifyFilename($filename);
}
// * Maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
/** @var string */
$extension = pathinfo($filename, \PATHINFO_EXTENSION);
/** @var string */
$filename = pathinfo($filename, \PATHINFO_FILENAME);
$encoding = mb_detect_encoding($filename);
$encoding = $encoding ? $encoding : null;
return \mb_strcut(
$filename,
0,
255 - (!empty($extension) ? strlen($extension) + 1 : 0),
$encoding
) . (!empty($extension) ? ".$extension" : '');
}
/**
* Beautify a filename
*
* @param string $filename
* @return string
*/
private static function beautifyFilename(string $filename): string
{
// Reduce consecutive characters.
$filename = preg_replace([
// * "file name.zip" becomes 'file-name.zip'
'/ +/',
// * "file___name.zip" becomes 'file-name.zip'
'/_+/',
// * "file---name.zip" becomes 'file-name.zip'
'/-+/'
], '-', $filename);
$filename = preg_replace([
// * "file--.--.-.--name.zip" becomes "file.name.zip"
'/-*\.-*/',
// * "file...name..zip" becomes "file.name.zip"
'/\.{2,}/'
], '.', $filename);
// Lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625 .
$filename = mb_strtolower($filename, mb_detect_encoding($filename));
// * ".file-name.-" becomes "file-name"
$filename = trim($filename, '.-');
return $filename;
}
}

View file

@ -0,0 +1,237 @@
<?php
namespace App\Lib\Helpers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ToolboxHelper
{
/**
* Strip scheme (https) on oembed urls
* Only embed allowed are for MP4 self hosted videos right now
*
* https is force by ckeditor MediaElements which natively supports
* only cloud hosted medias (youtube, spotify etc..)
*
* @param string $input
* @return string
*/
public static function stripCkEditorSchemesOnMediaInputs(string $input): string
{
$input = \preg_replace('/(?<=<oembed url=")(https:\/\/)(?=.*?">)/m', '', $input);
return $input;
}
/**
* Assert That no Back Office url is present on txt
*
* @param string $field
* @param string $text
* @return string
* @throws \Illuminate\Validation\ValidationException If url is a bo url.
*/
public static function assertNoInternalBoUrls(string $field, string $text): string
{
$routes = Route::getRoutes();
// * Url replace and email replace.
$text = preg_replace_callback(
// phpcs:ignore Generic.Files.LineLength.TooLong
'/(?P<url>(?:http[s]?:\/\/.)?(?:www\.)?[-a-zA-Z0-9@%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*))/',
function ($matches) use ($routes, $field) {
$match = collect($matches)->first() ?? '';
$url = $match;
try {
$request = Request::create($url);
// If a route is match then it do not throws exception.
if (
\parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) &&
trim($routes->match($request)->getPrefix() ?? '', '/') === 'bo'
) {
// Removes the matched url.
throw ValidationException::withMessages([
$field => ':attribute : Il est interdit de coller une url du back office dans ce champ'
]);
}
return $match;
} catch (NotFoundHttpException $e) {
return $match;
}
},
$text
);
return $text;
}
/**
* Assert That only external url is present on txt
*
* @param string $field
* @param string $text
* @return string
* @throws \Illuminate\Validation\ValidationException If url is a bo url.
*/
public static function assertNoInternalUrls(string $field, string $text): string
{
self::assertNoInternalBoUrls($field, $text);
$routes = Route::getRoutes();
// * Url replace and email replace.
$text = preg_replace_callback(
// phpcs:ignore Generic.Files.LineLength.TooLong
'/(?P<url>(?:http[s]?:\/\/.)?(?:www\.)?[-a-zA-Z0-9@%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*))/',
function ($matches) use ($routes, $field) {
$match = collect($matches)->first() ?? '';
$url = $match;
try {
$request = Request::create($url);
// If a route is match then it do not throws exception.
if (
\parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) &&
$routes->match($request)
) {
// Removes the matched url.
throw ValidationException::withMessages([
$field => sprintf(
':attribute : Il est interdit de coller une url de %s dans ce champ',
config('app.name')
)
]);
}
return $match;
} catch (NotFoundHttpException $e) {
return $match;
}
},
$text
);
return $text;
}
/**
* Mutltibyte string replace
* @param mixed $search
* @param mixed $replace
* @param mixed $subject
* @param integer $count
* @return mixed
*/
public static function mbReplace($search, $replace, $subject, int &$count = 0)
{
if (!is_array($search) && is_array($replace)) {
return false;
}
if (is_array($subject)) {
// Call mb_replace for each single string in $subject .
foreach ($subject as &$string) {
$string = &self::mbReplace($search, $replace, $string, $count);
}
} elseif (is_array($search)) {
if (!is_array($replace)) {
foreach ($search as &$string) {
$subject = self::mbReplace($string, $replace, $subject, $count);
}
} else {
$n = max(count($search), count($replace));
while ($n--) {
$subject = self::mbReplace(current($search), current($replace), $subject, $count);
next($search);
next($replace);
}
}
} else {
$parts = mb_split(preg_quote($search), $subject);
$count = count($parts) - 1;
$subject = implode($replace, $parts);
} //end if
return $subject;
}
/**
* Asserts that the field is unique
*
* @param string $table
* @param string $field
* @param mixed $value
* @param integer|null $id
* @param callable|null $query
* @return void
* @throws \Illuminate\Validation\ValidationException If the field is not unique.
*/
public static function assertFieldIsUnique(
string $table,
string $field,
$value,
?int $id = null,
?callable $query = null
) {
if (!$query) {
Validator::make([$field => $value], [
self::mbReplace('.', '\.', $field) => Rule::unique($table, $field)->ignore($id),
], [
self::mbReplace('.', '\.', "{$field}.unique")
=> trans('La valeur :value pour le champ :attribute est déjà utilisé', [
'attribute' => $field,
'value' => $value
])
])->validate();
return;
}
Validator::make([$field => $value], [
$field => Rule::unique($table)->where($query)->ignore($id),
], [
$field . '.unique' => trans('La valeur pour le champ :attribute est déjà utilisé', [
'attribute' => $field
])
])->validate();
}
/**
* Convert deeply an object to array
*
* @param array|object $input
* @return array
* @throws \RuntimeException If $input var is a scalar value.
*/
public static function objectToArray($input): array
{
// Only process if it's an object or array being passed to the function.
if (is_object($input) or is_array($input)) {
$ret = (array)$input;
foreach ($ret as &$item) {
// Recursively process EACH element only if not scalar.
$item = (is_object($item) or is_array($item)) ?
self::objectToArray($item) : $item;
}
return $ret;
} else {
throw new \RuntimeException('cannot handle $input of type ' . \gettype($input));
}
}
/**
* Convert deeply an array to object
*
* @param array|object $input
* @return object
* @throws \RuntimeException If $input var is a scalar value.
*/
public static function arrayToObject($input): object
{
// Only process if it's an object or array being passed to the function.
if (is_object($input) or is_array($input)) {
$ret = (object)$input;
foreach ($ret as &$item) {
// Recursively process EACH element only if not scalar.
$item = (is_object($item) or is_array($item)) ?
self::arrayToObject($item) : $item;
}
return $ret;
} else {
throw new \RuntimeException('cannot handle $input of type ' . \gettype($input));
}
}
}

View file

@ -3,9 +3,11 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
class User extends \TCG\Voyager\Models\User
class User extends Authenticatable
{
use HasFactory;
use Notifiable;
@ -16,7 +18,8 @@ class User extends \TCG\Voyager\Models\User
* @var array<int, string>
*/
protected $fillable = [
'name',
'firstname',
'lastname',
'email',
'password',
];
@ -39,4 +42,24 @@ class User extends \TCG\Voyager\Models\User
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* Perform any actions required after the model boots.
*
* @return void
*/
protected static function booted()
{
// * EVENT CLOSURES.
static::creating(function (User $user) {
if (Hash::needsRehash($user->password)) {
$user->password = Hash::make($user->password);
}
});
static::updating(function (User $user) {
if (Hash::needsRehash($user->password)) {
$user->password = Hash::make($user->password);
}
});
}
}

View file

@ -1,28 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Page extends Model
{
/**
* Page parts relationship
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function parts()
{
return $this->hasMany('App\Part');
}
/**
* Page snippets relationship
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function snippets()
{
return $this->hasMany('App\Snippet');
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Part extends Model
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
}

View file

@ -2,20 +2,14 @@
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
}
/**
* Bootstrap any application services.
*
@ -23,6 +17,47 @@ class AppServiceProvider extends ServiceProvider
*/
public function boot()
{
// * HTTPS FIX
URL::forceScheme('https');
// * HA PROXY FIX
App::singleton('clientIp', function () {
if (config('app.env') === 'local') {
return request()->getClientIp();
} else {
return request()->server('HTTP_X_FORWARDED_FOR') ??
request()->getClientIp();
}
});
// * LOCAL FORCE eg: for Carbon
setlocale(LC_ALL, \sprintf(
'%s_%s.UTF-8',
config('app.locale'),
\strtoupper(config('app.locale'))
));
Carbon::setLocale(config('app.locale'));
$this->sharetoView();
}
/**
* Share Vars to view
*
* @return void
*/
private function sharetoView()
{
if (!app()->runningInConsole()) {
// * FORCE BOOTSTRAP PAGINATOR (or custom if in front)
// Early boot, request wont be filled as expected.
if (collect(explode('/', \request()->getPathInfo()))->get(1) === 'bo') {
Paginator::useBootstrap();
} else {
// FIXME: change this if needed.
Paginator::useBootstrap();
// Paginator::defaultview('fo.modules.pagination'); .
}
}
}
}

View file

@ -6,13 +6,6 @@ use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvid
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [];
/**
* Register any authentication / authorization services.
*

View file

@ -27,14 +27,4 @@ class EventServiceProvider extends ServiceProvider
public function boot()
{
}
/**
* Determine if events and listeners should be automatically discovered.
*
* @return boolean
*/
public function shouldDiscoverEvents()
{
return false;
}
}

View file

@ -17,7 +17,7 @@ class RouteServiceProvider extends ServiceProvider
*
* @var string
*/
public const HOME = '/home';
public const HOME = '/';
/**
* Define your route model bindings, pattern filters, etc.
@ -28,15 +28,15 @@ class RouteServiceProvider extends ServiceProvider
{
$this->configureRateLimiting();
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
$this->cspReportRoute();
$this->routes(function () {
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web-bo.php'));
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web-fo.php'));
});
}
@ -49,7 +49,49 @@ class RouteServiceProvider extends ServiceProvider
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
return Limit::perMinute(150)->by(optional($request->user())->id ?: app('clientIp'));
});
RateLimiter::for('web', function (Request $request) {
return Limit::perMinute(150)->by(optional($request->user())->id ?: app('clientIp'));
});
RateLimiter::for('credentials', function (Request $request) {
return Limit::perMinute(30)->by(optional($request->user())->id ?: $request->ip());
});
}
/**
* * Register CSP report URI
*
* Put this function inside RouteServiceProvider,
* and call it in RouteServiceProvider::boot
*
* @return void
*/
private function cspReportRoute()
{
// * CSP REPORT URI, Please add /csp-report to VerifyCsrfToken $except middleware
\Illuminate\Support\Facades\Route::post('/csp-report', function () {
$isCspRequest = request()->header('Content-Type') === 'application/csp-report';
if (!$isCspRequest or !request()->json('csp-report') or !is_array(request()->json('csp-report'))) {
abort(401);
}
// * Flatten if needed
$cspReport = collect(request()->json('csp-report'))
->flatMap(function ($v, $k) {
return [$k => is_array($v) ? collect($v)->flatten()->implode(', ') : $v];
})->all();
// * Filter array keys
$cspReport = collect(array_intersect_key($cspReport, [
'blocked-uri' => '', 'document-uri' => '', 'original-policy' => '',
'referrer' => '', 'violated-directive' => ''
]));
\Illuminate\Support\Facades\Log::warning(sprintf(
"CSP REPORT for %s : \n %s",
$cspReport->get('document-uri'),
$cspReport->implode("\n")
));
})->middleware('throttle:5,2')
->withoutMiddleware(\App\Http\Middleware\VerifyCsrfToken::class)
->name('cspReportUri');
}
}

View file

@ -0,0 +1,78 @@
<?php
namespace App\Providers;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\Finder\SplFileInfo;
class TranslationServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
foreach ($this->collectLocalesStrings() as $locale) {
// * Suported locales
Cache::rememberForever(sprintf('translations.%s', $locale), function () use ($locale) {
$translations = [
'php' => $this->phpTranslations($locale),
'json' => $this->jsonTranslations($locale),
];
return $translations;
});
}
}
/**
* Gather provided langs checking from files
*
* @return Collection
*/
private function collectLocalesStrings(): Collection
{
return collect(File::allFiles(resource_path('lang/')))->flatMap(function (SplFileInfo $file) {
if ($file->getRelativePath() and \strpos($file->getRelativePath(), 'vendor') !== 0) {
return [$file->getRelativePath() => ''];
}
})->keys();
}
/**
* Gather all php translations
*
* @param string $locale
* @return array
*/
private function phpTranslations(string $locale): array
{
$path = resource_path("lang/$locale");
return collect(File::allFiles($path))->flatMap(function ($file) use ($locale) {
$translation = $file->getBasename('.php');
return [$translation => trans($translation, [], $locale)];
})->all();
}
/**
* Gather json translations
*
* @param string $locale
* @return array
*/
private function jsonTranslations(string $locale): array
{
$path = resource_path("lang/$locale.json");
if (is_string($path) && is_readable($path)) {
return json_decode(file_get_contents($path), true) ?? [];
}
return [];
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Recipe extends Model
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class RetailGroup extends Model
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Retailregion extends Model
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class SalesRegion extends Model
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Slider extends Model
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Snippet extends Model
{
}

View file

@ -1,9 +0,0 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Store extends Model
{
}

View file

View file

View file

View file

@ -1,63 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class ContentPart extends Component
{
/**
* Part variable
*
* @var mixed
*/
private $part;
/**
* odd variable
*
* @var integer
*/
private $odd;
/**
* bgcolor variable
*
* @var mixed
*/
private $bgcolor;
/**
* Create a new component instance.
*
* @param mixed $part
* @param integer $odd
* @param mixed $bgcolor
* @return void
*/
public function __construct(mixed $part = null, int $odd = 0, mixed $bgcolor = null)
{
$this->part = null;
if ($part != null) {
$this->part = $part;
}
$this->odd = $odd;
if ($bgcolor != null) {
$this->bgcolor = $bgcolor;
}
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
$part = $this->part;
$odd = $this->odd;
$bgcolor = $this->bgcolor;
return view('components.content-part', compact(['part', 'odd', 'bgcolor']));
}
}

View file

@ -1,63 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class ContentSnippet extends Component
{
/**
* snippet variable
*
* @var mixed
*/
private $snippet;
/**
* odd variable
*
* @var integer
*/
private $odd;
/**
* bgcolor variable
*
* @var mixed
*/
private $bgcolor;
/**
* Create a new component instance.
*
* @param mixed $snippet
* @param integer $odd
* @param mixed $bgcolor
* @return void
*/
public function __construct(mixed $snippet = null, int $odd = 0, mixed $bgcolor = null)
{
$this->snippet = null;
if ($snippet != null) {
$this->snippet = $snippet;
}
$this->odd = $odd;
if ($bgcolor != null) {
$this->bgcolor = $bgcolor;
}
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
$snippet = $this->snippet;
$odd = $this->odd;
$bgcolor = $this->bgcolor;
return view('components.content-snippet', compact(['snippet', 'odd', 'bgcolor']));
}
}

View file

@ -1,18 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class ProductCard extends Component
{
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.product-card');
}
}

View file

@ -1,44 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use App\Recipe;
class RecipeCard extends Component
{
/**
* @var integer
*/
public $id;
/**
* Recipe model
*
* @var \App\Recipe
*/
public $recipe;
/**
* Create a new component instance.
*
* @param integer $id
* @return void
*/
public function __construct(int $id)
{
$this->recipe = Recipe::where('id', $id)->first();
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
$recipe = $this->recipe;
return view('components.recipe-card', compact('recipe'));
}
}

View file

@ -1,44 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use App\Recipe;
class RecipeCardSmall extends Component
{
/**
* @var integer
*/
public $id;
/**
* Recipe model
*
* @var \App\Recipe
*/
public $recipe;
/**
* Create a new component instance.
*
* @param integer $id
* @return void
*/
public function __construct(int $id)
{
$this->recipe = Recipe::where('id', $id)->first();
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
$recipe = $this->recipe;
return view('components.recipe-card-small', compact('recipe'));
}
}

View file

@ -1,45 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use App\Product;
class RecipeProductStoerer extends Component
{
/**
* id variable
*
* @var integer
*/
public $id;
/**
* product variable
*
* @var \App\Product
*/
public $product;
/**
* Create a new component instance.
*
* @param integer $id
* @return void
*/
public function __construct(int $id)
{
$this->product = Product::where('id', $id)->first();
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
$product = $this->product;
return view('components.recipe-product-stoerer', compact('product'));
}
}

View file

@ -1,63 +0,0 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use App\Recipe;
class RecipeWidget extends Component
{
/**
* limit variable
*
* @var mixed
*/
private $limit;
/**
* id variable
*
* @var mixed
*/
private $id;
/**
* recipes variable
*
* @var \App\Recipe
*/
private $recipes;
/**
* Create a new component instance.
*
* @param mixed $limit
* @param mixed $id
* @return void
*/
public function __construct(mixed $limit, mixed $id = null)
{
$this->limit = 3;
if ($limit != null) {
$this->limit = $limit;
}
if ($id != null) {
$this->id = $id;
$this->recipes = Recipe::where('live', '1')
->where('id', '!=', $this->id)->inRandomOrder()->limit($this->limit)->get();
} else {
$this->recipes = Recipe::where('live', '1')->inRandomOrder()->limit($this->limit)->get();
}
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
$recipes = $this->recipes;
return view('components.recipe-widget', compact('recipes'));
}
}

0
artisan Normal file → Executable file
View file

View file

@ -2,27 +2,31 @@
"name": "laravel/laravel",
"type": "project",
"description": "The Laravel Framework.",
"keywords": ["framework", "laravel"],
"keywords": [
"framework",
"laravel"
],
"license": "MIT",
"require": {
"php": "^8.0.2",
"php": "^8.1",
"diglactic/laravel-breadcrumbs": "^8.0",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^9.2",
"laravel/tinker": "^2.7",
"ldc/web-admin-secure-laravel": "^1.0",
"ldc/web-status-checker-laravel": "^1.0",
"sentry/sentry-laravel": "^3.1",
"simplesoftwareio/simple-qrcode": "^4.2",
"tcg/voyager": "^1.5"
"laravel/framework": "^10.0",
"laravel/tinker": "^2.8",
"laravel/ui": "^4.2",
"mews/purifier": "^3.4"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",
"laravel/sail": "^1.0.1",
"kitloong/laravel-migrations-generator": "^6.8",
"krlove/eloquent-model-generator": "dev-l10-compatibility",
"laravel/pint": "^1.0",
"laravel/sail": "^1.18",
"mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^6.1",
"phpunit/phpunit": "^9.5.10",
"slevomat/coding-standard": "^8.6",
"spatie/laravel-ignition": "^1.0"
"nunomaduro/collision": "^7.0",
"phpunit/phpunit": "^10.0",
"spatie/laravel-ignition": "^2.0",
"thedoctor0/laravel-factory-generator": "^1.2"
},
"autoload": {
"psr-4": {
@ -31,6 +35,12 @@
"Database\\Seeders\\": "database/seeders/"
}
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/laravel-shift/eloquent-model-generator.git"
}
],
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
@ -61,15 +71,10 @@
"preferred-install": "dist",
"sort-packages": true,
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
"pestphp/pest-plugin": true,
"php-http/discovery": true
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"repositories": {
"gitlab.com/16669037": {
"type": "composer",
"url": "https://gitlab.com/api/v4/group/16669037/-/packages/composer/packages.json"
}
}
"minimum-stability": "stable",
"prefer-stable": true
}

5668
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,6 @@
<?php
use Illuminate\Support\Facades\Facade;
return [
/*
|--------------------------------------------------------------------------
| Application Name
@ -56,7 +53,7 @@ return [
'url' => env('APP_URL', 'http://localhost'),
'asset_url' => env('ASSET_URL'),
'asset_url' => env('ASSET_URL', null),
/*
|--------------------------------------------------------------------------
@ -82,7 +79,7 @@ return [
|
*/
'locale' => 'de',
'locale' => 'fr',
/*
|--------------------------------------------------------------------------
@ -108,7 +105,7 @@ return [
|
*/
'faker_locale' => 'en_US',
'faker_locale' => 'fr_FR',
/*
|--------------------------------------------------------------------------
@ -138,9 +135,10 @@ return [
'providers' => [
/**
/*
* Laravel Framework Service Providers...
*/
Illuminate\Auth\AuthServiceProvider::class,
Illuminate\Broadcasting\BroadcastServiceProvider::class,
Illuminate\Bus\BusServiceProvider::class,
@ -163,19 +161,20 @@ return [
Illuminate\Translation\TranslationServiceProvider::class,
Illuminate\Validation\ValidationServiceProvider::class,
Illuminate\View\ViewServiceProvider::class,
SimpleSoftwareIO\QrCode\QrCodeServiceProvider::class,
/**
/*
* Package Service Providers...
*/
/**
/*
* Application Service Providers...
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\TranslationServiceProvider::class
],
@ -190,8 +189,44 @@ return [
|
*/
'aliases' => Facade::defaultAliases()->merge([
'QrCode' => SimpleSoftwareIO\QrCode\Facades\QrCode::class,
])->toArray(),
'aliases' => [
'App' => Illuminate\Support\Facades\App::class,
'Arr' => Illuminate\Support\Arr::class,
'Artisan' => Illuminate\Support\Facades\Artisan::class,
'Auth' => Illuminate\Support\Facades\Auth::class,
'Blade' => Illuminate\Support\Facades\Blade::class,
'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
'Bus' => Illuminate\Support\Facades\Bus::class,
'Cache' => Illuminate\Support\Facades\Cache::class,
'Config' => Illuminate\Support\Facades\Config::class,
'Cookie' => Illuminate\Support\Facades\Cookie::class,
'Crypt' => Illuminate\Support\Facades\Crypt::class,
'Date' => Illuminate\Support\Facades\Date::class,
'DB' => Illuminate\Support\Facades\DB::class,
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
'Event' => Illuminate\Support\Facades\Event::class,
'File' => Illuminate\Support\Facades\File::class,
'Gate' => Illuminate\Support\Facades\Gate::class,
'Hash' => Illuminate\Support\Facades\Hash::class,
'Http' => Illuminate\Support\Facades\Http::class,
'Js' => Illuminate\Support\Js::class,
'Lang' => Illuminate\Support\Facades\Lang::class,
'Log' => Illuminate\Support\Facades\Log::class,
'Mail' => Illuminate\Support\Facades\Mail::class,
'Notification' => Illuminate\Support\Facades\Notification::class,
'Password' => Illuminate\Support\Facades\Password::class,
'Queue' => Illuminate\Support\Facades\Queue::class,
'RateLimiter' => Illuminate\Support\Facades\RateLimiter::class,
'Redirect' => Illuminate\Support\Facades\Redirect::class,
'Request' => Illuminate\Support\Facades\Request::class,
'Response' => Illuminate\Support\Facades\Response::class,
'Route' => Illuminate\Support\Facades\Route::class,
'Schema' => Illuminate\Support\Facades\Schema::class,
'Session' => Illuminate\Support\Facades\Session::class,
'Storage' => Illuminate\Support\Facades\Storage::class,
'Str' => Illuminate\Support\Str::class,
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
],
];

View file

@ -14,7 +14,7 @@ return [
*/
'defaults' => [
'guard' => 'web',
'guard' => 'frontend',
'passwords' => 'users',
],
@ -36,10 +36,16 @@ return [
*/
'guards' => [
'web' => [
'backend' => [
'driver' => 'session',
'provider' => 'users',
],
'frontend' => [
'driver' => 'session',
// ! Remplacer "users" par le model authenticable voulu
'provider' => 'users',
],
],
/*

78
config/breadcrumbs.php Normal file
View file

@ -0,0 +1,78 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| View Name
|--------------------------------------------------------------------------
|
| Choose a view to display when Breadcrumbs::render() is called.
| Built in templates are:
|
| - 'breadcrumbs::bootstrap5' - Bootstrap 5
| - 'breadcrumbs::bootstrap4' - Bootstrap 4
| - 'breadcrumbs::bulma' - Bulma
| - 'breadcrumbs::foundation6' - Foundation 6
| - 'breadcrumbs::json-ld' - JSON-LD Structured Data
| - 'breadcrumbs::materialize' - Materialize
| - 'breadcrumbs::tailwind' - Tailwind CSS
| - 'breadcrumbs::uikit' - UIkit
|
| Or a custom view, e.g. '_partials/breadcrumbs'.
|
*/
'view' => 'breadcrumbs/breadrcumb-layout',
/*
|--------------------------------------------------------------------------
| Breadcrumbs File(s)
|--------------------------------------------------------------------------
|
| The file(s) where breadcrumbs are defined. e.g.
|
| - base_path('routes/breadcrumbs.php')
| - glob(base_path('breadcrumbs/*.php'))
|
*/
'files' => [
base_path('routes/breadcrumbs-bo.php'),
base_path('routes/breadcrumbs-fo.php'),
],
/*
|--------------------------------------------------------------------------
| Exceptions
|--------------------------------------------------------------------------
|
| Determine when to throw an exception.
|
*/
// * When route-bound breadcrumbs are used but the current route doesn't have a name (UnnamedRouteException)
'unnamed-route-exception' => true,
// * When route-bound breadcrumbs are used and the matching breadcrumb doesn't exist (InvalidBreadcrumbException)
'missing-route-bound-breadcrumb-exception' => true,
// * When a named breadcrumb is used but doesn't exist (InvalidBreadcrumbException)
'invalid-named-breadcrumb-exception' => true,
/*
|--------------------------------------------------------------------------
| Classes
|--------------------------------------------------------------------------
|
| Subclass the default classes for more advanced customisations.
|
*/
// * Manager
'manager-class' => Diglactic\Breadcrumbs\Manager::class,
// * Generator
'generator-class' => Diglactic\Breadcrumbs\Generator::class,
];

View file

@ -39,10 +39,6 @@ return [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
],
'client_options' => [
// phpcs:ignore
// Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
],
],
'ably' => [

View file

@ -62,8 +62,7 @@ return [
env('MEMCACHED_PASSWORD'),
],
'options' => [
// phpcs:ignore
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
// Memcached::OPT_CONNECT_TIMEOUT => 2000, .
],
'servers' => [
[
@ -100,12 +99,12 @@ return [
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing the APC, database, memcached, Redis, or DynamoDB cache
| stores there might be other applications using the same cache. For
| that reason, you may prefix every cache key to avoid collisions.
| When utilizing a RAM based store such as APC or Memcached, there might
| be other applications utilizing the same cache. So, we'll specify a
| value to get prefixed to all our keys so we can avoid collisions.
|
*/
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache_'),
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache'),
];

View file

@ -74,7 +74,7 @@ return [
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
'search_path' => 'public',
'schema' => 'public',
'sslmode' => 'prefer',
],
@ -89,9 +89,6 @@ return [
'charset' => 'utf8',
'prefix' => '',
'prefix_indexes' => true,
// phpcs:ignore
// 'encrypt' => env('DB_ENCRYPT', 'yes'),
// 'trust_server_certificate' => env('DB_TRUST_SERVER_CERTIFICATE', 'false'),
],
],
@ -132,8 +129,7 @@ return [
'default' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_DB', '0'),
],
@ -141,8 +137,7 @@ return [
'cache' => [
'url' => env('REDIS_URL'),
'host' => env('REDIS_HOST', '127.0.0.1'),
'username' => env('REDIS_USERNAME'),
'password' => env('REDIS_PASSWORD'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', '6379'),
'database' => env('REDIS_CACHE_DB', '1'),
],

View file

@ -13,7 +13,7 @@ return [
|
*/
'default' => env('FILESYSTEM_DISK', 'local'),
'default' => env('FILESYSTEM_DRIVER', 'local'),
/*
|--------------------------------------------------------------------------
@ -22,7 +22,7 @@ return [
|
| Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have
| been set up for each driver as an example of the required values.
| been setup for each driver as an example of the required options.
|
| Supported Drivers: "local", "ftp", "sftp", "s3"
|
@ -33,7 +33,6 @@ return [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'throw' => false,
],
'public' => [
@ -41,7 +40,6 @@ return [
'root' => storage_path('app/public'),
'url' => env('APP_URL') . '/storage',
'visibility' => 'public',
'throw' => false,
],
's3' => [
@ -53,7 +51,6 @@ return [
'url' => env('AWS_URL'),
'endpoint' => env('AWS_ENDPOINT'),
'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
'throw' => false,
],
],

View file

@ -50,7 +50,7 @@ return [
'channels' => [
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
'channels' => ['single', 'sentry'],
'ignore_exceptions' => false,
],
@ -60,6 +60,11 @@ return [
'level' => env('LOG_LEVEL', 'debug'),
],
'sentry' => [
'driver' => 'sentry',
'level' => env('LOG_LEVEL', 'error'),
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
@ -78,11 +83,10 @@ return [
'papertrail' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => env('LOG_PAPERTRAIL_HANDLER', SyslogUdpHandler::class),
'handler' => SyslogUdpHandler::class,
'handler_with' => [
'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'),
'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
],
],

View file

@ -42,6 +42,7 @@ return [
'username' => env('MAIL_USERNAME'),
'password' => env('MAIL_PASSWORD'),
'timeout' => null,
'auth_mode' => null,
],
'ses' => [
@ -58,7 +59,7 @@ return [
'sendmail' => [
'transport' => 'sendmail',
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'),
'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -t -i'),
],
'log' => [

122
config/purifier.php Normal file
View file

@ -0,0 +1,122 @@
<?php
/**
* Ok, glad you are here
* first we get a config instance, and set the settings
* $config = HTMLPurifier_Config::createDefault();
* $config->set('Core.Encoding', $this->config->get('purifier.encoding'));
* $config->set('Cache.SerializerPath', $this->config->get('purifier.cachePath'));
* if ( ! $this->config->get('purifier.finalize')) {
* $config->autoFinalize = false;
* }
* $config->load [$this->getConfig());
*
* You must NOT delete the default settings
* anything in settings should be compacted with params that needed to instance HTMLPurifier_Config.
*
* @link http://htmlpurifier.org/live/configdoc/plain.html
*/
// phpcs:disable Generic.Files.LineLength.TooLong
return [
'encoding' => 'UTF-8',
'finalize' => true,
'cachePath' => storage_path('app/purifier'),
'cacheFileMode' => 0755,
'settings' => [
'default' => [
'HTML.SafeIframe' => true,
// * For iframes
'URI.SafeIframeRegexp' => "%^(http://|https://|//)(www.youtube.com/embed/|player.vimeo.com/video/|vimeo.com/)%",
'HTML.Doctype' => 'HTML 4.01 Transitional',
// TODO: Rules en FULL CKEDITOR.
// * Legacy filter en full avec safe legacy.
// 'HTML.Allowed' => 'h1[style],h2[style],h3[style],h4[style],h5[style],h6[style],figure[class|style],oembed[url],div[style],b,strong,i,em,u,a[href|title|target|rel],ul[style],ol[style],dl[style],li,p[style],br,span[style|class],img[width|height|alt|src|style|class|title],iframe[src|width|height|class|frameborder|style],table[style|align|border|cellspacing|cellpadding|width],thead,tbody,th[colspan|align|valign|style],tr[align|valign|style],td[style|colspan|rowspan|scope|align|valign],hr,dl,dt',
// * Restricted basics.
'HTML.Allowed' => 'br,p[style],b,u,i,a[href|title|target|rel],strong,span[class],ul,ol,li,h2,h3,h4,hr',
// * Legacy filter en full avec safe legacy.
// 'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align,list-style-type,float,width,height,vertical-align,border-color',
// * Restricted basics.
'CSS.AllowedProperties' => 'text-align',
'AutoFormat.AutoParagraph' => false,
'AutoFormat.RemoveEmpty' => false,
'AutoFormat.RemoveEmpty.RemoveNbsp' => false,
],
'custom_definition' => [
'id' => 'html5-definitions',
'rev' => 1,
'debug' => true,
'elements' => [
// * http://developers.whatwg.org/sections.html
['section', 'Block', 'Flow', 'Common'],
['nav', 'Block', 'Flow', 'Common'],
['article', 'Block', 'Flow', 'Common'],
['aside', 'Block', 'Flow', 'Common'],
['header', 'Block', 'Flow', 'Common'],
['footer', 'Block', 'Flow', 'Common'],
// * Content model actually excludes several tags, not modelled here
['address', 'Block', 'Flow', 'Common'],
['hgroup', 'Block', 'Required: h1 | h2 | h3 | h4 | h5 | h6', 'Common'],
// * http://developers.whatwg.org/grouping-content.html
['figure', 'Block', 'Optional: (figcaption, Flow) | (Flow, figcaption) | Flow', 'Common'],
['figcaption', 'Inline', 'Flow', 'Common'],
['oembed', 'Inline', 'Flow', 'Common'],
// * http://developers.whatwg.org/the-video-element.html#the-video-element
['video', 'Block', 'Optional: (source, Flow) | (Flow, source) | Flow', 'Common', [
'src' => 'URI',
'type' => 'Text',
'width' => 'Length',
'height' => 'Length',
'poster' => 'URI',
'preload' => 'Enum#auto,metadata,none',
'controls' => 'Bool',
]],
['source', 'Block', 'Flow', 'Common', [
'src' => 'URI',
'type' => 'Text',
]],
// * http://developers.whatwg.org/text-level-semantics.html
['s', 'Inline', 'Inline', 'Common'],
['var', 'Inline', 'Inline', 'Common'],
['sub', 'Inline', 'Inline', 'Common'],
['sup', 'Inline', 'Inline', 'Common'],
['mark', 'Inline', 'Inline', 'Common'],
['wbr', 'Inline', 'Empty', 'Core'],
// * http://developers.whatwg.org/edits.html
['ins', 'Block', 'Flow', 'Common', ['cite' => 'URI', 'datetime' => 'CDATA']],
['del', 'Block', 'Flow', 'Common', ['cite' => 'URI', 'datetime' => 'CDATA']],
],
'attributes' => [
['iframe', 'allowfullscreen', 'Bool'],
['table', 'height', 'Text'],
['td', 'border', 'Text'],
['th', 'border', 'Text'],
['tr', 'width', 'Text'],
['tr', 'height', 'Text'],
['tr', 'border', 'Text'],
['figure', 'class', 'Text'],
['figure', 'style', 'Text'],
['oembed', 'url', 'Text'],
['span', 'style', 'Text'],
['img', 'style', 'Text'],
],
],
'custom_attributes' => [
['a', 'target', 'Enum#_blank,_self,_target,_top'],
['ol', 'style', 'Text'],
['figure', 'style', 'Text'],
['img', 'style', 'Text'],
['span', 'style', 'Text'],
['oembed', 'url', 'Text'],
],
'custom_elements' => [
['u', 'Inline', 'Inline', 'Common'],
['oembed', 'Inline', 'Inline', 'Common'],
],
],
];

View file

@ -4,7 +4,7 @@ return [
'dsn' => env('SENTRY_LARAVEL_DSN', env('SENTRY_DSN')),
// The release version of your application
// The release version of your application.
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')).
'release' => env('SENTRY_RELEASE'),
@ -51,12 +51,11 @@ return [
'missing_routes' => false,
],
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#send-default-pii.
'send_default_pii' => env('SENTRY_SEND_DEFAULT_PII', false),
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate
// @see: https://docs.sentry.io/platforms/php/guides/laravel/configuration/options/#traces-sample-rate.
'traces_sample_rate' => env('SENTRY_TRACES_SAMPLE_RATE') === null ? null : (float)env('SENTRY_TRACES_SAMPLE_RATE'),
'before_send' => [\App\Lib\ExceptionsHelper::class, 'sentryEventHandler'],
'before_send' => [\App\Lib\Helpers\ExceptionsHelper::class, 'sentryEventHandler'],
];

View file

@ -18,7 +18,6 @@ return [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
'scheme' => 'https',
],
'postmark' => [
@ -31,10 +30,4 @@ return [
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'google' => [
'maps' => [
'key' => env('GOOGLE_MAPS_KEY')
]
]
];

View file

@ -72,7 +72,7 @@ return [
|
*/
'connection' => env('SESSION_CONNECTION'),
'connection' => env('SESSION_CONNECTION', null),
/*
|--------------------------------------------------------------------------
@ -100,7 +100,7 @@ return [
|
*/
'store' => env('SESSION_STORE'),
'store' => env('SESSION_STORE', null),
/*
|--------------------------------------------------------------------------
@ -155,7 +155,7 @@ return [
|
*/
'domain' => env('SESSION_DOMAIN'),
'domain' => env('SESSION_DOMAIN', null),
/*
|--------------------------------------------------------------------------

View file

@ -1,247 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| User config
|--------------------------------------------------------------------------
|
| Here you can specify voyager user configs
|
*/
'user' => [
'add_default_role_on_register' => true,
'default_role' => 'user',
'default_avatar' => 'users/default.png',
'redirect' => '/admin',
],
/*
|--------------------------------------------------------------------------
| Controllers config
|--------------------------------------------------------------------------
|
| Here you can specify voyager controller settings
|
*/
'controllers' => [
'namespace' => 'TCG\\Voyager\\Http\\Controllers',
],
/*
|--------------------------------------------------------------------------
| Models config
|--------------------------------------------------------------------------
|
| Here you can specify default model namespace when creating BREAD.
| Must include trailing backslashes. If not defined the default application
| namespace will be used.
|
*/
'models' => [
// phpcs:ignore
// 'namespace' => 'App\\Models\\',
],
/*
|--------------------------------------------------------------------------
| Storage Config
|--------------------------------------------------------------------------
|
| Here you can specify attributes related to your application file system
|
*/
'storage' => [
'disk' => 'public',
],
/*
|--------------------------------------------------------------------------
| Media Manager
|--------------------------------------------------------------------------
|
| Here you can specify if media manager can show hidden files like(.gitignore)
|
*/
'hidden_files' => false,
/*
|--------------------------------------------------------------------------
| Database Config
|--------------------------------------------------------------------------
|
| Here you can specify voyager database settings
|
*/
'database' => [
'tables' => [
'hidden' => [
'migrations', 'data_rows', 'data_types', 'menu_items', 'password_resets', 'permission_role', 'settings'
],
],
'autoload_migrations' => true,
],
/*
|--------------------------------------------------------------------------
| Multilingual configuration
|--------------------------------------------------------------------------
|
| Here you can specify if you want Voyager to ship with support for
| multilingual and what locales are enabled.
|
*/
'multilingual' => [
/**
* Set whether or not the multilingual is supported by the BREAD input.
*/
'enabled' => false,
/**
* Select default language
*/
'default' => 'en',
/**
* Select languages that are supported.
*/
'locales' => [
'en',
// 'pt',
],
],
/*
|--------------------------------------------------------------------------
| Dashboard config
|--------------------------------------------------------------------------
|
| Here you can modify some aspects of your dashboard
|
*/
'dashboard' => [
// Add custom list items to navbar's dropdown.
'navbar_items' => [
'voyager::generic.profile' => [
'route' => 'voyager.profile',
'classes' => 'class-full-of-rum',
'icon_class' => 'voyager-person',
],
'voyager::generic.home' => [
'route' => '/',
'icon_class' => 'voyager-home',
'target_blank' => true,
],
'voyager::generic.logout' => [
'route' => 'voyager.logout',
'icon_class' => 'voyager-power',
],
],
'widgets' => [
],
],
/*
|--------------------------------------------------------------------------
| Automatic Procedures
|--------------------------------------------------------------------------
|
| When a change happens on Voyager, we can automate some routines.
|
*/
'bread' => [
// When a BREAD is added, create the Menu item using the BREAD properties.
'add_menu_item' => true,
// Which menu add item to.
'default_menu' => 'admin',
// When a BREAD is added, create the related Permission.
'add_permission' => true,
// Which role add premissions to.
'default_role' => 'admin',
],
/*
|--------------------------------------------------------------------------
| UI Generic Config
|--------------------------------------------------------------------------
|
| Here you change some of the Voyager UI settings.
|
*/
'primary_color' => '#22A7F0',
'show_dev_tips' => true,
// Here you can specify additional assets you would like to be included in the master.blade.
'additional_css' => [
// 'css/custom.css',
],
'additional_js' => [
// 'js/custom.js',
],
'googlemaps' => [
'key' => env('GOOGLE_MAPS_KEY', ''),
'center' => [
'lat' => env('GOOGLE_MAPS_DEFAULT_CENTER_LAT', '32.715738'),
'lng' => env('GOOGLE_MAPS_DEFAULT_CENTER_LNG', '-117.161084'),
],
'zoom' => env('GOOGLE_MAPS_DEFAULT_ZOOM', 11),
],
/*
|--------------------------------------------------------------------------
| Model specific settings
|--------------------------------------------------------------------------
|
| Here you change some model specific settings
|
*/
'settings' => [
// Enables Laravel cache method for
// Storing cache values between requests.
'cache' => false,
],
// Activate compass when environment is NOT local.
'compass_in_production' => false,
'media' => [
// The allowed mimetypes to be uploaded through the media-manager.
'allowed_mimetypes' => [
'image/jpeg',
'image/png',
'image/gif',
'image/bmp',
'image/webp',
'image/svg+xml',
'video/mp4',
],
// Path for media-manager. Relative to the filesystem.
'path' => '/',
'show_folders' => true,
'allow_upload' => true,
'allow_move' => true,
'allow_delete' => true,
'allow_create_folder' => true,
'allow_rename' => true,
],
];

View file

@ -5,22 +5,21 @@ namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User>
*/
class UserFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->name(),
'firstname' => $this->faker->firstname(),
'lastname' => $this->faker->lastname(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
// * password
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
'remember_token' => Str::random(10),
];
@ -29,7 +28,7 @@ class UserFactory extends Factory
/**
* Indicate that the model's email address should be unverified.
*
* @return static
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public function unverified()
{

View file

@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
@ -15,7 +15,8 @@ return new class extends Migration
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('firstname');
$table->string('lastname');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
@ -33,4 +34,4 @@ return new class extends Migration
{
Schema::dropIfExists('users');
}
};
}

View file

@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
class CreatePasswordResetsTable extends Migration
{
/**
* Run the migrations.
@ -29,4 +29,4 @@ return new class extends Migration
{
Schema::dropIfExists('password_resets');
}
};
}

View file

@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
class CreateFailedJobsTable extends Migration
{
/**
* Run the migrations.
@ -33,4 +33,4 @@ return new class extends Migration
{
Schema::dropIfExists('failed_jobs');
}
};
}

View file

@ -1,36 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('personal_access_tokens');
}
};

View file

@ -1,372 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\DataRow;
use TCG\Voyager\Models\DataType;
class DataRowsTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*/
public function run()
{
$userDataType = DataType::where('slug', 'users')->firstOrFail();
$menuDataType = DataType::where('slug', 'menus')->firstOrFail();
$roleDataType = DataType::where('slug', 'roles')->firstOrFail();
$dataRow = $this->dataRow($userDataType, 'id');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'number',
'display_name' => __('voyager::seeders.data_rows.id'),
'required' => 1,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 1,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'name');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'text',
'display_name' => __('voyager::seeders.data_rows.name'),
'required' => 1,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 1,
'order' => 2,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'email');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'text',
'display_name' => __('voyager::seeders.data_rows.email'),
'required' => 1,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 1,
'order' => 3,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'password');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'password',
'display_name' => __('voyager::seeders.data_rows.password'),
'required' => 1,
'browse' => 0,
'read' => 0,
'edit' => 1,
'add' => 1,
'delete' => 0,
'order' => 4,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'remember_token');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'text',
'display_name' => __('voyager::seeders.data_rows.remember_token'),
'required' => 0,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 5,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'created_at');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'timestamp',
'display_name' => __('voyager::seeders.data_rows.created_at'),
'required' => 0,
'browse' => 1,
'read' => 1,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 6,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'updated_at');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'timestamp',
'display_name' => __('voyager::seeders.data_rows.updated_at'),
'required' => 0,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 7,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'avatar');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'image',
'display_name' => __('voyager::seeders.data_rows.avatar'),
'required' => 0,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 1,
'order' => 8,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'user_belongsto_role_relationship');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'relationship',
'display_name' => __('voyager::seeders.data_rows.role'),
'required' => 0,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 0,
'details' => [
'model' => 'TCG\\Voyager\\Models\\Role',
'table' => 'roles',
'type' => 'belongsTo',
'column' => 'role_id',
'key' => 'id',
'label' => 'display_name',
'pivot_table' => 'roles',
'pivot' => 0,
],
'order' => 10,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'user_belongstomany_role_relationship');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'relationship',
'display_name' => __('voyager::seeders.data_rows.roles'),
'required' => 0,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 0,
'details' => [
'model' => 'TCG\\Voyager\\Models\\Role',
'table' => 'roles',
'type' => 'belongsToMany',
'column' => 'id',
'key' => 'id',
'label' => 'display_name',
'pivot_table' => 'user_roles',
'pivot' => '1',
'taggable' => '0',
],
'order' => 11,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'settings');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'hidden',
'display_name' => 'Settings',
'required' => 0,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 12,
])->save();
}
$dataRow = $this->dataRow($menuDataType, 'id');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'number',
'display_name' => __('voyager::seeders.data_rows.id'),
'required' => 1,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 1,
])->save();
}
$dataRow = $this->dataRow($menuDataType, 'name');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'text',
'display_name' => __('voyager::seeders.data_rows.name'),
'required' => 1,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 1,
'order' => 2,
])->save();
}
$dataRow = $this->dataRow($menuDataType, 'created_at');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'timestamp',
'display_name' => __('voyager::seeders.data_rows.created_at'),
'required' => 0,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 3,
])->save();
}
$dataRow = $this->dataRow($menuDataType, 'updated_at');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'timestamp',
'display_name' => __('voyager::seeders.data_rows.updated_at'),
'required' => 0,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 4,
])->save();
}
$dataRow = $this->dataRow($roleDataType, 'id');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'number',
'display_name' => __('voyager::seeders.data_rows.id'),
'required' => 1,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 1,
])->save();
}
$dataRow = $this->dataRow($roleDataType, 'name');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'text',
'display_name' => __('voyager::seeders.data_rows.name'),
'required' => 1,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 1,
'order' => 2,
])->save();
}
$dataRow = $this->dataRow($roleDataType, 'created_at');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'timestamp',
'display_name' => __('voyager::seeders.data_rows.created_at'),
'required' => 0,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 3,
])->save();
}
$dataRow = $this->dataRow($roleDataType, 'updated_at');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'timestamp',
'display_name' => __('voyager::seeders.data_rows.updated_at'),
'required' => 0,
'browse' => 0,
'read' => 0,
'edit' => 0,
'add' => 0,
'delete' => 0,
'order' => 4,
])->save();
}
$dataRow = $this->dataRow($roleDataType, 'display_name');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'text',
'display_name' => __('voyager::seeders.data_rows.display_name'),
'required' => 1,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 1,
'order' => 5,
])->save();
}
$dataRow = $this->dataRow($userDataType, 'role_id');
if (!$dataRow->exists) {
$dataRow->fill([
'type' => 'text',
'display_name' => __('voyager::seeders.data_rows.role'),
'required' => 1,
'browse' => 1,
'read' => 1,
'edit' => 1,
'add' => 1,
'delete' => 1,
'order' => 9,
])->save();
}
}
/**
* [dataRow description].
*
* @param [type] $type [description]
* @param [type] $field [description]
*
* @return [type] [description]
*/
protected function dataRow($type, $field)
{
return DataRow::firstOrNew([
'data_type_id' => $type->id,
'field' => $field,
]);
}
}

View file

@ -1,71 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\DataType;
class DataTypesTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*/
public function run()
{
$dataType = $this->dataType('slug', 'users');
if (!$dataType->exists) {
$dataType->fill([
'name' => 'users',
'display_name_singular' => __('voyager::seeders.data_types.user.singular'),
'display_name_plural' => __('voyager::seeders.data_types.user.plural'),
'icon' => 'voyager-person',
'model_name' => 'TCG\\Voyager\\Models\\User',
'policy_name' => 'TCG\\Voyager\\Policies\\UserPolicy',
'controller' => 'TCG\\Voyager\\Http\\Controllers\\VoyagerUserController',
'generate_permissions' => 1,
'description' => '',
])->save();
}
$dataType = $this->dataType('slug', 'menus');
if (!$dataType->exists) {
$dataType->fill([
'name' => 'menus',
'display_name_singular' => __('voyager::seeders.data_types.menu.singular'),
'display_name_plural' => __('voyager::seeders.data_types.menu.plural'),
'icon' => 'voyager-list',
'model_name' => 'TCG\\Voyager\\Models\\Menu',
'controller' => '',
'generate_permissions' => 1,
'description' => '',
])->save();
}
$dataType = $this->dataType('slug', 'roles');
if (!$dataType->exists) {
$dataType->fill([
'name' => 'roles',
'display_name_singular' => __('voyager::seeders.data_types.role.singular'),
'display_name_plural' => __('voyager::seeders.data_types.role.plural'),
'icon' => 'voyager-lock',
'model_name' => 'TCG\\Voyager\\Models\\Role',
'controller' => 'TCG\\Voyager\\Http\\Controllers\\VoyagerRoleController',
'generate_permissions' => 1,
'description' => '',
])->save();
}
}
/**
* [dataType description].
*
* @param [type] $field [description]
* @param [type] $for [description]
*
* @return [type] [description]
*/
protected function dataType($field, $for)
{
return DataType::firstOrNew([$field => $for]);
}
}

View file

@ -2,7 +2,6 @@
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
@ -14,6 +13,5 @@ class DatabaseSeeder extends Seeder
*/
public function run()
{
// \App\Models\User::factory(10)->create();
}
}

View file

@ -1,179 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\Menu;
use TCG\Voyager\Models\MenuItem;
class MenuItemsTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*
* @return void
*/
public function run()
{
$menu = Menu::where('name', 'admin')->firstOrFail();
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.dashboard'),
'url' => '',
'route' => 'voyager.dashboard',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-boat',
'color' => null,
'parent_id' => null,
'order' => 1,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.media'),
'url' => '',
'route' => 'voyager.media.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-images',
'color' => null,
'parent_id' => null,
'order' => 5,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.users'),
'url' => '',
'route' => 'voyager.users.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-person',
'color' => null,
'parent_id' => null,
'order' => 3,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.roles'),
'url' => '',
'route' => 'voyager.roles.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-lock',
'color' => null,
'parent_id' => null,
'order' => 2,
])->save();
}
$toolsMenuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.tools'),
'url' => '',
]);
if (!$toolsMenuItem->exists) {
$toolsMenuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-tools',
'color' => null,
'parent_id' => null,
'order' => 9,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.menu_builder'),
'url' => '',
'route' => 'voyager.menus.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-list',
'color' => null,
'parent_id' => $toolsMenuItem->id,
'order' => 10,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.database'),
'url' => '',
'route' => 'voyager.database.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-data',
'color' => null,
'parent_id' => $toolsMenuItem->id,
'order' => 11,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.compass'),
'url' => '',
'route' => 'voyager.compass.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-compass',
'color' => null,
'parent_id' => $toolsMenuItem->id,
'order' => 12,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.bread'),
'url' => '',
'route' => 'voyager.bread.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-bread',
'color' => null,
'parent_id' => $toolsMenuItem->id,
'order' => 13,
])->save();
}
$menuItem = MenuItem::firstOrNew([
'menu_id' => $menu->id,
'title' => __('voyager::seeders.menu_items.settings'),
'url' => '',
'route' => 'voyager.settings.index',
]);
if (!$menuItem->exists) {
$menuItem->fill([
'target' => '_self',
'icon_class' => 'voyager-settings',
'color' => null,
'parent_id' => null,
'order' => 14,
])->save();
}
}
}

View file

@ -1,21 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\Menu;
class MenusTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*
* @return void
*/
public function run()
{
Menu::firstOrCreate([
'name' => 'admin',
]);
}
}

View file

@ -1,26 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\Permission;
use TCG\Voyager\Models\Role;
class PermissionRoleTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*
* @return void
*/
public function run()
{
$role = Role::where('name', 'admin')->firstOrFail();
$permissions = Permission::all();
$role->permissions()->sync(
$permissions->pluck('id')->all()
);
}
}

View file

@ -1,38 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\Permission;
class PermissionsTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*/
public function run()
{
$keys = [
'browse_admin',
'browse_bread',
'browse_database',
'browse_media',
'browse_compass',
];
foreach ($keys as $key) {
Permission::firstOrCreate([
'key' => $key,
'table_name' => null,
]);
}
Permission::generateFor('menus');
Permission::generateFor('roles');
Permission::generateFor('users');
Permission::generateFor('settings');
}
}

View file

@ -1,29 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\Role;
class RolesTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*/
public function run()
{
$role = Role::firstOrNew(['name' => 'admin']);
if (!$role->exists) {
$role->fill([
'display_name' => __('voyager::seeders.roles.admin'),
])->save();
}
$role = Role::firstOrNew(['name' => 'user']);
if (!$role->exists) {
$role->fill([
'display_name' => __('voyager::seeders.roles.user'),
])->save();
}
}
}

View file

@ -1,147 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\Setting;
class SettingsTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*/
public function run()
{
$setting = $this->findSetting('site.title');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.site.title'),
'value' => __('voyager::seeders.settings.site.title'),
'details' => '',
'type' => 'text',
'order' => 1,
'group' => 'Site',
])->save();
}
$setting = $this->findSetting('site.description');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.site.description'),
'value' => __('voyager::seeders.settings.site.description'),
'details' => '',
'type' => 'text',
'order' => 2,
'group' => 'Site',
])->save();
}
$setting = $this->findSetting('site.logo');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.site.logo'),
'value' => '',
'details' => '',
'type' => 'image',
'order' => 3,
'group' => 'Site',
])->save();
}
$setting = $this->findSetting('site.google_analytics_tracking_id');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.site.google_analytics_tracking_id'),
'value' => '',
'details' => '',
'type' => 'text',
'order' => 4,
'group' => 'Site',
])->save();
}
$setting = $this->findSetting('admin.bg_image');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.admin.background_image'),
'value' => '',
'details' => '',
'type' => 'image',
'order' => 5,
'group' => 'Admin',
])->save();
}
$setting = $this->findSetting('admin.title');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.admin.title'),
'value' => 'Voyager',
'details' => '',
'type' => 'text',
'order' => 1,
'group' => 'Admin',
])->save();
}
$setting = $this->findSetting('admin.description');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.admin.description'),
'value' => __('voyager::seeders.settings.admin.description_value'),
'details' => '',
'type' => 'text',
'order' => 2,
'group' => 'Admin',
])->save();
}
$setting = $this->findSetting('admin.loader');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.admin.loader'),
'value' => '',
'details' => '',
'type' => 'image',
'order' => 3,
'group' => 'Admin',
])->save();
}
$setting = $this->findSetting('admin.icon_image');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.admin.icon_image'),
'value' => '',
'details' => '',
'type' => 'image',
'order' => 4,
'group' => 'Admin',
])->save();
}
$setting = $this->findSetting('admin.google_analytics_client_id');
if (!$setting->exists) {
$setting->fill([
'display_name' => __('voyager::seeders.settings.admin.google_analytics_client_id'),
'value' => '',
'details' => '',
'type' => 'text',
'order' => 1,
'group' => 'Admin',
])->save();
}
}
/**
* [setting description].
*
* @param [type] $key [description]
*
* @return [type] [description]
*/
protected function findSetting($key)
{
return Setting::firstOrNew(['key' => $key]);
}
}

View file

@ -1,233 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use TCG\Voyager\Models\Category;
use TCG\Voyager\Models\DataType;
use TCG\Voyager\Models\MenuItem;
use TCG\Voyager\Models\Page;
use TCG\Voyager\Models\Translation;
class TranslationsTableSeeder extends Seeder
{
/**
* Auto generated seed file.
*
* @return void
*/
public function run()
{
$this->dataTypesTranslations();
$this->categoriesTranslations();
$this->pagesTranslations();
$this->menusTranslations();
}
/**
* Auto generate Categories Translations.
*
* @return void
*/
private function categoriesTranslations()
{
// Adding translations for 'categories'
//
$cat = Category::where('slug', 'category-1')->firstOrFail();
if ($cat->exists) {
$this->trans('pt', $this->arr(['categories', 'slug'], $cat->id), 'categoria-1');
$this->trans('pt', $this->arr(['categories', 'name'], $cat->id), 'Categoria 1');
}
$cat = Category::where('slug', 'category-2')->firstOrFail();
if ($cat->exists) {
$this->trans('pt', $this->arr(['categories', 'slug'], $cat->id), 'categoria-2');
$this->trans('pt', $this->arr(['categories', 'name'], $cat->id), 'Categoria 2');
}
}
/**
* Auto generate DataTypes Translations.
*
* @return void
*/
private function dataTypesTranslations()
{
// Adding translations for 'display_name_singular'
//
$_fld = 'display_name_singular';
$_tpl = ['data_types', $_fld];
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.post.singular'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Post');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.page.singular'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Página');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.user.singular'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Utilizador');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.category.singular'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Categoria');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.menu.singular'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Menu');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.role.singular'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Função');
}
// Adding translations for 'display_name_plural'
//
$_fld = 'display_name_plural';
$_tpl = ['data_types', $_fld];
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.post.plural'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Posts');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.page.plural'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Páginas');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.user.plural'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Utilizadores');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.category.plural'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Categorias');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.menu.plural'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Menus');
}
$dtp = DataType::where($_fld, __('voyager::seeders.data_types.role.plural'))->firstOrFail();
if ($dtp->exists) {
$this->trans('pt', $this->arr($_tpl, $dtp->id), 'Funções');
}
}
/**
* Auto generate Pages Translations.
*
* @return void
*/
private function pagesTranslations()
{
$page = Page::where('slug', 'hello-world')->firstOrFail();
if ($page->exists) {
$_arr = $this->arr(['pages', 'title'], $page->id);
$this->trans('pt', $_arr, 'Olá Mundo');
/**
* For configuring additional languages use it e.g.
*
* ```
* $this->trans('es', $_arr, 'hola-mundo');
* $this->trans('de', $_arr, 'hallo-welt');
* ```
*/
$_arr = $this->arr(['pages', 'slug'], $page->id);
$this->trans('pt', $_arr, 'ola-mundo');
$_arr = $this->arr(['pages', 'body'], $page->id);
$this->trans('pt', $_arr, '<p>Olá Mundo. Scallywag grog swab Cat o\'nine tails scuttle rigging hardtack cable nipper Yellow Jack. Handsomely spirits knave lad killick landlubber or just lubber deadlights chantey pinnace crack Jennys tea cup. Provost long clothes black spot Yellow Jack bilged on her anchor league lateen sail case shot lee tackle.</p>'
."\r\n".'<p>Ballast spirits fluke topmast me quarterdeck schooner landlubber or just lubber gabion belaying pin. Pinnace stern galleon starboard warp carouser to go on account dance the hempen jig jolly boat measured fer yer chains. Man-of-war fire in the hole nipperkin handsomely doubloon barkadeer Brethren of the Coast gibbet driver squiffy.</p>');
}
}
/**
* Auto generate Menus Translations.
*
* @return void
*/
private function menusTranslations()
{
$_tpl = ['menu_items', 'title'];
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.dashboard'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Painel de Controle');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.media'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Media');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.posts'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Publicações');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.users'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Utilizadores');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.categories'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Categorias');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.pages'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Páginas');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.roles'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Funções');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.tools'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Ferramentas');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.menu_builder'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Menus');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.database'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Base de dados');
}
$_item = $this->findMenuItem(__('voyager::seeders.menu_items.settings'));
if ($_item->exists) {
$this->trans('pt', $this->arr($_tpl, $_item->id), 'Configurações');
}
}
private function findMenuItem($title)
{
return MenuItem::where('title', $title)->firstOrFail();
}
private function arr($par, $id)
{
return [
'table_name' => $par[0],
'column_name' => $par[1],
'foreign_key' => $id,
];
}
private function trans($lang, $keys, $value)
{
$_t = Translation::firstOrNew(array_merge($keys, [
'locale' => $lang,
]));
if (!$_t->exists) {
$_t->fill(array_merge(
$keys,
['value' => $value]
))->save();
}
}
}

Some files were not shown because too many files have changed in this diff Show more