Compare commits

..

57 commits

Author SHA1 Message Date
Noah Lancien
b668848e63 Added a migration to update existing nutritionnal values 2024-01-31 09:11:44 +01:00
Vincent BRIDIER
dcf995bdc6 Merge branch 'issue-38' into 'develop'
bump cookies notice to v4.0.1 - #38

See merge request ldc-web/projets/agis!29
2024-01-30 10:49:14 +00:00
Alexis Gousseau
29016ad3ba bump cookies notice to v4.0.1 - #38 2024-01-30 09:46:31 +01:00
Jérémy Munsch
e1961fab93
disable executeJavascript for sitemap as no puppeteer 2024-01-29 17:08:57 +01:00
Vincent BRIDIER
fa7d44d03d Merge branch 'mulitple-issues' into 'develop'
Mulitple issues

See merge request ldc-web/projets/agis!28
2024-01-29 11:58:53 +00:00
Jérémy Munsch
4d363f8fac
Fix navlink active on ranges 2024-01-29 12:36:34 +01:00
Jérémy Munsch
80a394691c
Closes #48 2024-01-29 12:33:12 +01:00
Jérémy Munsch
1648636bfa
npm update 2024-01-29 12:25:46 +01:00
Jérémy Munsch
159cbbebe7
Closes #56 Fix phone number 2024-01-29 12:13:48 +01:00
Vincent BRIDIER
a53cfc7d55 Merge branch 'issue-60-nutrionnal-values-labels' into 'develop'
Updated nutrionnal values labels

See merge request ldc-web/projets/agis!27
2024-01-29 11:11:31 +00:00
Noah Lancien
c498e298d8 Updated nutrionnal values labels 2024-01-29 11:24:12 +01:00
Vincent BRIDIER
e2d3d7ec28 Merge branch 'php-stan-issues-48-57' into 'develop'
Php stan issues 48 57

See merge request ldc-web/projets/agis!26
2024-01-29 08:40:19 +00:00
Noah Lancien
bed9d9dde6 phpstan 2024-01-26 16:08:12 +01:00
Noah Lancien
19f6454ea3 Merge branch 'issue-57' into php-stan-issues-48-57 2024-01-26 13:09:38 +01:00
Noah Lancien
ffdd886ddc Merge remote-tracking branch 'origin/issue-48' into php-stan-issues-48-57 2024-01-26 13:03:07 +01:00
Vincent BRIDIER
0d17174052 Merge branch 'issue-51' into 'develop'
Added a BackToTop button

See merge request ldc-web/projets/agis!25
2024-01-26 11:14:50 +00:00
Vincent BRIDIER
50a99c7344 Merge branch 'issue-58' into 'develop'
paËlla

See merge request ldc-web/projets/agis!23
2024-01-26 11:13:50 +00:00
Vincent BRIDIER
41dba737cb Merge branch 'issue-59' into 'develop'
Added youtube channel link in join-us page

See merge request ldc-web/projets/agis!22
2024-01-26 11:13:27 +00:00
Vincent BRIDIER
ae4ab562dc Merge branch 'issue-52' into 'develop'
Issue 52, 53, 54, 55, 56 - Typos + footer link

See merge request ldc-web/projets/agis!21
2024-01-26 11:12:29 +00:00
Vincent BRIDIER
a04a65c232 Merge branch 'issue-36-seo-package' into 'develop'
Added the SEO package

See merge request ldc-web/projets/agis!20
2024-01-26 11:11:44 +00:00
Vincent BRIDIER
fd987180bb Merge branch 'fix-news-show' into 'develop'
apply text-center for news subtitle in news show blade

See merge request ldc-web/projets/agis!19
2024-01-26 11:10:21 +00:00
Vincent BRIDIER
58d359155f Merge branch 'issue-44' into 'develop'
Decorative picture is now aligned with the cooking advice part in produt.show

See merge request ldc-web/projets/agis!17
2024-01-26 11:06:57 +00:00
Vincent BRIDIER
1532e3a31d Merge branch 'issue-41' into 'develop'
Ranges title in homepage are now with different colors

See merge request ldc-web/projets/agis!16
2024-01-26 11:05:41 +00:00
Vincent BRIDIER
8e9f7f8419 Merge branch 'issue-32' into 'develop'
Issue 32 Fix Trait HasPicture (Blame pas possible à cause du squash), les parametres...

See merge request ldc-web/projets/agis!15
2024-01-26 11:04:33 +00:00
Vincent BRIDIER
d5c0c06294 Merge branch 'issue-46' into 'develop'
The width of black strip is now the same as title in about-us page

See merge request ldc-web/projets/agis!14
2024-01-26 11:02:59 +00:00
Vincent BRIDIER
0333649f48 Merge branch 'issue-35' into 'develop'
Issue 35

See merge request ldc-web/projets/agis!13
2024-01-26 11:02:19 +00:00
Vincent BRIDIER
6d482c4631 Merge branch 'develop' into issue-35 2024-01-26 12:01:21 +01:00
Noah Lancien
14b0382cdb Added a BackToTop button 2024-01-23 11:53:45 +01:00
Noah Lancien
54e501cd03 In contact form, dates are now dates inpiuts instead of string 2024-01-22 09:56:19 +00:00
Noah Lancien
d162f87f3e Some wording in the contact form 2024-01-22 09:55:27 +00:00
Noah Lancien
1f1d691cbe paËlla 2024-01-22 09:01:28 +01:00
Noah Lancien
be80ca6c6a Added youtube channel link in join-us page 2024-01-22 08:59:16 +01:00
Noah Lancien
bf365eadca Fix #53, added 'convictions' link in footer 2024-01-19 09:51:43 +01:00
Noah Lancien
28a8390c41 Fix #55, wording on ranges page 2024-01-19 09:48:29 +01:00
Noah Lancien
6ee0986b48 Fix #56, renamed civilities 2024-01-19 09:47:34 +01:00
Noah Lancien
239307c1b1 Fixed footer typo 2024-01-19 09:46:41 +01:00
Noah Lancien
81089b8e12 Fixed header typo 2024-01-19 09:45:25 +01:00
Noah Lancien
30ee51d9d1 Added the SEO package 2024-01-08 10:54:20 +01:00
Nicolas Demangeat
398c762b33 apply text-center for news subtitle in news show blade 2023-12-29 15:18:09 +01:00
Jérémy Munsch
a952ea6ac6
Fixes #48 Add style to ck-content + fix all front WYSIWYG taht where missing ck-content 2023-12-22 11:46:21 +01:00
Jérémy Munsch
8318e83d0b
Update secure header with vite config form base project 2023-12-22 11:23:25 +01:00
Jérémy Munsch
25d9e1cac6
Fix commitments responsive on products.show 2023-12-22 11:05:14 +01:00
Jérémy Munsch
cffa0f34a8
Closes #37 add sitemap 2023-12-22 09:49:02 +01:00
Noah Lancien
9a8e0f8f9a Decorative picture is now aligned with the cooking advice part in produt.show 2023-12-21 16:10:31 +01:00
Noah Lancien
5854fc274b Ranges title in homepage are now with different colors 2023-12-21 15:51:00 +01:00
Jérémy Munsch
608629307f
Closes #32 Add youtube video on Homepage
+ remove Unused video Frame
+ FIX  Video Inlaid in Cookie Notice
2023-12-21 15:42:36 +01:00
Noah Lancien
b32f5161b3 The width of black strip is now the same as title in about-us page 2023-12-21 15:22:05 +01:00
Jérémy Munsch
f06e87daf5
Update HasPicture 2023-12-21 15:18:27 +01:00
Jérémy Munsch
13d998ac9c
Fix Trait HasPicture (Blame pas possible à cause du squash), les parametres ajoutés doivent être à la fin pour ne pas niquer le reste du code 2023-12-21 14:41:27 +01:00
Jérémy Munsch
fed7a112c2
Bump inputs form base project 2023-12-21 13:56:34 +01:00
Jérémy Munsch
f34bb70504
cookie notice bump to 4.0.0 2023-12-21 12:09:47 +01:00
Jérémy Munsch
53ccbb5af8
Closes #35 Change civility labels 2023-12-21 10:59:50 +01:00
Jérémy Munsch
8949c3b427
bump front stack + add favicon Fixes #40 2023-12-21 10:45:43 +01:00
Jérémy Munsch
1963b827d8
composer update 2023-12-21 09:28:30 +01:00
Vincent BRIDIER
256a8b5542 Add foreach for contactformé 2023-12-19 16:50:48 +01:00
Vincent BRIDIER
6c63d52996 Merge branch '2.0.0' into 'develop'
2.0.0

See merge request ldc-web/projets/agis!1
2023-12-19 15:09:12 +00:00
noah.lancien
b557533b72 2.0.0 with Laravel 2023-12-19 15:09:12 +00:00
170 changed files with 6493 additions and 6608 deletions

View file

@ -3,7 +3,6 @@ APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
ASSET_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
@ -23,12 +22,6 @@ 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=mailpit
MAIL_PORT=1025
@ -37,26 +30,7 @@ MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
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}"
MAIL_CONTACTFORM_RECEIVER=
# Sentry
SENTRY_LARAVEL_DSN=
@ -69,3 +43,6 @@ MATOMO_SITE_ID=
GOOGLE_RECAPTCHA_PUBLIC=
GOOGLE_RECAPTCHA_PRIVATE=
GOOGLE_RECAPTCHA_VERSION=
# Admin secure
LDC_WEB_API_KEY=

13
.gitignore vendored
View file

@ -23,3 +23,16 @@ Homestead.yaml
npm-debug.log
yarn-error.log
.npmrc
# Ignore public favicon
/public/android-chrome-192x192.png
/public/android-chrome-512x512.png
/public/apple-touch-icon.png
/public/browserconfig.xml
/public/browserconfig.xml
/public/favicon-16x16.png
/public/favicon-32x32.png
/public/favicon.ico
/public/mstile-150x150.png
/public/safari-pinned-tab.svg
/public/site.webmanifest

5
Dockerfile Normal file
View file

@ -0,0 +1,5 @@
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.2:latest
COPY --chown=www-data:www-data . /app/srcs
USER root
RUN chmod -R 755 /app/srcs/storage
USER www-data

View file

@ -1 +1,7 @@
# Agis
## CRON
Put every min in PROD :
```
php artisan schedule:run
```

View file

@ -28,35 +28,35 @@ class UserCreate extends Command
/**
* The first name of the new user.
*
* @var string
* @var string|null
*/
protected $first_name;
/**
* The last name of the new user.
*
* @var string
* @var string|null
*/
protected $last_name;
/**
* The email of the new user.
*
* @var string
* @var string|null
*/
protected $email;
/**
* The password of the new user.
*
* @var string
* @var string|null
*/
protected $password;
/**
* The role of the new user.
*
* @var string
* @var string|null
*/
protected $role;
@ -219,7 +219,7 @@ class UserCreate extends Command
$this->role = $tmp;
} catch (ValidationException $e) {
$this->error(sprintf(
'Please choose from the selection',
'Please choose from the selection %s',
\implode(',', collect($e->errors())->flatten()->all())
));
continue;

View file

@ -15,6 +15,8 @@ enum ActivityLogsEventEnum: int
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::created->name => 'Création',

View file

@ -13,9 +13,11 @@ enum CivilityEnum: int
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::man->name => 'Homme',
self::woman->name => 'Femme',
self::man->name => 'Monsieur',
self::woman->name => 'Madame',
];
}

View file

@ -15,6 +15,8 @@ enum ObjectEnum: int
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::customerService->name => 'Service consommateurs',

View file

@ -260,6 +260,8 @@ enum Country: int
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::afghanistan->name => 'Afghanistan',

View file

@ -16,6 +16,8 @@ enum CategoryEnum: int
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::enterprise->name => 'La vie d\'Entreprise',

View file

@ -16,6 +16,8 @@ enum CookingModeEnum: int
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::microwave->name => 'Micro-ondes',

View file

@ -14,6 +14,8 @@ enum BackgroundEnum: int
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::candlemas->name => 'Chandeleur',

View file

@ -21,6 +21,8 @@ enum StaticPageType: int
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::contact->name => 'Contact',

View file

@ -13,6 +13,8 @@ enum BootstrapThemeEnum: int
/**
* Optionnal labels definition
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::light->name => 'Light',

View file

@ -14,6 +14,8 @@ enum RoleEnum: int
/**
* Optionnal labels definition.
*
* @phpstan-ignore-next-line
*/
private const LABELS = [
self::conceptor->name => 'Concepteur',

View file

@ -51,7 +51,7 @@ class ActivityLogsController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\ActivityLog $activity_log
* @param \App\Models\ActivityLog $activity_log
* @return \Illuminate\Contracts\View\View
*/
public function show(ActivityLog $activity_log): \Illuminate\Contracts\View\View

View file

@ -98,7 +98,7 @@ class CommitmentController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\Commitment $commitment
* @param \App\Models\Commitment $commitment
* @return \Illuminate\Contracts\View\View
*/
public function edit(Commitment $commitment): \Illuminate\Contracts\View\View
@ -139,7 +139,7 @@ class CommitmentController extends Controller
{
$commitment->products()->detach();
if ($commitment->explorerpage()->count() > 3) {
if ($commitment->explorerpage()->count() === 0) {
if ($commitment->deleteOrFail()) {
return redirect()->route('bo.commitments.index')
->with('success', __('crud.messages.has_been_deleted', [

View file

@ -28,7 +28,7 @@ class JoinuspageController extends Controller
/**
* Update the specified resource in storage.
*
* @param \App\Http\Requests\Bo\Joinuspages\UpdateJoinuspageRequest $request
* @param \App\Http\Requests\Bo\Joinuspage\UpdateJoinuspageRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateJoinuspageRequest $request): \Illuminate\Http\RedirectResponse

View file

@ -104,7 +104,7 @@ class NewsController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\News $news
* @param \App\Models\News $news
* @return \Illuminate\Contracts\View\View
*/
public function edit(News $news): \Illuminate\Contracts\View\View

View file

@ -115,7 +115,7 @@ class ProductController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\Product $product
* @param \App\Models\Product $product
* @return \Illuminate\Contracts\View\View
*/
public function edit(Product $product): \Illuminate\Contracts\View\View

View file

@ -104,7 +104,7 @@ class RangeController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\Range $range
* @param \App\Models\Range $range
* @return \Illuminate\Contracts\View\View
*/
public function edit(Range $range): \Illuminate\Contracts\View\View
@ -143,7 +143,9 @@ class RangeController extends Controller
*/
public function destroy(Range $range): \Illuminate\Http\RedirectResponse
{
if (!$range->products->isEmpty()) {
/** @var \Illuminate\Database\Eloquent\Collection $products*/
$products = $range->products;
if (!$products->isEmpty()) {
return redirect()->back()
->with('error', __('crud.messages.cannot_be_deleted_relation', [
'model' => Str::ucfirst(__('models.classes.range')),

View file

@ -98,7 +98,7 @@ class SeasonalSectionController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\SeasonalSection $seasonalSection
* @param \App\Models\SeasonalSection $seasonalSection
* @return \Illuminate\Contracts\View\View
*/
public function edit(SeasonalSection $seasonalSection): \Illuminate\Contracts\View\View

View file

@ -98,7 +98,7 @@ class StampController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\Stamp $stamp
* @param \App\Models\Stamp $stamp
* @return \Illuminate\Contracts\View\View
*/
public function edit(Stamp $stamp): \Illuminate\Contracts\View\View

View file

@ -56,7 +56,7 @@ class StaticPageController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\StaticPage $static_page
* @param \App\Models\StaticPage $static_page
* @return \Illuminate\Contracts\View\View
*/
public function edit(StaticPage $static_page): \Illuminate\Contracts\View\View

View file

@ -100,7 +100,7 @@ class TestimonialController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\Testimonial $testimonial
* @param \App\Models\Testimonial $testimonial
* @return \Illuminate\Contracts\View\View
*/
public function edit(Testimonial $testimonial): \Illuminate\Contracts\View\View

View file

@ -102,7 +102,7 @@ class UsersController extends Controller
/**
* Show the form for editing the specified resource.
*
* @param App\Models\User $user
* @param \App\Models\User $user
* @return \Illuminate\Contracts\View\View
*/
public function edit(User $user): \Illuminate\Contracts\View\View

View file

@ -94,7 +94,7 @@ class Controller extends BaseController
return $query;
}
// Get models with relation's name/label.
if (Str::endsWith($field, '_id') && $query->getModel()->has(Str::remove('_id', $field))) {
if (Str::endsWith($field, '_id')) {
$query->orWhereHas(Str::remove('_id', $field), function ($queryRelation) use ($field, $search) {
if (Schema::hasColumn(Str::remove('_id', $field) . 's', 'name')) {
$queryRelation->where('name', 'like', '%' . $search . '%');
@ -122,12 +122,15 @@ class Controller extends BaseController
*/
protected function getSearchValue(Builder $query, string $search, string $field): string|array
{
$cast = $query->getModel()->getCasts()[$field] ?? null;
if (
count($query->getModel()->getCasts()) and // Check if the model has casts.
isset($query->getModel()->getCasts()[$field]) and // Check if there is cast about specific field.
enum_exists($query->getModel()->getCasts()[$field]) // Check if the cast is an enum.
$cast and // Check if there is cast about specific field.
enum_exists($cast) // Check if the cast is an enum.
) {
$cases = collect($query->getModel()->getCasts()[$field]::toArray());
/** @var \App\Traits\Enums $cast */
// @phpstan-ignore-next-line
$cases = collect($cast::toArray());
$enum = $cases->filter(function ($item) use ($search) {
return preg_match('/' . Str::lower($search) . '/', Str::lower($item->label));
});
@ -148,12 +151,12 @@ class Controller extends BaseController
{
$rName = request()->route()->getName();
$table = $query->getModel()->getTable();
if (request()->sort_col) {
Session::put("$rName.sort_col", request()->sort_col);
if (request()->input('sort_col')) {
Session::put("$rName.sort_col", request()->input('sort_col'));
Session::put("$rName.sorted", true);
}
if (request()->sort_way) {
Session::put("$rName.sort_way", request()->sort_way);
if (request()->input('sort_way')) {
Session::put("$rName.sort_way", request()->input('sort_way'));
Session::put("$rName.sorted", true);
}
if (request()->rst) {
@ -161,12 +164,16 @@ class Controller extends BaseController
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);
if (
request()->input('sort_col') and
request()->input('sort_way') and
Schema::hasColumn($table, request()->input('sort_col'))
) {
if (!in_array(request()->input('sort_col'), $ignore)) {
$query = $query->orderBy(
\sprintf("$table.%s", request()->input('sort_col')),
request()->input('sort_way')
);
}
} elseif (Schema::hasColumn($table, 'order')) {
$query = $query->orderBy('order', 'ASC');

View file

@ -24,6 +24,7 @@ class NewsController extends Controller
/** @var \App\Models\News $newsModels */
$newsModels = News::query()->where('published', true)->orderBy('publish_at', 'desc')->paginate(12);
return view('fo.pages.news.index', \compact('staticPageModel', 'newsModels'));
}

View file

@ -3,6 +3,7 @@
namespace App\Http\Controllers\Fo;
use App\Http\Controllers\Controller;
use App\Lib\Helpers\CollectionHelper;
use App\Models\Product;
class ProductController extends Controller
@ -10,16 +11,35 @@ class ProductController extends Controller
/**
* Display the product page.
*
* @param \App\Models\Product $product
* @param string $slug
* @return \Illuminate\Contracts\View\View
*/
public function show(Product $product): \Illuminate\Contracts\View\View
public function show(string $slug): \Illuminate\Contracts\View\View
{
$otherProductModels = $product->range->products()
->where('id', '!=', $product->id)
$productModel = Product::query()->where('slug', $slug)->firstOrFail();
$otherProductModels = $productModel->range->products()
->where('id', '!=', $productModel->id)
->where('published', true)
->inRandomOrder()
->get();
return view('fo.pages.products.show', compact('product', 'otherProductModels'));
return view('fo.pages.products.show', compact('productModel', 'otherProductModels'));
}
/**
* Get filtered products.
*
* @return \Illuminate\Http\JsonResponse
*/
public function productsFiltered(): \Illuminate\Http\JsonResponse
{
$productModels = Product::query()
->where('published', true)
->where('range_id', request()->range_id)
->orderBy('order', 'asc')
->get();
$productModels = CollectionHelper::paginateManually($productModels, 12, request()->page);
return response()->json($productModels);
}
}

View file

@ -4,6 +4,7 @@ namespace App\Http\Controllers\Fo;
use App\Enums\StaticPageType;
use App\Http\Controllers\Controller;
use App\Lib\Helpers\CollectionHelper;
use App\Models\Product;
use App\Models\Range;
use App\Models\StaticPage;
@ -17,12 +18,12 @@ class RangeController extends Controller
*/
public function index(): \Illuminate\Contracts\View\View
{
/** @var \App\Models\Range $rangeModels */
$rangeModels = Range::query()->where('published', true)->orderBy('order')->get();
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = StaticPage::query()->where('type', StaticPageType::ranges)->firstOrFail();
/** @var \App\Models\Range $rangeModels */
$rangeModels = Range::query()->where('published', true)->orderBy('order')->paginate(12);
return view('fo.pages.ranges.index', compact('rangeModels', 'staticPageModel'));
}
@ -38,8 +39,27 @@ class RangeController extends Controller
$rangeModel = Range::query()->where('published', true)->where('slug', $slug)->firstOrFail();
/** @var \App\Models\Product $productModels */
$productModels = Product::query()->where('range_id', $rangeModel->id)->where('published', true)->get();
$productModels = Product::query()
->where('range_id', $rangeModel->id)
->where('published', true)
->orderBy('order')
->paginate(12);
return view('fo.pages.ranges.show', compact('rangeModel', 'productModels'));
}
/**
* Get filtered ranges.
*
* @return \Illuminate\Http\JsonResponse
*/
public function rangesFiltered(): \Illuminate\Http\JsonResponse
{
$productModels = Range::query()
->where('published', true)
->orderBy('order', 'asc')
->get();
$productModels = CollectionHelper::paginateManually($productModels, 12, request()->page);
return response()->json($productModels);
}
}

View file

@ -110,7 +110,10 @@ class StaticPageController extends Controller
*/
public function contactForm(ContactRequest $request): \Illuminate\Http\RedirectResponse
{
Mail::to(\config('mail.from.address'))->send(new SendContactMail((object)$request->validated()));
$receivers = \config('mail.contactform.receiver');
foreach ($receivers as $email) {
Mail::to($email)->send(new SendContactMail((object)$request->validated()));
}
return redirect()->route('fo.contact.show')
->with(
@ -184,7 +187,10 @@ class StaticPageController extends Controller
*/
public function joinusForm(JoinusRequest $request): \Illuminate\Http\RedirectResponse
{
Mail::to(\config('mail.from.address'))->send(new SendJoinusMail((object)$request->validated()));
$receivers = \config('mail.contactform.receiver');
foreach ($receivers as $email) {
Mail::to($email)->send(new SendJoinusMail((object)$request->validated()));
}
return redirect()->route('fo.joinus.show')
->with(

View file

@ -65,5 +65,6 @@ class Kernel extends HttpKernel
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class,
'local-development' => \App\Http\Middleware\LocalDevelopment::class,
];
}

View file

@ -0,0 +1,25 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class LocalDevelopment
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
if (app()->environment() != 'local') {
return abort(403, 'You are not authorized to access this');
}
return $next($request);
}
}

View file

@ -59,7 +59,10 @@ class SecureHeaders
config('app.debug') ? "https://{$host}:4443" : '',
'https://yl.s-web.fr',
]) . ';',
"img-src * https://yl.s-web.fr data: blob:;",
"img-src 'self' data: blob: " . implode(' ', [
// * VITE DEV
config('app.debug') ? "https://{$host}:4443" : ''
]) . ';',
'frame-src ' . implode(' ', [
'https://www.google.com/recaptcha/',
'https://recaptcha.google.com/recaptcha/',

View file

@ -27,14 +27,14 @@ class UpdateConvictionpageRequest extends FormRequest
public function rules()
{
return [
'key_feed' => 'required|numeric',
'key_earth_1' => 'required|numeric',
'key_earth_2' => 'required|numeric',
'key_together_1' => 'required|numeric',
'key_together_2' => 'required|numeric',
'key_together_3' => 'required|numeric',
'key_together_4' => 'required|numeric',
'key_territory' => 'required|numeric',
'key_feed' => 'required|numeric|max:2147483647',
'key_earth_1' => 'required|numeric|max:2147483647',
'key_earth_2' => 'required|numeric|max:2147483647',
'key_together_1' => 'required|numeric|max:2147483647',
'key_together_2' => 'required|numeric|max:2147483647',
'key_together_3' => 'required|numeric|max:2147483647',
'key_together_4' => 'required|numeric|max:2147483647',
'key_territory' => 'required|numeric|max:2147483647',
];
}

View file

@ -2,6 +2,7 @@
namespace App\Http\Requests\Bo\Homepage;
use App\Rules\IsValidYoutubeId;
use App\Traits\Requests\HasPicture;
use Illuminate\Foundation\Http\FormRequest;
@ -26,6 +27,9 @@ class UpdateHomepageRequest extends FormRequest
*/
protected function prepareForValidation()
{
$this->merge([
'display_video' => $this->boolean('display_video')
]);
$this->mergePicture('picture');
}
@ -44,10 +48,15 @@ class UpdateHomepageRequest extends FormRequest
'picture_title' => 'required|string|between:3,255',
'presentation_title' => 'required|string|between:3,255',
'presentation_content' => 'required|string',
'display_video' => 'present|boolean',
'youtube_video_id' => [
'nullable', 'required_if:display_video,true',
new IsValidYoutubeId()
],
];
return \array_merge(
$rules,
$this->pictureRules('picture', 640, 390, 640, 390, false),
$this->pictureRules('picture', 640, 390, 640, 390, true, requiredIf: 'display_video,false'),
);
}

View file

@ -54,7 +54,7 @@ class StoreNewsRequest extends FormRequest
'subtitle' => 'required|string|between:3,255',
'content' => 'required|string|min:15',
'published' => 'required|boolean',
'publish_at' => 'nullable|date',
'publish_at' => 'required|date',
'unpublish_at' => 'nullable|date|after:publish_at',
];

View file

@ -89,35 +89,35 @@ class StoreProductRequest extends FormRequest
// phpcs:enable
$nutritionnal_values = json_encode([
"energyKj" => [
"label" => "Energie en Kj",
"label" => "ÉNERGIE (kj)",
"value" => $this->nutritionnal_values['energy_kj'],
],
"energyKcal" => [
"label" => "Energie en kcal",
"label" => "ÉNERGIE (kcal)",
"value" => $this->nutritionnal_values['energy_kcal'],
],
"fat" => [
"label" => "Matières grasses",
"label" => "MATIÈRES GRASSES (g)",
"value" => $this->nutritionnal_values['fat'],
],
"saturated-fat" => [
"label" => "dont acides gras saturés",
"label" => "ACIDE GRAS SATURÉ (g)",
"value" => $this->nutritionnal_values['saturated_fat'],
],
"carbohydrate" => [
"label" => "Glucides",
"label" => "GLUCIDES (g)",
"value" => $this->nutritionnal_values['carbohydrate'],
],
"sugar" => [
"label" => "dont sucres",
"label" => "SUCRES (g)",
"value" => $this->nutritionnal_values['sugar'],
],
"proteins" => [
"label" => "Protéines",
"label" => "PROTÉINES (g)",
"value" => $this->nutritionnal_values['proteins'],
],
"salt" => [
"label" => "Sel",
"label" => "SEL (g)",
"value" => $this->nutritionnal_values['salt'],
]
]);

View file

@ -59,7 +59,7 @@ class StoreRangeRequest extends FormRequest
return \array_merge(
$rules,
$this->pictureRules('picture', 466, 440, 466, 440, false),
$this->pictureRules('picture_productsheet', 332, 442, 332, 442, false),
$this->pictureRules('picture_productsheet', 680, 300, 680, 300, false),
$this->pictureRules('picture_thumbnail', 246, 337, 246, 337, false),
);
}

View file

@ -24,8 +24,10 @@ class UpdateStaticPageRequest extends FormRequest
*/
public function prepareForValidation(): void
{
/** @var \App\Models\StaticPage $staticPageModel */
$staticPageModel = $this->route('static_page');
if (
\in_array($this->route('static_page')->type, [
\in_array($staticPageModel->type, [
\App\Enums\StaticPageType::confidentiality,
\App\Enums\StaticPageType::legals
])

View file

@ -109,7 +109,7 @@ abstract class UpdateMiniCrudRequest extends FormRequest
$rules = array_merge($rules, [
"data.$iptName.value" => [
function (string $attribute, $value, callable $fail) use ($sizes) {
return ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
}
],
$this->compileValidate(

View file

@ -3,7 +3,9 @@
namespace App\Http\Requests\Bo\Users;
use App\Enums\Users\RoleEnum;
use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rules\Enum;
use Illuminate\Validation\Rules\Password;
@ -16,7 +18,7 @@ class StoreUserRequest extends FormRequest
*/
public function authorize(): bool
{
return auth('backend')->check();
return Gate::check('create', User::class);
}
/**
@ -24,10 +26,10 @@ class StoreUserRequest extends FormRequest
*
* @return void
*/
protected function prepareForValidation()
protected function prepareForValidation(): void
{
$this->merge([
'published' => $this->published ? true : false
'published' => $this->boolean('published')
]);
}

View file

@ -2,23 +2,35 @@
namespace App\Http\Requests\Bo\Users;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Password;
class UpdateUserRequest extends StoreUserRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return boolean
*/
public function authorize(): bool
{
return Gate::check('update', $this->route('user'));
}
/**
* Prepare the data for validation.
*
* @return void
*/
protected function prepareForValidation()
protected function prepareForValidation(): void
{
$this->merge([
'published' => $this->published ? true : false,
'password' => $this->password ? $this->password : $this->route('user')->password,
'password_confirmation' => $this->password_confirmation ?
$this->password_confirmation :
$this->route('user')->password
'published' => $this->boolean('published'),
'password' => $this->input('password') ??
\optional($this->route('user'))->password,
'password_confirmation' => $this->input('password_confirmation') ??
\optional($this->route('user'))->password
]);
}
@ -30,10 +42,10 @@ class UpdateUserRequest extends StoreUserRequest
public function rules(): array
{
return array_merge(parent::rules(), [
'email' => [
'email' => [
'required',
'email:rfc,strict,dns,spoof,filter',
'unique:users,email,' . $this->route('user')->getKey() . ',id',
Rule::unique('users', 'email')->ignore(\optional($this->route('user'))->getRouteKey())
],
'password' => [
'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8)

View file

@ -21,8 +21,8 @@ class ContactRequest extends FormRequest
protected function prepareForValidation()
{
$this->merge([
'accept_rules' => $this->accept_rules ? true : false,
'send_data' => $this->send_data ? true : false,
'accept_rules' => $this->boolean('accept_rules'),
'send_data' => $this->boolean('send_data'),
]);
$this->mergePicture('file');
}
@ -31,9 +31,11 @@ class ContactRequest extends FormRequest
* Get the validation rules that apply to the request.
*
* @return array
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function rules()
{
// phpcs:enable
ToolboxHelper::validateRecaptcha($this, \config('services.google.recaptcha.version'));
$rules = [
@ -43,104 +45,96 @@ class ContactRequest extends FormRequest
'society' => 'sometimes|nullable|string|between:3,255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
'phone' => 'sometimes|nullable|numeric|min:0',
'address' => 'sometimes|nullable|string|between:3,255',
'postal_code' => 'sometimes|nullable|numeric|min:0',
'city' => 'sometimes|nullable|string|between:3,255',
'address' => 'required|string|between:3,255',
'postal_code' => 'required|numeric|min:0',
'city' => 'required|string|between:3,255',
'object' => ['required', new Enum(ObjectEnum::class)],
'product_name' => [
'nullable', 'string', 'between:3,255',
// @phpcs:ignore Generic.Files.LineLength.TooLong
'required_with:product_date_limit,product_barcode,product_lot,product_date_consumption,product_location',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_name'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_date_limit' => [
'sometimes', 'nullable', 'string', 'between:3,255',
// @phpcs:ignore Generic.Files.LineLength.TooLong
'required_with:product_name,product_barcode,product_lot,product_date_consumption,product_location',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_date_limit'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_barcode' => [
'sometimes', 'nullable', 'numeric', 'min:0',
// @phpcs:ignore Generic.Files.LineLength.TooLong
'required_with:product_name,product_date_limit,product_lot,product_date_consumption,product_location',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_barcode'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_lot' => [
'sometimes', 'nullable', 'numeric', 'min:0',
// @phpcs:ignore Generic.Files.LineLength.TooLong
'required_with:product_name,product_date_limit,product_barcode,product_date_consumption,product_location',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_lot'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_date_consumption' => [
'sometimes', 'nullable', 'string', 'between:3,255',
// @phpcs:ignore Generic.Files.LineLength.TooLong
'required_with:product_name,product_date_limit,product_barcode,product_lot,product_location',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_date_consumption'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_location' => [
'sometimes', 'nullable', 'string', 'between:3,255',
// @phpcs:ignore Generic.Files.LineLength.TooLong
'required_with:product_name,product_date_limit,product_barcode,product_lot,product_date_consumption',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_location'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'message' => 'required|string|between:3,255',
'message' => 'required|string|between:3,500',
'accept_rules' => 'required|boolean',
'send_data' => 'required|boolean',
];
if ($this->object === strval(ObjectEnum::customerService->value())) {
$rules = \array_merge($rules, [
'product_name' => [
'string', 'between:3,255', 'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_name'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_date_limit' => [
'required', 'date',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_date_limit'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_barcode' => [
'numeric', 'min:0', 'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_barcode'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_lot' => [
'numeric', 'min:0', 'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_lot'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_date_consumption' => [
'required', 'date',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_date_consumption'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
'product_location' => [
'string', 'between:3,255', 'required',
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
if ($this->get("object") != ObjectEnum::customerService->value()) {
$fail(\trans('le Champs :field doit être vide lorsque le champs objet
n\'est pas égale à :enumValue.', [
'field' => trans('validation.custom.product_location'),
'enumValue' => ObjectEnum::customerService->label(),
]));
}
}
],
]);
} //end if
if (
isset(request()->file) and
(request()->file->getClientMimeType() === "image/jpeg" ||
@ -152,8 +146,8 @@ class ContactRequest extends FormRequest
0,
1920,
1080,
3000,
true,
3000,
'product_name,product_date_limit,product_barcode,product_lot,product_date_consumption,product_location'
));
} elseif (isset(request()->file) and (request()->file->getClientMimeType() === "application/pdf")) {
@ -161,6 +155,20 @@ class ContactRequest extends FormRequest
//phpcs:ignore Generic.Files.LineLength.TooLong
'file' => 'sometimes|nullable|mimes:pdf|required_with:product_name,product_date_limit,product_barcode,product_lot,product_date_consumption,product_location'
]);
} elseif (
isset(request()->file) and
(request()->file->getClientMimeType() !== "application/pdf") and
(request()->file->getClientMimeType() !== "image/jpeg") and
(request()->file->getClientMimeType() !== "image/png")
) {
$rules = \array_merge($rules, [
'file' => [
// @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
function ($attribute, $value, $fail) {
$fail(\trans('Le format du fichier doit être .jpg, .png ou .pdf'));
}
],
]);
} //end if
return $rules;
}

View file

@ -21,7 +21,7 @@ class JoinusRequest extends FormRequest
'first_name' => 'required|string|between:3,255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|max:255',
'phone' => 'required|numeric|min:0',
'message' => 'required|string|between:3,255',
'message' => 'required|string|between:3,500',
"file" => "sometimes|nullable|mimes:pdf|max:10000"
];
}

View file

@ -19,7 +19,7 @@ class SeasonalSectionStatusUpdate
*/
public function handle()
{
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSections> */
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSection> */
$seasonalsectionsListToPublish = SeasonalSection::query()
->where('publish_at', '<=', Carbon::now()->toDateTime())
->whereNotNull('publish_at')
@ -30,7 +30,7 @@ class SeasonalSectionStatusUpdate
$seasonalsections->published = true;
$seasonalsections->saveOrFail();
}
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSections> */
/** @var \Illuminate\Database\Eloquent\Collection<array-key, \App\Models\SeasonalSection> */
$seasonalsectionsListToUnPublish = SeasonalSection::query()
->where('unpublish_at', '<=', Carbon::now()->toDateTime())
->whereNotNull('unpublish_at')

View file

@ -145,7 +145,7 @@ class ExceptionsHelper
$traceStr .= self::handleArgs($stack);
}
$traceStr .= ")\n";
} elseif (isset($stack['function'])) {
} else {
$traceStr .= "{$stack['function']}(";
if (isset($stack['args'])) {
$traceStr .= self::handleArgs($stack);

View file

@ -118,7 +118,7 @@ class FileStorageHelper
);
return str_replace('/private/', '', $newPath);
}//end if
} //end if
if (\is_object($file) and $file instanceof \SplFileInfo) {
/** @var \SplFileInfo $file */
$filename = $filename ?: $file->getBaseName();
@ -309,7 +309,6 @@ class FileStorageHelper
$private ? 'app/private/modelfiles' : 'app/public/modelfiles',
$tableName,
$filename,
$private
);
$filename = self::getFileUniqueName($folderPath, $filename);
return "{$folderPath}/{$filename}";
@ -404,7 +403,7 @@ class FileStorageHelper
$filename = Str::of($filename)->ltrim('.-');
// * Optional beautification
if ($beautify) {
$filename = static::beautifyFilename($filename);
$filename = self::beautifyFilename($filename);
}
// * Maximize filename length to 255 bytes http://serverfault.com/a/9548/44086
/** @var string */

View file

@ -175,11 +175,10 @@ class ToolboxHelper
$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)
) {
// Assert route matches existing routes.
$routes->match($request);
// ? Is url internal ?
if (\parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST)) {
// Removes the matched url.
throw ValidationException::withMessages([
$field => trans(
@ -205,14 +204,14 @@ class ToolboxHelper
* @param array|string $replace
* @param array|string $subject
* @param integer $count
* @return array|string
* @return array|string|false
*/
public static function mbReplace(
array|string $search,
array|string $replace,
array|string $subject,
int &$count = 0
): array|string {
): array|string|false {
if (!is_array($search) && is_array($replace)) {
return false;
}
@ -289,9 +288,12 @@ class ToolboxHelper
public static function getOriginal(Model $model, string $attribute): mixed
{
if (\in_array('Spatie\Translatable\HasTranslations', \class_uses_recursive($model))) {
// @phpstan-ignore-next-line
return $model->getTranslation(
$attribute,
// @phpstan-ignore-next-line
$model->getLocale(),
// @phpstan-ignore-next-line
$model->useFallbackLocale()
);
}
@ -361,47 +363,45 @@ class ToolboxHelper
/**
* Convert deeply an object to array
*
* @param array|object $input
* @param mixed $input
* @return array
* @throws \RuntimeException If $input var is a scalar value.
*/
public static function objectToArray($input): array
public static function objectToArray(mixed $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 {
if (!(is_object($input) or is_array($input))) {
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($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;
}
/**
* Convert deeply an array to object
*
* @param array|object $input
* @param mixed $input
* @return object
* @throws \RuntimeException If $input var is a scalar value.
*/
public static function arrayToObject($input): object
public static function arrayToObject(mixed $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 {
if (!(is_object($input) or is_array($input))) {
throw new \RuntimeException('Cannot handle $input of type ' . \gettype($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;
}
/**
@ -409,11 +409,11 @@ class ToolboxHelper
*
* @param string $attribute
* @param string|null $value
* @param callback $fail
* @param callable $fail
* @param object $sizes
* @return void
*/
public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes)
public static function validatePicture(string $attribute, string|null $value, callable $fail, object $sizes): void
{
if (!($useStorage = Storage::exists($value)) and !File::exists($value)) {
$fail(trans(':attribute n\'existe pas dans le système de fichier', [
@ -432,7 +432,7 @@ class ToolboxHelper
'attribute' => $attribute
]));
}
if (!($dimensions = \getimagesize($fileFullPath)) or !isset($dimensions[0]) or !isset($dimensions[1])) {
if (!($dimensions = \getimagesize($fileFullPath))) {
$fail(trans(':attribute impossible de valider les dimensions', [
'attribute' => $attribute
]));

View file

@ -5,7 +5,6 @@ namespace App\Mail;
use App\Enums\Contact\ObjectEnum;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
@ -17,7 +16,7 @@ class SendContactMail extends Mailable
use SerializesModels;
/**
* @var \App\Mail\Contact
* @var \stdClass
*/
private \stdClass $data;
@ -40,16 +39,11 @@ class SendContactMail extends Mailable
*/
public function envelope(): \Illuminate\Mail\Mailables\Envelope
{
$subject = ObjectEnum::make($this->data->object) ?
ObjectEnum::make($this->data->object)->label() :
__('Nouveau message');
return new Envelope(
from: new Address(
$this->data->email,
($this->data->first_name !== null || $this->data->last_name !== null) ?
(($this->data->first_name ?? '') . " " . ($this->data->last_name ?? '')) :
null
),
to: [new Address(config('mail.from.address'), config('mail.from.name'))],
subject: sprintf('%s - %s', ObjectEnum::make($this->data->object)->label() ??
__('Nouveau message'), config('app.name')),
subject: sprintf('%s - %s', $subject, config('app.name')),
);
}

View file

@ -4,7 +4,6 @@ namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
@ -16,7 +15,7 @@ class SendJoinusMail extends Mailable
use SerializesModels;
/**
* @var \App\Mail\Joinus
* @var \stdClass
*/
private \stdClass $data;
@ -25,7 +24,6 @@ class SendJoinusMail extends Mailable
*
* @param \stdClass $data
* @return void
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
*/
public function __construct(\stdClass $data)
{
@ -40,13 +38,6 @@ class SendJoinusMail extends Mailable
public function envelope(): \Illuminate\Mail\Mailables\Envelope
{
return new Envelope(
from: new Address(
$this->data->email,
($this->data->first_name !== null || $this->data->last_name !== null) ?
(($this->data->first_name ?? '') . " " . ($this->data->last_name ?? '')) :
null
),
to: [new Address(config('mail.from.address'), config('mail.from.name'))],
subject: sprintf('%s - %s', __('Candidature spontanée'), config('app.name')),
);
}

View file

@ -3,18 +3,17 @@
namespace App\Models;
use App\Enums\ActivityLogs\ActivityLogsEventEnum;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Schema;
/**
* @property string $model Target model.
* @property string $model_id Id of the target model.
* @property string $event Event of this activity (ActivityLogsEventEnum).
* @property string $data Changes.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property string $model Target model.
* @property string $model_id Id of the target model.
* @property \App\Enums\ActivityLogs\ActivityLogsEventEnum $event Event of this activity (ActivityLogsEventEnum).
* @property array $data Changes.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
*
* @property-read \App\Models\User $user User BelongsTo relation.
*/
@ -82,19 +81,20 @@ class ActivityLog extends Model
$activity->model_id = $model->getKey();
$activity->event = $eventEnum;
$activity->data = static::getChangedColumns($activity, $model, $eventEnum);
$activity->created_at = Carbon::now();
// @phpstan-ignore-next-line
$activity->created_at = now();
$activity->saveOrFail();
}
/**
* Get old, new columns that has changed.
*
* @param \self $activity
* @param self $activity
* @param \Illuminate\Database\Eloquent\Model $model
* @param \App\Enums\ActivityLogs\ActivityLogsEventEnum $eventEnum
* @return array|null
* @return array
*/
public static function getChangedColumns(self $activity, Model $model, ActivityLogsEventEnum $eventEnum): array|null
public static function getChangedColumns(self $activity, Model $model, ActivityLogsEventEnum $eventEnum): array
{
$modelClassName = $activity->model_class;
/** Get type of each fields of the target model */
@ -103,16 +103,17 @@ class ActivityLog extends Model
$activity->model_id
)->first();
if ($targetModel != null) {
// phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
$targetModelTypes = collect($targetModel->toArray())
// phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
->map(function ($field, $fieldIndex) use ($targetModel) {
return Schema::getColumnType($targetModel->getTable(), $fieldIndex);
})->toArray();
// phpcs:enable
/** Return old, new and type of values changed */
return ($eventEnum === ActivityLogsEventEnum::updated) ?
array_intersect_key($targetModelTypes, $model->getChanges()) : [];
}
/** Return old, new and type of values changed */
return ($eventEnum === ActivityLogsEventEnum::updated) ?
array_intersect_key($targetModelTypes, $model->getChanges()) : null;
return [];
}
// * RELATIONS
@ -122,7 +123,7 @@ class ActivityLog extends Model
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class);
}

View file

@ -11,9 +11,11 @@ use Illuminate\Database\Eloquent\Model;
* @property string $title_part1 Title part 1.
* @property string $title_part2 Title part 2.
* @property string $title_part3 Title part 3.
* @property string $picture Path of the picture (640px * 390px).
* @property string|null $picture Path of the picture (640px * 390px).
* @property string $picture_alt Picture alt attribute.
* @property string $picture_title Picture title attribute.
* @property string $youtube_video_id The youtube video Id.
* @property boolean $display_video Wether to display video or picture.
* @property string $presentation_title Presentation title.
* @property string $presentation_content WYSIWYG - Presentation content.
* @property-read \Carbon\Carbon $created_at Created date.
@ -38,6 +40,17 @@ class Homepage extends Model
'picture_title',
'presentation_title',
'presentation_content',
'youtube_video_id',
'display_video',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'display_video' => 'bool'
];
/**

View file

@ -9,6 +9,9 @@ use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Uwil\Seo\Laravel\Traits\SeoTrait;
/**
* @property string $seo_title SEO title.
@ -31,10 +34,11 @@ use Illuminate\Support\Str;
* @property-read \Carbon\Carbon $created_at Created date.
* @property-read \Carbon\Carbon $updated_at Updated date.
*/
class News extends Model
class News extends Model implements SeoInterface
{
use ActivityLog;
use HasFactory;
use SeoTrait;
/**
* The attributes that are mass assignable.
@ -198,4 +202,22 @@ class News extends Model
}
return false;
}
// * SEO TRAIT OVERLOAD
/**
* Transform to seoModel
*
* @return \Uwil\Seo\Laravel\Objects\SeoItem
*/
public function toSeoItem(): SeoItem
{
return new SeoItem(
\trans('models.classes.' . Str::singular($this->getTable())),
$this->seo_title,
$this->seo_description,
$this->published ?? false,
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
$this->published ? \route('fo.' . $this->getTable() . '.show', $this) : ''
);
}
}

View file

@ -9,6 +9,9 @@ use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Uwil\Seo\Laravel\Traits\SeoTrait;
/**
* @phpcs:disable Generic.Files.LineLength.TooLong
@ -41,10 +44,11 @@ use Illuminate\Support\Str;
* @property-read \App\Models\Range $range Range Belongs to relationship.
* @phpcs:enable
*/
class Product extends Model
class Product extends Model implements SeoInterface
{
use ActivityLog;
use HasFactory;
use SeoTrait;
/**
* The attributes that are mass assignable.
@ -189,4 +193,22 @@ class Product extends Model
{
return $this->belongsToMany(Commitment::class);
}
// * SEO TRAIT OVERLOAD
/**
* Transform to seoModel
*
* @return \Uwil\Seo\Laravel\Objects\SeoItem
*/
public function toSeoItem(): SeoItem
{
return new SeoItem(
\trans('models.classes.' . Str::singular($this->getTable())),
$this->seo_title,
$this->seo_description,
$this->published ?? false,
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
$this->published ? \route('fo.' . $this->getTable() . '.show', $this) : ''
);
}
}

View file

@ -9,6 +9,9 @@ use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Uwil\Seo\Laravel\Traits\SeoTrait;
// phpcs:disable Generic.Files.LineLength.TooLong
/**
@ -22,7 +25,7 @@ use Illuminate\Support\Str;
* @property string $picture Path of the picture (466px * 440px).
* @property string $picture_alt Picture alt attribute.
* @property string $picture_title Picture title attribute.
* @property string $picture_productsheet Path of the picture of the product sheet (332px * 442px).
* @property string $picture_productsheet Path of the picture of the product sheet (680px * 300px).
* @property string $picture_productsheet_alt Picture alt attribute of the product sheet.
* @property string $picture_productsheet_title Picture title attribute of the product sheet.
* @property string $picture_thumbnail Path of the thumbnail (246px * 337px).
@ -36,10 +39,11 @@ use Illuminate\Support\Str;
* @property-read \App\Models\Products $products Products Has Many relationship.
*/
// phpcs:enable
class Range extends Model
class Range extends Model implements SeoInterface
{
use ActivityLog;
use HasFactory;
use SeoTrait;
/**
* The attributes that are mass assignable.
@ -170,4 +174,22 @@ class Range extends Model
{
return $this->hasMany(Product::class);
}
// * SEO TRAIT OVERLOAD
/**
* Transform to seoModel
*
* @return \Uwil\Seo\Laravel\Objects\SeoItem
*/
public function toSeoItem(): SeoItem
{
return new SeoItem(
\trans('models.classes.' . Str::singular($this->getTable())),
$this->seo_title,
$this->seo_description,
$this->published ?? false,
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
$this->published ? \route('fo.' . $this->getTable() . '.show', $this) : ''
);
}
}

View file

@ -5,6 +5,7 @@ namespace App\Models;
use App\Lib\Helpers\FileStorageHelper;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
/**
* @property string $picture Path of the picture (120px * 120px).
@ -54,9 +55,14 @@ class Stamp extends Model
});
static::updated(function (self $model) {
FileStorageHelper::removeOldFile($model, 'picture');
Cache::forget('randomStampsFooter');
});
static::deleted(function (self $model) {
FileStorageHelper::removeFile($model, 'picture');
Cache::forget('randomStampsFooter');
});
static::created(function () {
Cache::forget('randomStampsFooter');
});
}
}

View file

@ -8,6 +8,9 @@ use App\Traits\Models\ActivityLog;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Uwil\Seo\Laravel\Traits\SeoTrait;
/**
* @property \App\Enums\StaticPageType $type Page type (StaticPageEnum).
@ -19,10 +22,11 @@ use Illuminate\Support\Str;
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*/
class StaticPage extends Model
class StaticPage extends Model implements SeoInterface
{
use ActivityLog;
use HasFactory;
use SeoTrait;
/**
* The attributes that are mass assignable.
@ -57,7 +61,7 @@ class StaticPage extends Model
});
static::updating(function (self $model) {
// * ASSERTIONS
static::assertTitleIsUnique($model->title, $model->id);
self::assertTitleIsUnique($model->title, $model->id);
// * CHANGES
$model->slug = Str::slug($model->title);
@ -83,4 +87,22 @@ class StaticPage extends Model
ToolboxHelper::assertFieldIsUnique($table, 'title', $title, $id);
ToolboxHelper::assertFieldIsUnique($table, 'slug', Str::slug($title), $id);
}
// * SEO TRAIT OVERLOAD
/**
* Transform to seoModel
*
* @return \Uwil\Seo\Laravel\Objects\SeoItem
*/
public function toSeoItem(): SeoItem
{
return new SeoItem(
\trans('models.classes.' . Str::singular($this->getTable())),
$this->seo_title,
$this->seo_description,
true,
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
''
);
}
}

View file

@ -4,6 +4,7 @@ namespace App\Models;
use App\Enums\Users\RoleEnum;
use App\Traits\Models\ActivityLog;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
@ -72,7 +73,7 @@ class User extends Authenticatable
protected static function booted(): void
{
static::creating(function (self $model) {
static::updatePassword($model);
self::updatePassword($model);
// * Prevent user elevation privileges
throw_if(
auth('backend')->user() and auth('backend')->user()->role->value() > $model->role->value(),
@ -80,7 +81,7 @@ class User extends Authenticatable
);
});
static::updating(function (self $model) {
static::updatePassword($model);
self::updatePassword($model);
if (optional(auth('backend')->user())->getKey() === $model->getKey()) {
\validator(
['published' => $model->published],

View file

@ -32,7 +32,7 @@ class TranslationServiceProvider extends ServiceProvider
/**
* Gather provided langs checking from files
*
* @return \Illuminate\Support\Collection<string, string>
* @return \Illuminate\Support\Collection<int, string>
*/
private function collectLocalesStrings(): Collection
{

View file

@ -4,6 +4,7 @@ namespace App\Providers;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
@ -20,6 +21,7 @@ class ViewServiceProvider extends ServiceProvider
$appInfos = Cache::remember('composer', 360, function () {
return json_decode(File::get(\app_path('../composer.json')));
});
// Share composer.json infos.
if (isset($appInfos->name) and isset($appInfos->version)) {
View::share('cpsr_name', $appInfos->name);
@ -28,12 +30,33 @@ class ViewServiceProvider extends ServiceProvider
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') {
// For the moment, we exclude the seo page because the new pagination system doesn't work in the package.
if (
collect(explode('/', \request()->getPathInfo()))->get(1) === 'bo' &&
collect(explode('/', \request()->getPathInfo()))->last() !== 'seo'
) {
Paginator::defaultView('bo.modules.pagination');
} else {
Paginator::useBootstrapFive();
}
}
// Get all the stamps that are pubished.
$stamps = Cache::remember('randomStampsFooter', 360, function () {
return DB::table('stamps')
->select('picture', 'picture_alt', 'picture_title')
->where('published', true)
->get();
});
/**
* Share a collection of 1 or 2 random stamps for footer.
* First, check if $stamps is not empty, if not,
* we count if the number of stamp in $stamps is greater than 2.
* Then, pick 1 or 2 stamp(s) depending on the number of stamps.
*/
View::share(
'randomStampsFooter',
$stamps->isNotEmpty() ? $stamps->random($stamps->count() >= 2 ? 2 : 1) : []
);
} //end if
}
}

View file

@ -0,0 +1,33 @@
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Str;
/**
* Validate a youtube ID regex
*
* @url https://webapps.stackexchange.com/questions/54443/format-for-id-of-youtube-video
* @package App\Rules
*/
class IsValidYoutubeId implements ValidationRule
{
/**
* Run the validation rule.
*
* @param string $attribute
* @param mixed $value
* @param \Closure(string):\Illuminate\Translation\PotentiallyTranslatedString $fail
* @return void
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceBeforeLastUsed
* @phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
*/
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
// phpcs:enable
if (!Str::of($value)->isMatch('/[0-9A-Za-z_-]{10}[048AEIMQUYcgkosw]/')) {
$fail(trans('validation.youtube_id'));
}
}
}

View file

@ -37,18 +37,16 @@ trait ChangesModelOrder
return DB::transaction(function () use ($request, $className, $model) {
/** @var \Illuminate\Database\Eloquent\Model|null */
$tmp = $className::where('order', $request->direction ? '<' : '>', $model->order)
$tmp = $className::where('order', $request->direction ? '<' : '>', $model->getOriginal('order'))
->orderBy('order', $request->direction ? 'DESC' : 'ASC')->first();
if (!$tmp) {
return back()->with('error', trans('crud.messages.order_not_changed'));
}
$newOrder = $tmp->order;
$tmp->order = $model->order;
$model->order = $newOrder;
$tmp->saveOrFail();
$model->saveOrFail();
$newOrder = $tmp->getOriginal('order');
$tmp->update(['order' => $model->getOriginal('order')]);
$model->update(['order' => $newOrder]);
Session::flash('success', trans('crud.messages.order_changed'));
return back();

View file

@ -19,8 +19,7 @@ trait UpdateModelPublished
*/
public function changePublished(Model $model)
{
$model->published = !$model->published;
$model->saveOrFail();
$model->update(['published' => !$model->getOriginal('published')]);
return redirect()->back()->with('success', trans(__('crud.messages.publish_status_saved')));
}
}

View file

@ -118,9 +118,9 @@ trait BaseEnum
/**
* Fetch enum using value.
*
* @param \App\Traits\Enums\BaseEnum|integer|string $value
* @param string $field
* @return \App\Traits\Enums\BaseEnum|null
* @param self|integer|string $value
* @param string $field
* @return self|null
*/
public static function make(self|int|string $value, string $field = 'value'): self|null
{

View file

@ -10,7 +10,8 @@ use Illuminate\Support\Facades\Cache;
/**
* ! Use this only on limited elements, (not on tags, or products, or posts for ex.)
*
* @property private static array $cacheConditions Eloquent condition to cache elements (to be used in where statement).
* @property array<string,string|integer|float|boolean> $cacheConditions
* Eloquent condition to cache elements (to be used in where statement).
*/
trait IsCachedAsCollection
{

View file

@ -45,9 +45,11 @@ trait HasPicture
* @param integer|null $minHeight
* @param integer|null $maxWith
* @param integer|null $maxHeight
* @param integer|null $size
* @param boolean $nullable
* @param integer|null $size
* @param string|null $requiredWith
* @param string|null $requiredWithout
* @param string|null $requiredIf
* @return array
*/
public function pictureRules(
@ -56,9 +58,11 @@ trait HasPicture
?int $minHeight = null,
?int $maxWith = null,
?int $maxHeight = null,
?int $size = null,
bool $nullable = false,
?int $size = null,
?string $requiredWith = null,
?string $requiredWithout = null,
?string $requiredIf = null,
): array {
$dimensions = (object)[
'minWith' => $minWith ?? $this->minWith,
@ -69,10 +73,12 @@ trait HasPicture
return [
$name => [
!$nullable ? 'required' : 'nullable',
(strlen($requiredWith)) ? 'required_with:' . $requiredWith : '',
($size) ? 'max:' . $size : '',
(!empty($requiredWith)) ? "required_with:{$requiredWith}" : '',
(!empty($requiredWithout)) ? "required_without:{$requiredWithout}" : '',
(!empty($requiredIf)) ? "required_if:{$requiredIf}" : '',
($size) ? "max:{$size}" : '',
function (string $attribute, $value, callable $fail) use ($dimensions) {
return ToolboxHelper::validatePicture($attribute, $value, $fail, $dimensions);
ToolboxHelper::validatePicture($attribute, $value, $fail, $dimensions);
}
]
];
@ -107,7 +113,7 @@ trait HasPicture
"{$name}Validate.*" => [
'required',
function (string $attribute, $value, callable $fail) use ($sizes) {
return $this->validatePicture($attribute, $value, $fail, $sizes);
ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
}
]
];

View file

@ -1,22 +1,26 @@
{
"name": "uwil/agis",
"version": "1.0.0",
"version": "2.0.0",
"type": "project",
"description": "Agis website.",
"require": {
"php": "^8.2",
"diglactic/laravel-breadcrumbs": "^8.0",
"doctrine/dbal": "^3.7",
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.0",
"laravel/tinker": "^2.8",
"laravel/ui": "^4.2",
"ldc/sitemap-generator": "^2.0",
"ldc/web-admin-secure-laravel": "^2.0",
"mews/purifier": "^3.4",
"sentry/sentry-laravel": "*"
"sentry/sentry-laravel": "*",
"uwil/k8s-laravel": "^1.2",
"uwil/seo-laravel": "^2.0"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",
"kitloong/laravel-migrations-generator": "^6.8",
"krlove/eloquent-model-generator": "dev-l10-compatibility",
"larastan/larastan": "^2.8",
"laravel-lang/common": "^4.0",
"laravel/pint": "^1.0",
"laravel/sail": "^1.18",
@ -24,8 +28,7 @@
"nunomaduro/collision": "^7.0",
"phpunit/phpunit": "^10.0",
"slevomat/coding-standard": "^8.10",
"spatie/laravel-ignition": "^2.0",
"thedoctor0/laravel-factory-generator": "^1.2"
"spatie/laravel-ignition": "^2.0"
},
"autoload": {
"psr-4": {
@ -36,8 +39,8 @@
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/laravel-shift/eloquent-model-generator.git"
"type": "composer",
"url": "https://lab.s-web.fr/api/v4/group/23/-/packages/composer/packages.json"
}
],
"autoload-dev": {

4764
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -96,6 +96,10 @@ return [
'name' => env('MAIL_FROM_NAME', 'Example'),
],
'contactform' => [
'receiver' => explode(',', env('MAIL_CONTACTFORM_RECEIVER', 'hello@example.com'))
],
/*
|--------------------------------------------------------------------------
| Markdown Mail Settings

12
config/seo.php Normal file
View file

@ -0,0 +1,12 @@
<?php
return [
'bo_route_prefix' => 'bo.',
'blade' => 'bo.pages.seo.index',
'middlewares' => [
'web',
'admin-secure',
'auth:backend'
],
'guard' => 'backend'
];

View file

@ -38,4 +38,8 @@ return [
'version' => env('GOOGLE_RECAPTCHA_VERSION', "3") === "3" ? true : false
]
],
'matomo' => [
'site_id' => env('MATOMO_SITE_ID')
]
];

View file

@ -0,0 +1,101 @@
<?php
use Spatie\Sitemap\Tags\Url;
return [
/**
* A list of url to ignore
* These are hard coded
* Each url does not have to be exhaustive
*
* For example, if you want to ignore all routes
* of the backoffice group
* just add 'bo' into this table
*
* * Note that this can take route names (both partially or full)
* * You can use a wild card just as for routeIs method
*/
'ignoreRoutes' => [
'back.*',
'bo.*',
'fo.verification.*',
'fo.password.*',
'front.frame',
'cspReportUri',
],
/**
* This should be filled using the command `php artisan sitemap:install-completer`
*
* 'completeWith' => [CLASS, 'METHOD'],
* eg : 'completeWith' => [CompleteSitemapWith::class, 'append'],
*
* This should point to a static method which will be called with the folowing parameter
* (LDC\SitemapGenerator\Lib\Sitemap $sitemap)
*
* You may now use $sitemap->addLinks('route.myRouteName', string[] $links)
*/
'completeWith' => null,
/**
* The default route frequency to use with sitemap generator
*/
'routeDefaultFrequency' => Url::CHANGE_FREQUENCY_DAILY,
/**
* The default route priority to use with sitemap generator
*
* priority should be a number between 0 and 1
* https://www.sitemaps.org/protocol.html
*/
'routeDefaultPriority' => 0.5,
/**
* Frequencies for routes
* use the full or partial route name as index
* and a frequency within \Spatie\Sitemap\Tags\Url constants
*
* eg: 'engagments.*' => \Spatie\Sitemap\Tags\Url::CHANGE_FREQUENCY_HOURLY
*/
'routeFrequencies' => [],
/**
* Priorities for routes
* use the full or partial route name as index
* and a priority in 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1, and 0.0.
*
* 1.0 is the Highest
*
* eg: 'engagments.*' => 1.0
*/
'routePriorities' => [],
/**
* Enable or disable schedule for the job
* If set to true the sitemap generator will be run
* using the 'cron' instruction
*/
'schedule' => true,
/**
* If you want to set specific
* instruction for when to schedule job
* you can set this with a cron instruction
* You can generate one using https://crontab.guru/
*
* schedule must be set to true
*
* Default is every day at 15:45
*/
'cron' => '45 15 * * *',
/**
* The sitemap generator can execute JavaScript on each page so it will
* discover links that are generated by your JS scripts. This feature
* is powered by headless Chrome.
*
* ! This needs pupetter installed with npm : npm i puppeteer (not to put in dev dependencies)
*/
'executeJavascript' => false,
];

View file

@ -20,35 +20,35 @@ class ProductFactory extends Factory
$nutritionnal_values = [
'energyKj' => [
'label' => 'Energie en Kj',
'label' => 'ÉNERGIE (kj)',
'value' => fake()->randomFloat(2, 0, 70)
],
'energyKcal' => [
'label' => 'Energie en kcal',
'label' => 'ÉNERGIE (kcal)',
'value' => fake()->randomFloat(2, 0, 70)
],
'fat' => [
'label' => 'Matières grasses',
'label' => 'MATIÈRES GRASSES (g)',
'value' => fake()->randomFloat(2, 0, 70)
],
'saturated-fat' => [
'label' => 'dont acides gras saturés',
'label' => 'ACIDE GRAS SATURÉ (g)',
'value' => fake()->randomFloat(2, 0, 70)
],
'carbohydrate' => [
'label' => 'Glucides',
'label' => 'GLUCIDES (g)',
'value' => fake()->randomFloat(2, 0, 70)
],
'sugar' => [
'label' => 'dont sucres',
'label' => 'SUCRES (g)',
'value' => fake()->randomFloat(2, 0, 70)
],
'proteins' => [
'label' => 'Protéines',
'label' => 'PROTÉINES (g)',
'value' => fake()->randomFloat(2, 0, 70)
],
'salt' => [
'label' => 'Sel',
'label' => 'SEL (g)',
'value' => fake()->randomFloat(2, 0, 70)
],
];

View file

@ -36,7 +36,7 @@ class UserFactory extends Factory
*/
public function unverified(): static
{
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
return $this->state(fn (array $attributes) => [
'email_verified_at' => null,
]);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -15,14 +15,14 @@ return new class extends Migration
{
Schema::create('convictionpages', function (Blueprint $table) {
$table->id();
$table->float('key_feed')->comment('Chiffre clé \'bien nourrir\'');
$table->float('key_earth_1')->comment('Chiffre clé \'respecter la terre\' 1');
$table->float('key_earth_2')->comment('Chiffre clé \'respecter la terre\' 2');
$table->float('key_together_1')->comment('Chiffre clé \'vivre ensemble\' 1');
$table->float('key_together_2')->comment('Chiffre clé \'vivre ensemble\' 2');
$table->float('key_together_3')->comment('Chiffre clé \'vivre ensemble\' 3');
$table->float('key_together_4')->comment('Chiffre clé \'vivre ensemble\' 4');
$table->float('key_territory')->comment('Chiffre clé \'intégrer son territoire\'');
$table->float('key_feed', 12)->comment('Chiffre clé \'bien nourrir\'');
$table->float('key_earth_1', 12)->comment('Chiffre clé \'respecter la terre\' 1');
$table->float('key_earth_2', 12)->comment('Chiffre clé \'respecter la terre\' 2');
$table->float('key_together_1', 12)->comment('Chiffre clé \'vivre ensemble\' 1');
$table->float('key_together_2', 12)->comment('Chiffre clé \'vivre ensemble\' 2');
$table->float('key_together_3', 12)->comment('Chiffre clé \'vivre ensemble\' 3');
$table->float('key_together_4', 12)->comment('Chiffre clé \'vivre ensemble\' 4');
$table->float('key_territory', 12)->comment('Chiffre clé \'intégrer son territoire\'');
$table->timestamps();
});
}

View file

@ -26,7 +26,7 @@ return new class extends Migration
$table->string('picture_alt')->comment('Attribut alt pour l\'image picture');
$table->string('picture_title')->comment('Attribut title pour l\'image picture');
$table->string('picture_productsheet')
->comment('Path de l\'image à afficher sur les fiches produits de cette gamme (332px * 442px)');
->comment('Path de l\'image à afficher sur les fiches produits de cette gamme (680px * 300px)');
$table->string('picture_productsheet_alt')
->comment('Attribut alt de l\'image à afficher sur les fiches produits');
$table->string('picture_productsheet_title')

View file

@ -0,0 +1,43 @@
<?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(): void
{
Schema::table('homepages', function (Blueprint $table) {
$table->string('picture')->nullable()->change()
->comment('Path de l\'image de la page d\'accueil (640px * 390px)');
$table->string('youtube_video_id')->after('picture_title')
->nullable()
->default(null)
->comment('L\ídentifiant de la vidéo Youtube');
$table->boolean('display_video')->after('youtube_video_id')
->default(false)
->comment('Afficher la video ou l\'image');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::table('homepages', function (Blueprint $table) {
$table->string('picture')->change()
->comment('Path de l\'image de la page d\'accueil (640px * 390px)');
$table->dropColumn('youtube_video_id');
$table->dropColumn('display_video');
});
}
};

View file

@ -0,0 +1,110 @@
<?php
use App\Models\Product;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
DB::transaction(function () {
Product::all()->each(function (Product $product) {
$oldValues = json_decode($product->nutritionnal_values, true);
$product->nutritionnal_values = [
'energyKj' => [
'label' => 'ÉNERGIE (kj)',
'value' => $oldValues['energyKj']['value']
],
'energyKcal' => [
'label' => 'ÉNERGIE (kcal)',
'value' => $oldValues['energyKcal']['value']
],
'fat' => [
'label' => 'MATIÈRES GRASSES (g)',
'value' => $oldValues['fat']['value']
],
'saturated-fat' => [
'label' => 'ACIDE GRAS SATURÉ (g)',
'value' => $oldValues['saturated-fat']['value']
],
'carbohydrate' => [
'label' => 'GLUCIDES (g)',
'value' => $oldValues['carbohydrate']['value']
],
'sugar' => [
'label' => 'SUCRES (g)',
'value' => $oldValues['sugar']['value']
],
'proteins' => [
'label' => 'PROTÉINES (g)',
'value' => $oldValues['proteins']['value']
],
'salt' => [
'label' => 'SEL (g)',
'value' => $oldValues['salt']['value']
],
];
$product->save();
});
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
DB::transaction(function () {
Product::all()->each(function (Product $product) {
$oldValues = json_decode($product->nutritionnal_values, true);
$product->nutritionnal_values = [
'energyKj' => [
'label' => 'Energie en Kj',
'value' => $oldValues['energyKj']['value']
],
'energyKcal' => [
'label' => 'Energie en kcal',
'value' => $oldValues['energyKcal']['value']
],
'fat' => [
'label' => 'Matières grasses',
'value' => $oldValues['fat']['value']
],
'saturated-fat' => [
'label' => 'dont acides gras saturés',
'value' => $oldValues['saturated-fat']['value']
],
'carbohydrate' => [
'label' => 'Glucides',
'value' => $oldValues['carbohydrate']['value']
],
'sugar' => [
'label' => 'dont sucres',
'value' => $oldValues['sugar']['value']
],
'proteins' => [
'label' => 'Protéines',
'value' => $oldValues['proteins']['value']
],
'salt' => [
'label' => 'Sel',
'value' => $oldValues['salt']['value']
],
];
$product->save();
});
});
}
};

View file

@ -21,7 +21,7 @@ class RangeSeeder extends Seeder
'../database/factories/assets/ranges/default-picture-466x440.png'
)));
$range->picture_productsheet = FileStorageHelper::storeFile($range, new \SplFileInfo(\resource_path(
'../database/factories/assets/ranges/default-picture-332x442.png'
'../database/factories/assets/ranges/default-picture-680x300.png'
)));
$range->picture_thumbnail = FileStorageHelper::storeFile($range, new \SplFileInfo(\resource_path(
'../database/factories/assets/ranges/default-picture-246x337.png'

177
manifest.yaml Normal file
View file

@ -0,0 +1,177 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ${CI_PROJECT_PATH_SLUG}-config-map
data:
APP_NAME: "${APP_APP_NAME}"
APP_ENV: "${APP_APP_ENV}"
APP_KEY: "${APP_APP_KEY}"
APP_DEBUG: "${APP_APP_DEBUG}"
APP_URL: "https://www.${APP_DOMAIN}"
LOG_CHANNEL: "k8s"
DB_HOST: "mariadb-service.common-services"
DB_DATABASE: "${APP_DB_DATABASE}"
DB_USERNAME: "${APP_DB_USERNAME}"
DB_PASSWORD: "${APP_DB_PASSWORD}"
MAIL_HOST: "${APP_MAIL_HOST}"
MAIL_PORT: "${APP_MAIL_PORT}"
MAIL_USERNAME: "${APP_MAIL_USERNAME}"
MAIL_PASSWORD: "${APP_MAIL_PASSWORD}"
MAIL_ENCRYPTION: "${APP_MAIL_ENCRYPTION}"
MAIL_FROM_ADDRESS: "${APP_MAIL_FROM_ADDRESS}"
MAIL_FROM_NAME: "${APP_APP_NAME}"
MAIL_CONTACTFORM_RECEIVER: "${APP_MAIL_CONTACTFORM_RECEIVER}"
LDC_WEB_API_KEY: "${APP_LDC_WEB_API_KEY}"
GOOGLE_RECAPTCHA_PRIVATE: "${APP_GOOGLE_RECAPTCHA_PRIVATE}"
GOOGLE_RECAPTCHA_PUBLIC: "${APP_GOOGLE_RECAPTCHA_PUBLIC}"
GOOGLE_RECAPTCHA_VERSION: "${APP_GOOGLE_RECAPTCHA_VERSION}"
SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}"
MATOMO_SITE_ID: "${APP_MATOMO_SITE_ID}"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ${CI_PROJECT_PATH_SLUG}-pvc-storage
spec:
storageClassName: "csi-cinder-classic"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: $APP_PVC_SIZE
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${CI_PROJECT_PATH_SLUG}-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ${CI_PROJECT_PATH_SLUG}-app
template:
metadata:
labels:
app: ${CI_PROJECT_PATH_SLUG}-app
spec:
containers:
- name: ${CI_PROJECT_PATH_SLUG}-container
image: $IMAGE_TAG
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
---
apiVersion: v1
kind: Service
metadata:
name: ${CI_PROJECT_PATH_SLUG}-service
spec:
selector:
app: ${CI_PROJECT_PATH_SLUG}-app
ports:
- port: 80
targetPort: 443
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: ${CI_PROJECT_PATH_SLUG}-ingress-route
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`${APP_DOMAIN}`, `www.${APP_DOMAIN}`)
kind: Rule
services:
- name: ${CI_PROJECT_PATH_SLUG}-service
port: 80
middlewares:
- name: redirect-no-www-to-www
namespace: common-services
tls:
secretName: $APP_DOMAIN
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: $APP_DOMAIN
spec:
dnsNames:
- $APP_DOMAIN
- www.${APP_DOMAIN}
secretName: $APP_DOMAIN
issuerRef:
name: $APP_CERT_ISSUER
kind: ClusterIssuer
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ${CI_PROJECT_PATH_SLUG}-cronjob
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ${CI_PROJECT_PATH_SLUG}-app
topologyKey: "kubernetes.io/hostname"
namespaces: [$KUBE_NAMESPACE]
containers:
- name: ${CI_PROJECT_PATH_SLUG}-scheduled
image: $IMAGE_TAG
imagePullPolicy: IfNotPresent
command:
- "php"
args:
- "artisan"
- "schedule:run"
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
restartPolicy: OnFailure

2914
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
{
"private": true,
"name": "srcs",
"scripts": {
"vite": "vite --clearScreen false",
"prod": "vite build --mode production",
@ -15,12 +16,11 @@
"devDependencies": {
"@babel/core": "^7.22.11",
"@babel/types": "^7.21.2",
"@fortawesome/fontawesome-svg-core": "latest",
"@fortawesome/free-brands-svg-icons": "latest",
"@fortawesome/free-regular-svg-icons": "latest",
"@fortawesome/free-solid-svg-icons": "latest",
"@fortawesome/vue-fontawesome": "^3.0.3",
"@ldc-web/cookie-notice": "^3.0.9",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.5",
"@ldc-web/cookie-notice": "^4.0.1",
"@sipec/vue3-tags-input": "^3.0.4",
"@types/bootstrap": "^5.2.7",
"@types/node": "^20.8.2",
@ -28,11 +28,10 @@
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.36.2",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-legacy": "latest",
"@vitejs/plugin-vue": "latest",
"@vitejs/plugin-vue": "^4.6.2",
"@vue/compiler-sfc": "latest",
"@vue/eslint-config-typescript": "latest",
"@vue/tsconfig": "latest",
"@vue/tsconfig": "^0.4.0",
"axios": "^1.5.1",
"bootstrap": "^5.3.2",
"chart.js": "^4.4.0",
@ -40,33 +39,34 @@
"eslint": "latest",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-vue": "latest",
"laravel-vite-plugin": "latest",
"laravel-vite-plugin": "^0.8.1",
"postcss-discard-comments": "^6.0.0",
"prettier": "latest",
"print-js": "^1.6.0",
"resolve-url-loader": "^5.0.0",
"rollup-plugin-copy": "^3.5.0",
"sass": "latest",
"slugify": "^1.6.6",
"stylelint": "latest",
"stylelint": "^15.11.0",
"stylelint-config-idiomatic-order": "github:ream88/stylelint-config-idiomatic-order",
"stylelint-config-sass-guidelines": "latest",
"stylelint-config-standard-scss": "latest",
"stylelint-scss": "latest",
"stylelint-config-sass-guidelines": "^10.0.0",
"stylelint-config-standard-scss": "^11.1.0",
"stylelint-scss": "^5.3.2",
"sweetalert2": "^11.7.31",
"swiper": "^10.2.0",
"swiper": "^11.0.5",
"terser": "latest",
"toastify-js": "^1.12.0",
"ts-loader": "^9.3.1",
"typescript": ">=3.3.1 <5.2.0",
"typescript-eslint": "latest",
"typescript": "latest",
"vite": "^4.5.1",
"vite-plugin-babel": "latest",
"vite-plugin-checker": "latest",
"vite-plugin-eslint": "latest",
"vite-plugin-stylelint": "latest",
"vite": "^4.0.0",
"vue-eslint-parser": "^9.1.0",
"vue-loader": "^16.8.3",
"vue": "latest",
"vue-tsc": "1.6.0"
"vue-eslint-parser": "^9.3.2",
"vue-loader": "^17.3.1",
"vue-tsc": "1.8.11"
}
}
}

10
phpstan.neon Normal file
View file

@ -0,0 +1,10 @@
includes:
- vendor/larastan/larastan/extension.neon
parameters:
paths:
- app/
# Level 9 is the highest level
level: 5

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#ffc40d</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 656 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

View file

@ -0,0 +1,173 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="330.000000pt" height="330.000000pt" viewBox="0 0 330.000000 330.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,330.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1565 3286 c-113 -31 -202 -130 -219 -240 -4 -22 -8 -41 -10 -43 -1
-2 -38 -14 -82 -27 -464 -136 -823 -506 -947 -976 -25 -94 -32 -134 -43 -240
-3 -30 -7 -59 -8 -65 -2 -6 -35 -10 -75 -9 l-71 0 0 -38 0 -38 75 0 75 0 1
-32 c3 -160 55 -361 139 -533 80 -164 171 -288 303 -411 159 -149 398 -281
583 -324 50 -11 52 -13 58 -53 17 -105 94 -200 192 -236 184 -69 376 45 409
242 3 20 12 37 19 37 54 0 306 106 417 175 137 86 292 233 392 373 147 204
248 496 256 740 1 21 5 22 76 22 l75 0 0 38 0 39 -71 -1 c-39 -1 -72 2 -74 5
-2 3 -6 26 -9 52 -14 116 -16 134 -22 162 -51 281 -199 551 -413 754 -150 143
-371 267 -582 326 -54 15 -57 18 -64 53 -18 100 -91 195 -177 232 -60 26 -145
32 -203 16z m135 -70 c0 11 80 -38 108 -67 27 -28 68 -116 59 -126 -2 -2 -37
0 -78 5 -88 9 -220 8 -306 -2 -71 -9 -75 -4 -50 57 39 92 148 155 235 136 17
-4 32 -5 32 -3z m120 -271 c136 -20 253 -55 390 -117 105 -48 262 -161 358
-257 214 -216 348 -505 376 -814 4 -51 3 -57 -12 -53 -9 3 -93 28 -187 56 -93
28 -173 54 -176 58 -3 4 -19 48 -34 97 -93 304 -313 529 -615 628 -181 60
-429 54 -605 -15 -285 -110 -495 -341 -578 -633 l-23 -79 -187 -57 c-103 -31
-188 -53 -188 -50 -2 9 -2 9 5 89 14 152 79 353 161 497 131 229 321 408 560
525 152 75 266 109 425 126 30 4 56 8 58 9 6 5 226 -3 272 -10z m35 -464 c244
-65 441 -225 555 -451 33 -66 74 -179 67 -186 -1 -1 -36 8 -77 21 -41 13 -113
35 -160 49 -47 14 -200 61 -341 104 l-255 78 -205 -62 c-112 -34 -300 -91
-416 -127 -140 -42 -213 -61 -213 -52 0 51 95 247 158 325 130 163 346 292
527 316 28 3 52 8 54 10 13 12 235 -7 306 -25z m-251 -543 c-1 -35 -2 -66 -3
-69 -1 -4 -15 -9 -33 -13 -41 -8 -119 -88 -134 -138 -34 -111 38 -255 139
-275 15 -3 27 -8 28 -12 4 -23 3 -134 -1 -136 -6 -4 -156 41 -695 205 -148 45
-316 96 -372 113 -57 17 -103 34 -103 37 0 4 10 10 23 12 12 3 195 58 407 123
619 188 735 223 741 219 3 -1 4 -31 3 -66z m118 63 c13 -6 264 -82 558 -171
294 -88 546 -166 560 -172 23 -10 19 -12 -55 -35 -44 -13 -87 -26 -95 -28 -16
-4 -540 -163 -992 -301 -16 -5 -18 3 -18 64 l0 70 55 27 c30 14 67 41 80 60
90 117 42 286 -97 342 l-38 15 0 69 c0 71 3 76 42 60z m-12 -226 c46 -24 73
-71 73 -125 0 -139 -174 -194 -258 -82 -14 19 -20 43 -20 82 0 62 21 100 70
124 38 20 98 20 135 1z m-1187 -226 c95 -29 178 -55 186 -59 8 -4 25 -44 37
-89 75 -258 253 -471 499 -594 64 -32 169 -64 253 -78 65 -10 226 -14 267 -5
11 2 40 7 64 11 70 12 175 50 259 95 216 116 386 329 455 567 13 46 26 85 29
88 6 7 357 115 371 115 22 0 -19 -238 -63 -372 -59 -176 -136 -304 -290 -481
-34 -39 -180 -157 -245 -199 -318 -205 -738 -257 -1106 -137 -436 141 -764
501 -869 954 -20 87 -36 235 -26 235 4 0 84 -23 179 -51z m922 -285 c99 -30
187 -55 195 -55 17 -1 71 15 525 154 171 52 311 94 313 93 1 -2 -7 -32 -19
-67 -81 -248 -264 -443 -504 -538 -44 -17 -91 -34 -105 -36 -204 -40 -390 -24
-552 48 -142 63 -283 183 -369 314 -47 73 -101 191 -113 249 l-7 31 228 -69
c125 -38 309 -94 408 -124z m200 -998 c44 0 112 3 151 7 l72 7 -8 -35 c-41
-181 -301 -224 -405 -67 -13 20 -27 52 -31 69 l-6 32 73 -7 c41 -3 110 -6 154
-6z"/>
<path d="M1589 2881 c-11 -5 -14 -32 -14 -115 0 -106 1 -109 23 -111 14 -1 22
4 23 14 1 9 2 25 3 36 2 31 26 24 45 -14 10 -21 25 -36 39 -38 26 -3 27 3 8
48 -13 30 -13 36 2 52 21 23 21 83 -1 104 -17 17 -104 33 -128 24z m98 -67 c5
-17 -14 -35 -41 -38 -23 -3 -26 0 -22 23 2 14 5 29 5 33 1 9 54 -6 58 -18z"/>
<path d="M1320 2843 c-42 -13 -60 -29 -74 -63 -40 -100 51 -197 147 -157 89
38 97 157 14 207 -31 20 -57 23 -87 13z m53 -52 c23 -9 36 -31 43 -68 4 -21
-29 -52 -59 -57 -19 -3 -33 1 -47 17 -11 11 -20 23 -21 26 0 3 -2 14 -4 25 -4
18 35 66 54 66 5 0 21 -4 34 -9z"/>
<path d="M1890 2808 c-14 -23 -32 -54 -41 -69 -8 -15 -23 -39 -33 -53 -9 -15
-14 -31 -11 -36 9 -15 43 -12 52 5 13 22 67 5 71 -22 2 -13 13 -23 29 -26 l25
-5 -5 116 c-5 116 -11 132 -47 132 -8 0 -26 -19 -40 -42z m40 -63 c0 -28 -4
-35 -20 -35 -11 0 -20 3 -20 6 0 7 33 64 37 64 2 0 3 -16 3 -35z"/>
<path d="M2096 2775 c-9 -23 -9 -23 18 -37 l24 -13 -27 -55 c-52 -108 -51
-105 -30 -118 17 -11 23 -4 59 68 22 44 44 80 48 80 4 0 14 -4 22 -10 16 -10
40 4 40 25 0 9 -69 46 -136 72 -6 2 -14 -3 -18 -12z"/>
<path d="M1026 2717 c-17 -13 -16 -18 34 -108 29 -52 54 -95 56 -97 1 -2 27
11 58 28 49 28 54 34 46 51 -12 21 -21 24 -35 10 -6 -5 -20 -12 -32 -15 -19
-6 -26 1 -52 51 -45 88 -53 96 -75 80z"/>
<path d="M2290 2573 c-36 -46 -66 -87 -68 -92 -1 -4 22 -27 52 -50 55 -41 55
-41 67 -19 10 18 8 24 -12 39 -13 10 -27 19 -31 19 -13 0 -9 27 5 39 11 8 18
6 32 -9 22 -25 41 -26 50 -3 4 12 -2 24 -19 38 -19 16 -23 24 -15 38 10 16 12
16 40 -8 17 -14 34 -25 39 -25 14 0 33 31 24 39 -5 4 -29 24 -54 43 l-45 35
-65 -84z"/>
<path d="M832 2579 c-23 -17 -42 -36 -42 -42 0 -7 20 -32 43 -57 23 -26 54
-61 69 -79 25 -29 30 -31 48 -18 l20 14 -21 27 -21 26 26 31 c29 34 31 47 15
82 -12 26 -47 47 -78 47 -9 0 -36 -14 -59 -31z m87 -38 c8 -14 6 -23 -10 -37
-20 -18 -21 -18 -39 6 -17 22 -17 25 -2 37 24 18 40 16 51 -6z"/>
<path d="M2490 2423 c-30 -25 -60 -53 -67 -62 -36 -47 18 -140 75 -126 28 6
73 35 130 83 30 25 31 29 19 47 -14 18 -17 17 -82 -33 -56 -43 -70 -50 -87
-41 -30 16 -19 38 48 95 48 40 59 55 52 68 -14 24 -28 19 -88 -31z"/>
<path d="M680 2425 c-11 -13 -10 -22 3 -51 l17 -34 -39 6 c-33 5 -41 3 -50
-15 -7 -11 -10 -21 -9 -22 6 -1 53 -9 80 -13 38 -6 41 -9 68 -65 13 -28 26
-51 29 -51 4 0 12 9 19 20 10 17 10 26 -3 50 -20 39 -20 40 17 29 27 -7 36 -5
52 11 25 24 22 27 -34 35 -71 10 -75 12 -100 65 -25 54 -31 58 -50 35z"/>
<path d="M2630 2175 c-76 -34 -94 -47 -92 -61 6 -28 10 -29 44 -16 45 17 56
-4 21 -40 -20 -21 -24 -33 -19 -54 l7 -27 33 32 c27 26 38 31 65 26 26 -4 37
0 62 25 26 26 30 35 23 62 -8 38 -35 98 -43 97 -3 0 -49 -20 -101 -44z m94
-40 c15 -39 -25 -66 -49 -32 -14 20 -14 23 2 34 23 17 40 16 47 -2z"/>
<path d="M515 2154 c-14 -31 -25 -59 -25 -63 0 -7 153 -79 185 -87 18 -4 25 4
48 57 21 48 24 65 15 71 -24 15 -35 8 -50 -31 -13 -33 -20 -39 -37 -34 -25 6
-25 6 -6 43 14 27 14 30 -4 40 -27 14 -28 14 -40 -20 -10 -31 -17 -35 -39 -21
-11 6 -10 15 5 45 15 32 15 38 3 46 -25 16 -29 12 -55 -46z"/>
<path d="M1170 2213 l0 -93 48 0 c52 0 73 14 90 60 13 35 -4 87 -34 106 -13 9
-42 17 -64 18 l-40 2 0 -93z m98 3 c4 -32 -13 -56 -39 -56 -16 0 -19 8 -19 48
0 27 3 52 7 55 12 13 48 -20 51 -47z"/>
<path d="M1374 2302 c-5 -4 -9 -45 -9 -92 l0 -85 58 -3 c52 -3 57 -1 57 18 0
17 -6 20 -40 20 -37 0 -40 2 -31 19 7 12 18 17 33 14 18 -3 24 0 25 16 1 17
-4 21 -28 21 -22 0 -29 5 -29 19 0 12 7 18 23 18 42 1 47 3 47 21 0 15 -9 19
-48 19 -27 1 -53 -2 -58 -5z"/>
<path d="M1541 2300 c-4 -3 -8 -45 -8 -93 0 -84 1 -88 21 -85 15 2 20 9 19 26
-2 12 1 23 5 23 4 1 18 3 31 4 39 4 61 39 50 77 -7 27 -21 45 -39 49 -18 4
-72 4 -79 -1z m79 -60 c0 -25 -38 -33 -45 -9 -4 10 -4 23 -1 28 10 15 46 0 46
-19z"/>
<path d="M1700 2234 c0 -66 3 -78 24 -99 18 -18 31 -23 53 -19 47 8 57 27 59
106 1 84 0 88 -24 82 -14 -4 -17 -17 -18 -70 0 -45 -5 -68 -14 -74 -25 -16
-39 10 -42 77 -2 54 -6 67 -20 69 -16 2 -18 -7 -18 -72z"/>
<path d="M1903 2302 c-6 -4 -11 -45 -11 -94 0 -79 2 -88 19 -88 13 0 19 7 20
23 4 134 3 157 -7 161 -6 2 -15 1 -21 -2z"/>
<path d="M2011 2293 c-13 -9 -21 -25 -21 -43 0 -24 7 -33 40 -50 22 -11 40
-25 40 -30 0 -17 -16 -19 -42 -6 -22 12 -26 11 -36 -4 -8 -14 -6 -20 11 -29
40 -21 66 -21 93 2 22 19 24 26 15 50 -6 15 -25 34 -46 44 -19 9 -35 20 -35
24 0 16 20 20 41 8 17 -9 23 -8 30 2 20 33 -52 59 -90 32z"/>
<path d="M2616 1392 c-2 -4 -13 -33 -24 -65 l-21 -58 27 -10 c37 -15 176 -59
184 -59 3 0 16 28 27 62 16 48 18 64 8 70 -23 15 -34 8 -46 -32 -12 -42 -17
-45 -40 -31 -12 8 -13 14 -2 37 10 22 10 29 -1 35 -23 15 -36 10 -47 -21 -6
-17 -17 -30 -27 -30 -17 0 -16 13 2 76 4 16 0 23 -15 27 -12 3 -23 2 -25 -1z"/>
<path d="M600 1355 c-9 -11 -23 -13 -50 -9 -65 11 -100 -51 -66 -114 8 -15 17
-39 21 -54 6 -32 21 -37 29 -10 4 12 15 17 38 16 49 -2 60 4 47 28 -6 11 -17
17 -24 14 -20 -7 -28 9 -11 24 10 7 21 8 33 2 58 -30 105 37 63 91 -24 30 -61
35 -80 12z m53 -50 c1 -5 -6 -11 -15 -13 -11 -2 -18 3 -18 13 0 17 30 18 33 0z
m-99 -17 c-18 -32 -27 -39 -35 -27 -11 18 1 39 23 39 12 0 17 -4 12 -12z"/>
<path d="M2521 1164 c-22 -28 -21 -33 19 -74 3 -3 18 -20 34 -38 l30 -32 -55
17 c-74 23 -99 22 -116 -4 -14 -21 -11 -24 72 -85 47 -35 90 -64 95 -66 5 -2
13 5 19 16 9 17 3 24 -39 53 -28 19 -50 37 -50 41 0 3 25 -2 55 -13 67 -23 72
-24 84 0 11 19 10 19 -63 100 l-31 34 50 -28 c28 -16 56 -33 63 -38 12 -10 42
7 42 24 0 4 -33 27 -72 50 -40 23 -83 49 -94 56 -20 13 -24 11 -43 -13z"/>
<path d="M689 1085 c-38 -21 -59 -58 -59 -106 0 -35 6 -47 36 -75 42 -40 68
-42 108 -10 l30 23 -23 36 c-25 41 -33 44 -51 22 -10 -12 -10 -18 -1 -29 19
-22 -7 -31 -30 -10 -40 36 -8 114 48 114 30 0 63 -34 58 -59 -2 -14 3 -25 16
-32 26 -14 31 -9 32 34 2 84 -87 134 -164 92z"/>
<path d="M2311 903 c-67 -35 -85 -120 -37 -176 53 -61 133 -57 185 9 26 33 27
79 1 121 -33 55 -95 74 -149 46z m72 -44 c37 -17 53 -53 39 -84 -26 -56 -105
-50 -120 9 -10 35 8 72 36 79 9 3 18 5 19 6 1 0 13 -4 26 -10z"/>
<path d="M880 844 c-47 -30 -89 -59 -94 -65 -15 -14 26 -40 41 -27 21 17 66
-18 59 -46 -4 -15 1 -29 13 -40 17 -16 20 -12 64 84 26 55 47 104 47 109 0 8
-33 41 -41 41 -2 0 -42 -25 -89 -56z m56 -43 c-11 -20 -21 -28 -31 -25 -21 8
-19 15 13 40 34 28 38 24 18 -15z"/>
<path d="M1079 759 c-25 -25 -20 -56 18 -106 18 -24 23 -37 16 -44 -14 -14
-53 6 -53 27 0 22 -44 14 -48 -8 -4 -23 38 -65 74 -74 39 -10 78 14 82 50 3
20 -6 42 -27 71 -17 24 -31 46 -31 49 0 15 40 4 54 -15 18 -26 52 -22 48 6 -5
30 -49 65 -83 65 -16 0 -38 -9 -50 -21z"/>
<path d="M2123 769 l-22 -8 25 -56 c14 -31 24 -58 23 -60 -2 -2 -29 16 -60 39
-44 34 -60 41 -77 35 -25 -9 -24 -12 30 -124 48 -99 46 -97 68 -83 17 11 17
13 -5 65 -13 29 -22 53 -19 53 3 0 28 -16 57 -35 54 -37 64 -40 85 -27 10 7 1
33 -35 109 -44 93 -50 100 -70 92z"/>
<path d="M1265 693 c-3 -10 -2 -19 3 -21 5 -1 17 -9 27 -16 16 -12 16 -17 -8
-94 -24 -78 -24 -82 -6 -87 22 -7 39 1 39 18 0 6 10 42 21 79 20 63 23 66 45
58 19 -8 26 -5 34 10 5 10 10 21 10 23 0 5 -132 47 -148 47 -5 0 -13 -8 -17
-17z"/>
<path d="M1783 655 c-82 -35 -81 -163 1 -207 46 -25 122 -4 149 41 35 59 12
137 -49 166 -39 18 -59 18 -101 0z m96 -61 c41 -52 18 -104 -44 -104 -58 0
-86 69 -45 110 28 28 64 25 89 -6z"/>
<path d="M1486 642 c-3 -9 -8 -61 -11 -114 l-6 -98 25 0 c23 0 26 4 26 35 0
23 5 35 13 35 14 0 37 -40 37 -65 0 -10 10 -15 30 -15 l29 0 -14 41 c-14 37
-13 42 5 62 42 45 6 126 -57 128 -15 0 -38 2 -50 5 -14 2 -24 -2 -27 -14z
m101 -58 c9 -23 -18 -44 -44 -34 -15 6 -20 15 -16 29 6 25 51 29 60 5z"/>
<path d="M1279 1166 c-1 -1 -3 -13 -5 -28 -2 -19 2 -28 12 -28 17 0 16 7 18
-110 l1 -95 28 -3 28 -3 -3 132 -3 133 -37 1 c-21 1 -39 1 -39 1z"/>
<path d="M1456 1149 c-13 -10 -27 -30 -30 -43 -11 -46 25 -105 67 -106 21 0
21 -2 -3 -50 -11 -22 -20 -41 -20 -43 0 -2 14 -4 31 -5 28 -1 33 5 65 71 39
81 43 131 14 165 -26 32 -90 37 -124 11z m82 -51 c14 -14 -2 -48 -22 -48 -20
0 -37 25 -30 44 7 19 35 21 52 4z"/>
<path d="M1703 1158 c-30 -14 -48 -70 -33 -98 8 -15 8 -25 1 -34 -49 -59 23
-150 103 -130 49 12 89 99 55 119 -6 4 -8 22 -4 46 9 51 -1 76 -35 94 -33 17
-56 18 -87 3z m70 -62 c8 -19 -16 -38 -37 -30 -16 6 -21 25 -9 37 12 12 41 7
46 -7z m7 -110 c0 -28 -33 -41 -51 -20 -17 20 -3 44 26 44 20 0 25 -5 25 -24z"/>
<path d="M1883 1163 c-7 -3 -13 -16 -13 -29 0 -22 4 -24 45 -24 30 0 45 -4 45
-13 0 -7 -13 -52 -29 -99 -16 -48 -27 -89 -23 -92 12 -13 50 -5 57 12 15 37
72 237 69 241 -5 5 -137 9 -151 4z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,19 @@
{
"name": "Agis",
"short_name": "Agis",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-256x256.png",
"sizes": "256x256",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View file

@ -1,27 +1,35 @@
<?php
// * Version 3.0.8
// * Version 4.0.0
// phpcs:disable
return [
'button_customize_cookies' => 'Customize cookies',
'button_close_cookies' => 'Close cookie window',
'button_forbid' => 'Prohibit',
'button_allow' => 'Allow',
'button_forbid_all' => 'Reject all',
'button_allow_all' => 'Accept all',
'button_forbid_all_title' => 'Refuse all cookies and close the cookies panel',
'button_allow_all_title' => 'Accept all cookies and close the cookies panel',
'button_customize' => 'Customize',
'button_back' => 'Back',
'button_title_open_new_tab' => 'Open link in new tab',
'banner_title' => 'The :site_name website uses cookies!',
'banner_text_open' => 'This website stores cookies on your computer. :site_name uses this information to improve and personalize your browsing experience, as well as for analysis and indicators concerning our visitors both on this website and on other media. You can click on "Accept" if you consent to the use of these cookies.',
'banner_text' => 'We use cookies to ensure the smooth operation of our site and for analytical purposes. By continuing to browse this site or by closing this banner, you consent to the use of these cookies.',
'banner_details' => 'If you refuse the use of cookies, your information will not be tracked during your visit to this site. A cookie will be used in your browser to remember not to track your preferences. Some features will not be accessible. You can change your mind and modify your consent at any time by returning to this site.',
'banner_details_link' => 'To find out more about the cookies we use, please consult our privacy policy.',
'banner_details_link_title' => 'Privacy policy',
'banner_more_details' => 'More details...',
'banner_less_details' => 'Fewer details...',
'Panel_title' => 'Cookie management panel',
'Panel_subtitle' => 'Your privacy is our priority',
'Panel_details' => 'The functionalities of this site are based on services provided by third parties. If you accept, these third parties will deposit cookies that will enable you to view content on the site hosted by these third parties. Through these cookies, these third parties will collect and use your browsing data for their own purposes, in accordance with their privacy policy (link below). This page allows you to give or withdraw your consent, either globally or service by service.',
'banner_text' => 'We use cookies to ensure the proper functioning of our site and for analytical purposes.
You can change your mind at any time by clicking on the icon on any page of our site.
By authorizing these third-party services, you agree to the deposit and reading of cookies and the use of tracking technologies necessary for their proper operation.',
'modal_title' => 'Cookie management window',
'panel_title' => 'Cookie management panel',
'panel_content' => 'Cookie management panel content',
'panel_subtitle' => 'Your privacy is our priority',
'panel_details' => 'The functionalities of this site are based on services provided by third parties. If you accept, these third parties will deposit cookies that will enable you to view content on the site hosted by these third parties. Through these cookies, these third parties will collect and use your browsing data for their own purposes, in accordance with their privacy policy (link below). This page allows you to give or withdraw your consent, either globally or service by service.',
'picture_cookie_title' => 'Image of a nice big cookie',
'navigation_title' => 'Cookies panel navigation',
'custom' => [
'analytics' => [
'title' => 'Google Analytics',
'description' => 'Audience measurement services make it possible to generate attendance statistics useful for improving the site.',
],
'youtube' => [
'name' => 'Youtube',
'description' => 'Cookies placed via video sharing services are intended to allow the user to view multimedia content directly on the site.',

View file

@ -13,26 +13,27 @@ return [
],
'helpers' => [
'list' => 'List',
'list_all' => 'List all :model',
'create_model' => 'Create :model',
'view_model' => 'View :model',
'update_model' => 'Update :model',
'duplicate_model' => 'Duplicate :model',
'delete_model' => 'Delete :model',
'save_model' => 'Save :model',
'edit_model' => 'Edit :model',
'no_results' => 'No results for :models',
'publish' => 'Publish',
'unpublish' => 'Unpublish',
'seo_title' => 'Must give a precise description of the page, which is recommended for optimum
'list' => 'List',
'list_all' => 'List all :model',
'create_model' => 'Create :model',
'view_model' => 'View :model',
'update_model' => 'Update :model',
'duplicate_model' => 'Duplicate :model',
'delete_model' => 'Delete :model',
'save_model' => 'Save :model',
'edit_model' => 'Edit :model',
'no_results' => 'No results for :models',
'publish' => 'Publish',
'unpublish' => 'Unpublish',
'seo_title' => 'Must give a precise description of the page, which is recommended for optimum
positioning in search engines (<title> tag).',
'seo_description' => 'Must give a precise description of the page content (<meta> description tag).',
'required_fields' => 'Required fields',
'seo_description' => 'Must give a precise description of the page content (<meta> description tag).',
'required_fields' => 'Required fields',
'visibility_with_dates' => 'This field will only have an effect if no date is entered.',
'publish_at' => 'The :model will be published from that date.',
'unpublish_at' => 'The :model will be unpublished from that date.',
'nutritionnal_values' => 'Values must be given in grams, except for energy in kJ and kcal.',
'publish_at' => 'The :model will be published from that date.',
'unpublish_at' => 'The :model will be unpublished from that date.',
'nutritionnal_values' => 'Values must be given in grams, except for energy in kJ and kcal.',
'year' => 'Year of :model'
],
'libs' => [

View file

@ -215,75 +215,79 @@ return [
'year' => 'year',
'url' => 'URL',
],
'youtube_id' => ':attribute must be a valid Youtube video ID',
'custom' => [
'of_the' => [
'male' => 'of the ',
'female' => 'of the ',
'vowel' => 'of the '
],
'accept_rules' => 'acceptation of rules',
'activated' => 'activated',
'attribute_alt' => 'alt attribute',
'attribute_title' => 'title attribute',
'background' => 'background',
'category' => 'category',
'category' => 'category',
'civility' => 'civility',
'cooking_advice' => 'cooking advice',
'description' => 'description',
'direction' => 'direction',
'event' => 'event',
'file' => 'file',
'ingredients' => 'ingredients',
'job' => 'job',
'key_earth_1' => 'key number for "respect the earth" 1',
'key_earth_2' => 'key number for "respect the earth" 2',
'key_feed' => 'key number for "feed well"',
'key_territory' => 'key number for "integrate its territory"',
'key_together_1' => 'key number for "live together" 1',
'key_together_2' => 'key number for "live together" 2',
'key_together_3' => 'key number for "live together" 3',
'key_together_4' => 'key number for "live together" 4',
'model' => 'target element',
'nutritionnal_values' => 'nutritionnal values',
'object' => 'object',
'order' => 'order',
'picture_1' => 'picture one',
'picture_2' => 'picture two',
'picture_3' => 'picture three',
'picture_alt' => 'attribut alt of the :field',
'picture_ambiance' => 'ambiance picture',
'picture_packshot' => 'packshot picture',
'picture_productsheet' => 'productsheet picture',
'picture_thumbnail' => 'thumbnail',
'picture_title' => 'attribut title of the :field',
'picture' => 'picture',
'presentation_content' => 'presentation content',
'presentation_title' => 'presentation title',
'product_barcode' => 'product barcode',
'product_date_consumption' => 'product date consumption',
'product_date_limit' => 'product date limit',
'product_location' => 'product location',
'product_lot' => 'product lot',
'product_name' => 'product name',
'publication' => 'publication',
'publish_at' => 'publication date',
'publish_at' => 'publication date',
'send_data' => 'autorization to send data',
'seo_description' => 'SEO description',
'seo_title' => 'SEO title',
'seo' => 'SEO',
'society' => 'society',
'static_page_type' => 'static page type',
'statut' => 'statut',
'subtitle' => 'subtitle',
'tagline' => 'tagline',
'target' => 'target',
'title_part1' => 'title part one',
'title_part2' => 'title part two',
'title_part3' => 'title part three',
'unpublish_at' => 'end of publication date',
'unpublish_at' => 'end of publication date',
'video_id' => 'ID of the video',
'accept_rules' => 'acceptation of rules',
'activated' => 'activated',
'attribute_alt' => 'alt attribute',
'attribute_title' => 'title attribute',
'background' => 'background',
'category' => 'category',
'category' => 'category',
'civility' => 'civility',
'cooking_advice' => 'cooking advice',
'description' => 'description',
'direction' => 'direction',
'event' => 'event',
'file' => 'file',
'ingredients' => 'ingredients',
'job' => 'job',
'key_earth_1' => 'key number for "respect the earth" 1',
'key_earth_2' => 'key number for "respect the earth" 2',
'key_feed' => 'key number for "feed well"',
'key_territory' => 'key number for "integrate its territory"',
'key_together_1' => 'key number for "live together" 1',
'key_together_2' => 'key number for "live together" 2',
'key_together_3' => 'key number for "live together" 3',
'key_together_4' => 'key number for "live together" 4',
'model' => 'target element',
'nutritionnal_values' => 'nutritionnal values',
'object' => 'object',
'order' => 'order',
'picture_1' => 'picture one',
'picture_2' => 'picture two',
'picture_3' => 'picture three',
'picture_alt' => 'attribut alt of the :field',
'picture_ambiance' => 'ambiance picture',
'picture_packshot' => 'packshot picture',
'picture_productsheet' => 'productsheet picture',
'picture_thumbnail' => 'thumbnail',
'picture_title' => 'attribut title of the :field',
'picture' => 'picture',
'presentation_content' => 'presentation content',
'presentation_title' => 'presentation title',
'product_barcode' => 'product barcode',
'product_barcode_detail' => '(13 digits)',
'product_date_consumption' => 'product date consumption',
'product_date_limit' => 'product date limit',
'product_location' => 'product location',
'product_lot' => 'product lot',
'product_name' => 'product name',
'publication' => 'publication',
'publish_at' => 'publication date',
'publish_at' => 'publication date',
'send_data' => 'autorization to send data',
'seo_description' => 'SEO description',
'seo_title' => 'SEO title',
'seo' => 'SEO',
'society' => 'society',
'static_page_type' => 'static page type',
'statut' => 'statut',
'subtitle' => 'subtitle',
'tagline' => 'tagline',
'target' => 'target',
'title_part1' => 'title part one',
'title_part2' => 'title part two',
'title_part3' => 'title part three',
'unpublish_at' => 'end of publication date',
'unpublish_at' => 'end of publication date',
'video_id' => 'ID of the video',
],
];

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