ajoute les alertes Prometheus du self-healing et installe Larastan (dette de l'étape 8, 72 erreurs corrigées à la racine)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
f2649d0f8b
commit
d47e8356fc
23 changed files with 340 additions and 22 deletions
1
portail/.gitignore
vendored
1
portail/.gitignore
vendored
|
|
@ -21,6 +21,7 @@
|
|||
/public/storage
|
||||
/storage/*.key
|
||||
/storage/pail
|
||||
/storage/phpstan
|
||||
/vendor
|
||||
_ide_helper.php
|
||||
Homestead.json
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||
|
||||
use App\Models\Eleve;
|
||||
use App\Models\Seance;
|
||||
use App\Models\User;
|
||||
use App\Services\Visio\JetonVisio;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
|
@ -177,7 +178,7 @@ class VisioController extends Controller
|
|||
|
||||
// ---- Interne ----------------------------------------------------------
|
||||
|
||||
private function verifierProf(Seance $seance)
|
||||
private function verifierProf(Seance $seance): User
|
||||
{
|
||||
$prof = Auth::guard('web')->user();
|
||||
abort_if($seance->classe->user_id !== $prof->id, 403);
|
||||
|
|
@ -217,6 +218,9 @@ class VisioController extends Controller
|
|||
/**
|
||||
* Lecture-modification-écriture sous verrou : deux élèves qui lèvent la
|
||||
* main au même instant ne s'écrasent pas.
|
||||
*
|
||||
* @param callable(array{mains: array<int, array{nom: string, depuis: int}>, participants: array<int, string>, presences: array<int, array{nom: string, vu: int}>}): array{mains: array<int, array{nom: string, depuis: int}>, participants: array<int, string>, presences: array<int, array{nom: string, vu: int}>} $changement
|
||||
* @return array{mains: array<int, array{nom: string, depuis: int}>, participants: array<int, string>, presences: array<int, array{nom: string, vu: int}>}
|
||||
*/
|
||||
private function modifier(Seance $seance, callable $changement): array
|
||||
{
|
||||
|
|
|
|||
|
|
@ -55,7 +55,9 @@ class CreerStackLab implements ShouldQueue
|
|||
$stack = $fabrique->fabriquer(
|
||||
DefinitionLab::depuis($session->lab->identifiant),
|
||||
"{$base}-e{$this->attempts()}",
|
||||
fn (string $nom, string $id) => $session->forceFill(['heat_stack_name' => $nom, 'heat_stack_id' => $id])->save(),
|
||||
function (string $nom, string $id) use ($session): void {
|
||||
$session->forceFill(['heat_stack_name' => $nom, 'heat_stack_id' => $id])->save();
|
||||
},
|
||||
);
|
||||
|
||||
if ($session->fresh()->etat !== LabSession::ADMIS) {
|
||||
|
|
|
|||
|
|
@ -2,15 +2,17 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Database\Factories\ClasseFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Classe extends Model
|
||||
{
|
||||
/** @use HasFactory<ClasseFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['etablissement_id', 'user_id', 'nom', 'formation', 'code_classe'];
|
||||
|
|
@ -35,26 +37,31 @@ class Classe extends Model
|
|||
return $code;
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Etablissement, $this> */
|
||||
public function etablissement(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Etablissement::class);
|
||||
}
|
||||
|
||||
/** @return BelongsTo<User, $this> */
|
||||
public function prof(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
/** @return HasMany<Eleve, $this> */
|
||||
public function eleves(): HasMany
|
||||
{
|
||||
return $this->hasMany(Eleve::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<DemandeInscription, $this> */
|
||||
public function demandesInscription(): HasMany
|
||||
{
|
||||
return $this->hasMany(DemandeInscription::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<Seance, $this> */
|
||||
public function seances(): HasMany
|
||||
{
|
||||
return $this->hasMany(Seance::class);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ class Correction extends Model
|
|||
'details' => 'array',
|
||||
];
|
||||
|
||||
/** @return BelongsTo<LabSession, $this> */
|
||||
public function labSession(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(LabSession::class);
|
||||
|
|
|
|||
|
|
@ -30,11 +30,13 @@ class DemandeInscription extends Model
|
|||
'code_secret_chiffre' => 'encrypted',
|
||||
];
|
||||
|
||||
/** @return BelongsTo<Classe, $this> */
|
||||
public function classe(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Classe::class);
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Eleve, $this> */
|
||||
public function eleve(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Eleve::class);
|
||||
|
|
@ -45,6 +47,7 @@ class DemandeInscription extends Model
|
|||
return hash('sha256', $jeton);
|
||||
}
|
||||
|
||||
/** @return Builder<self> */
|
||||
public function prunable(): Builder
|
||||
{
|
||||
return static::where('created_at', '<', now()->subHour());
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Models\Concerns\GereSessionUnique;
|
||||
use Database\Factories\EleveFactory;
|
||||
use Illuminate\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -12,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||
|
||||
class Eleve extends Model implements AuthenticatableContract
|
||||
{
|
||||
/** @use HasFactory<EleveFactory> */
|
||||
use Authenticatable, GereSessionUnique, HasFactory;
|
||||
|
||||
protected $fillable = ['classe_id', 'prenom', 'nom', 'identifiant', 'code_secret', 'jeton_qr'];
|
||||
|
|
@ -27,11 +29,13 @@ class Eleve extends Model implements AuthenticatableContract
|
|||
return 'code_secret';
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Classe, $this> */
|
||||
public function classe(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Classe::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<LabSession, $this> */
|
||||
public function labSessions(): HasMany
|
||||
{
|
||||
return $this->hasMany(LabSession::class);
|
||||
|
|
|
|||
|
|
@ -2,21 +2,25 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Database\Factories\EtablissementFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Etablissement extends Model
|
||||
{
|
||||
/** @use HasFactory<EtablissementFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['nom', 'ville', 'uai'];
|
||||
|
||||
/** @return HasMany<User, $this> */
|
||||
public function profs(): HasMany
|
||||
{
|
||||
return $this->hasMany(User::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<Classe, $this> */
|
||||
public function classes(): HasMany
|
||||
{
|
||||
return $this->hasMany(Classe::class);
|
||||
|
|
|
|||
|
|
@ -2,16 +2,19 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Database\Factories\LabFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Lab extends Model
|
||||
{
|
||||
/** @use HasFactory<LabFactory> */
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['identifiant', 'titre', 'niveau', 'duree_min'];
|
||||
|
||||
/** @return HasMany<Seance, $this> */
|
||||
public function seances(): HasMany
|
||||
{
|
||||
return $this->hasMany(Seance::class);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
|
@ -11,8 +10,6 @@ use Illuminate\Support\Facades\DB;
|
|||
|
||||
class LabSession extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public const EN_ATTENTE = 'en_attente';
|
||||
|
||||
// Admis par le prof : CreerStackLab est dispatché, la stack Heat se construit.
|
||||
|
|
@ -35,21 +32,25 @@ class LabSession extends Model
|
|||
'expire_a' => 'datetime',
|
||||
];
|
||||
|
||||
/** @return BelongsTo<Seance, $this> */
|
||||
public function seance(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Seance::class);
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Eleve, $this> */
|
||||
public function eleve(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Eleve::class);
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Lab, $this> */
|
||||
public function lab(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Lab::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<LabSessionMachine, $this> */
|
||||
public function machines(): HasMany
|
||||
{
|
||||
return $this->hasMany(LabSessionMachine::class);
|
||||
|
|
@ -79,11 +80,13 @@ class LabSession extends Model
|
|||
});
|
||||
}
|
||||
|
||||
/** @return HasMany<Correction, $this> */
|
||||
public function corrections(): HasMany
|
||||
{
|
||||
return $this->hasMany(Correction::class);
|
||||
}
|
||||
|
||||
/** @return HasOne<Correction, $this> */
|
||||
public function derniereCorrection(): HasOne
|
||||
{
|
||||
return $this->hasOne(Correction::class)->latestOfMany();
|
||||
|
|
|
|||
|
|
@ -2,14 +2,11 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class LabSessionMachine extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
// Self-healing (SurveillanceVm) : la VM a été relancée automatiquement,
|
||||
// ou ne répond plus malgré les relances.
|
||||
public const RELANCEE = 'relancee';
|
||||
|
|
@ -22,6 +19,7 @@ class LabSessionMachine extends Model
|
|||
'sante_a' => 'datetime',
|
||||
];
|
||||
|
||||
/** @return BelongsTo<LabSession, $this> */
|
||||
public function labSession(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(LabSession::class);
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* @property-read int|null $servies_count Nombre de LabSession déjà admises/actives/terminées/expirées, uniquement
|
||||
* quand chargé par `withCount('labSessions as servies_count', ...)` (StockChaud::cible()).
|
||||
*/
|
||||
class Seance extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public const PLANIFIEE = 'planifiee';
|
||||
|
||||
public const SALLE_ATTENTE = 'salle_attente';
|
||||
|
|
@ -34,16 +35,19 @@ class Seance extends Model
|
|||
return $this->visio_ouverte_a !== null && $this->visio_salle !== null;
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Classe, $this> */
|
||||
public function classe(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Classe::class);
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Lab, $this> */
|
||||
public function lab(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Lab::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<LabSession, $this> */
|
||||
public function labSessions(): HasMany
|
||||
{
|
||||
return $this->hasMany(LabSession::class);
|
||||
|
|
|
|||
|
|
@ -33,11 +33,13 @@ class User extends Authenticatable
|
|||
];
|
||||
}
|
||||
|
||||
/** @return BelongsTo<Etablissement, $this> */
|
||||
public function etablissement(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Etablissement::class);
|
||||
}
|
||||
|
||||
/** @return HasMany<Classe, $this> */
|
||||
public function classes(): HasMany
|
||||
{
|
||||
return $this->hasMany(Classe::class);
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ class DefinitionLab
|
|||
return count($this->machines);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $donnees
|
||||
*/
|
||||
private function __construct(array $donnees)
|
||||
{
|
||||
$this->identifiant = $donnees['id'];
|
||||
|
|
|
|||
|
|
@ -66,7 +66,14 @@ class StockChaud
|
|||
LUA;
|
||||
|
||||
for ($essai = 0; $essai < 3; $essai++) {
|
||||
$brut = Redis::eval($script, 2, self::clePretes($lab), self::ATTRIBUEES, time());
|
||||
// Redis::eval(...) (facade) : la classe réellement utilisée au
|
||||
// runtime (PhpRedisConnection) redispose les arguments pour
|
||||
// l'extension phpredis, mais PHPStan ne résout le mixin de la
|
||||
// façade Redis que sur la classe abstraite Connection (@mixin
|
||||
// \Redis, la signature native à 3 arguments) — jamais sur la
|
||||
// classe effective choisie par REDIS_CLIENT. `command()` est une
|
||||
// vraie méthode (pas un mixin) : même effet, correctement typé.
|
||||
$brut = Redis::command('eval', [$script, [self::clePretes($lab), self::ATTRIBUEES, time()], 2]);
|
||||
|
||||
if (! is_string($brut)) {
|
||||
return null;
|
||||
|
|
@ -135,7 +142,10 @@ class StockChaud
|
|||
*/
|
||||
public function retirer(string $lab, string $brut): bool
|
||||
{
|
||||
if ((int) Redis::lrem(self::clePretes($lab), 1, $brut) === 0) {
|
||||
// Même raison que dans prendre() : command() plutôt que le mixin de
|
||||
// la façade, qui ne voit pas le réordonnancement des arguments fait
|
||||
// par PhpRedisConnection::lrem().
|
||||
if ((int) Redis::command('lrem', [self::clePretes($lab), $brut, 1]) === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -373,11 +383,18 @@ class StockChaud
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array{nom: string, id: string}|null $stack
|
||||
* $stack vient d'un `json_decode` (Redis) : sa forme n'est pas garantie
|
||||
* par le type (contrairement à ce que laissait croire l'ancienne
|
||||
* signature `array{nom: string, id: string}`, qui rendait les `isset()`
|
||||
* ci-dessous inutiles aux yeux de PHPStan alors qu'ils sont le seul
|
||||
* rempart contre une entrée du stock corrompue ou tronquée).
|
||||
*
|
||||
* @param array<string, mixed>|null $stack
|
||||
*/
|
||||
private function estUtilisable(?array $stack): bool
|
||||
{
|
||||
if ($stack === null || ! isset($stack['nom'], $stack['id'], $stack['instances'])) {
|
||||
if ($stack === null || ! isset($stack['nom'], $stack['id'], $stack['instances'])
|
||||
|| ! is_string($stack['nom']) || ! is_string($stack['id'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use App\Services\Labs\DefinitionLab;
|
|||
class GenerateurTemplateHeat
|
||||
{
|
||||
/**
|
||||
* @return array{template: array, noms_machines: array<int, string>}
|
||||
* @return array{template: array<string, mixed>, noms_machines: array<int, string>}
|
||||
*/
|
||||
public function genererDepuis(DefinitionLab $lab, string $prefixe): array
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Services\OpenStack;
|
||||
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use RuntimeException;
|
||||
|
||||
|
|
@ -15,6 +16,7 @@ class HeatClient
|
|||
public function __construct(private readonly KeystoneAuth $auth) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $template
|
||||
* @return array{id: string}
|
||||
*/
|
||||
public function creerStack(string $nom, array $template): array
|
||||
|
|
@ -86,7 +88,7 @@ class HeatClient
|
|||
}
|
||||
}
|
||||
|
||||
private function requete()
|
||||
private function requete(): PendingRequest
|
||||
{
|
||||
return Http::withHeaders(['X-Auth-Token' => $this->auth->jeton()]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
"larastan/larastan": "^3.0",
|
||||
"laravel/pail": "^1.2.5",
|
||||
"laravel/pao": "^1.0.6",
|
||||
"laravel/pint": "^1.27",
|
||||
|
|
|
|||
200
portail/composer.lock
generated
200
portail/composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "69a4c7e65a216e8a691794b9b63cfe39",
|
||||
"content-hash": "0d410ce6600351e37dc21a4c2f27fe2b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
|
|
@ -6314,12 +6314,12 @@
|
|||
"version": "v5.7.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vlucas/phpdotenv.git",
|
||||
"url": "https://github.com/phpdotenv/phpdotenv.git",
|
||||
"reference": "301c07936b16d88628b126b01d082ba153cf4c40"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/301c07936b16d88628b126b01d082ba153cf4c40",
|
||||
"url": "https://api.github.com/repos/phpdotenv/phpdotenv/zipball/301c07936b16d88628b126b01d082ba153cf4c40",
|
||||
"reference": "301c07936b16d88628b126b01d082ba153cf4c40",
|
||||
"shasum": ""
|
||||
},
|
||||
|
|
@ -7003,6 +7003,47 @@
|
|||
},
|
||||
"time": "2026-03-17T11:56:53+00:00"
|
||||
},
|
||||
{
|
||||
"name": "iamcal/sql-parser",
|
||||
"version": "v0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/iamcal/SQLParser.git",
|
||||
"reference": "610392f38de49a44dab08dc1659960a29874c4b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/iamcal/SQLParser/zipball/610392f38de49a44dab08dc1659960a29874c4b8",
|
||||
"reference": "610392f38de49a44dab08dc1659960a29874c4b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^1.0",
|
||||
"phpunit/phpunit": "^5|^6|^7|^8|^9"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"iamcal\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cal Henderson",
|
||||
"email": "cal@iamcal.com"
|
||||
}
|
||||
],
|
||||
"description": "MySQL schema parser",
|
||||
"support": {
|
||||
"issues": "https://github.com/iamcal/SQLParser/issues",
|
||||
"source": "https://github.com/iamcal/SQLParser/tree/v0.7"
|
||||
},
|
||||
"time": "2026-01-28T22:20:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
"version": "2.1.1",
|
||||
|
|
@ -7063,6 +7104,95 @@
|
|||
},
|
||||
"time": "2025-03-19T14:43:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "larastan/larastan",
|
||||
"version": "v3.13.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/larastan/larastan.git",
|
||||
"reference": "24ee69a7705ffc7c2cd8a3c96a5f498a4c2de5e3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/24ee69a7705ffc7c2cd8a3c96a5f498a4c2de5e3",
|
||||
"reference": "24ee69a7705ffc7c2cd8a3c96a5f498a4c2de5e3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"iamcal/sql-parser": "^0.7.0",
|
||||
"illuminate/console": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/container": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/contracts": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/database": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/http": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/pipeline": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/support": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"php": "^8.2",
|
||||
"phpstan/phpstan": "^2.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^14",
|
||||
"laravel/framework": "^11.44.2 || ^12.7.2 || ^13",
|
||||
"mockery/mockery": "^1.6.12",
|
||||
"nikic/php-parser": "^5.4",
|
||||
"orchestra/canvas": "^v9.2.2 || ^10.0.1 || ^11",
|
||||
"orchestra/testbench-core": "^9.12.0 || ^10.1 || ^11",
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0.1",
|
||||
"phpunit/phpunit": "^10.5.35 || ^11.5.15 || ^12.5.8 || ^13.3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"orchestra/testbench": "Using Larastan for analysing a package needs Testbench",
|
||||
"phpmyadmin/sql-parser": "Install to enable Larastan's optional phpMyAdmin-based SQL parser automatically"
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
"extra": {
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"extension.neon"
|
||||
]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Larastan\\Larastan\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Can Vural",
|
||||
"email": "can9119@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel",
|
||||
"keywords": [
|
||||
"PHPStan",
|
||||
"code analyse",
|
||||
"code analysis",
|
||||
"larastan",
|
||||
"laravel",
|
||||
"package",
|
||||
"php",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/larastan/larastan/issues",
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.13.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/canvural",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-10-07T14:14:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/agent-detector",
|
||||
"version": "v2.0.4",
|
||||
|
|
@ -8408,6 +8538,70 @@
|
|||
},
|
||||
"time": "2026-09-27T20:07:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.3.1",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/6155239b488e95d26d1ebd95c6b4bb294d7f09db",
|
||||
"reference": "6155239b488e95d26d1ebd95c6b4bb294d7f09db",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
},
|
||||
"bin": [
|
||||
"phpstan",
|
||||
"phpstan.phar"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ondřej Mirtes"
|
||||
},
|
||||
{
|
||||
"name": "Markus Staab"
|
||||
},
|
||||
{
|
||||
"name": "Vincent Langlet"
|
||||
}
|
||||
],
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"keywords": [
|
||||
"dev",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"security": "https://github.com/phpstan/phpstan/security/policy",
|
||||
"source": "https://github.com/phpstan/phpstan-src"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ondrejmirtes",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/phpstan",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-10-08T21:09:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "12.5.8",
|
||||
|
|
|
|||
14
portail/phpstan.neon
Normal file
14
portail/phpstan.neon
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
includes:
|
||||
- vendor/larastan/larastan/extension.neon
|
||||
|
||||
parameters:
|
||||
paths:
|
||||
- app
|
||||
level: 6
|
||||
tmpDir: storage/phpstan
|
||||
|
||||
# Les tests ont leur propre style (fonctions globales Pest, helpers de
|
||||
# tests/Feature/*), analysés à part s'il y a un jour un intérêt à le
|
||||
# faire — pas une exigence du CLAUDE.md (PHPStan niveau 6 sur `app/`).
|
||||
excludePaths:
|
||||
- app/Providers/*ServiceProvider.php
|
||||
Loading…
Add table
Add a link
Reference in a new issue