conception/update #93

Merged
mael.daim merged 7 commits from conception/update into master 1 year ago

@ -64,7 +64,7 @@ et de reporter le plus d'erreurs possibles lorsqu'une requête ne valide pas le
public function doPostAction(array $form): HttpResponse { public function doPostAction(array $form): HttpResponse {
$failures = []; $failures = [];
$req = HttpRequest::from($form, $failures, [ $req = HttpRequest::from($form, $failures, [
'email' => [Validators::email(), Validators::isLenBetween(6, 64)] 'email' => [DefaultValidators::email(), DefaultValidators::isLenBetween(6, 64)]
]); ]);
if (!empty($failures)) { //ou $req == null if (!empty($failures)) { //ou $req == null

@ -0,0 +1,81 @@
# Welcome on the documentation's description
## Let's get started with the architecture diagram.
![architecture diagram](./assets/architecture.svg)
As you can see our entire application is build around three main package.
All of them contained in "src" package.
The core represent the main code of the web application.
It contains all the validation protocol, detailed below, the model of the imposed MVC architecture.
It also has a package named "data", it is a package of the structure of all the data we use in our application.
Of course there is package containing all the gateways as its name indicates. It is where we use the connection to our database.
Allowing to operate on it.
The App now is more about the web application itself.
Having all the controllers of the MVC architecture the use the model, the validation system and the http system in the core.
It also calls the twig's views inside of App. Finally, it uses the package Session. This one replace the $_SESSION we all know in PHP.
Thanks to this we have a way cleaner use of all session's data.
Nevertheless, all the controllers call not only twig views but also react ones.
Those are present in the package "front", dispatched in several other packages.
Such as assets having all the image and stuff, model containing all the data's structure, style centralizing all css file and eventually components the last package used for the editor.
Finally, we have the package "Api" that allows to share code and bind all the different third-hand application such as the web admin one.
## Main data class diagram.
![Class diagram](./assets/models.svg)
You can see how our data is structured contained in the package "data" as explained right above.
There is two clear part.
First of all, the Tactic one.
We got a nice class named TacticInfo representing as it says the information about a tactic, nothing to discuss more about.
It associates an attribute of type "CourtType". This last is just an "evoluated" type of enum with some more features.
We had to do it this way because of the language PHP that doesn't implement such a thing as an enum.
Now, let's discuss a much bigger part of the diagram.
In this part we find all the team logic. Actually, a team only have an array of members and a "TeamInfo".
The class "TeamInfo" only exists to split the team's information data (name, id etc) from the members.
The type Team does only link the information about a team and its members.
Talking about them, their class indicate what role they have (either Coach or Player) in the team.
Because a member is registered in the app, therefore he is a user of it. Represented by the type of the same name.
This class does only contain all the user's basic information.
The last class we have is the Account. It could directly be incorporated in User but we decided to split it the same way we did for the team.
Then, Account only has a user and a token which is an identifier.
## Validation's class diagram
![validation's class diagram](./assets/validation.svg)
We implemented our own validation system, here it is!
For the validation methods (for instance those in DefaultValidators) we use lambda to instantiate a Validator.
In general, we use the implementation "SimpleFunctionValidator".
We reconize the strategy pattern. Indeed, we need a family of algorithms because we have many classes that only differ by the way they validate.
Futhermore, you may have notices the ComposedValidator that allows to chain several Validator.
We can see that this system uses the composite pattern
The other part of the diagram is about the failure a specific field's validation.
We have a concrete class to return a something more general. All the successors are just more precise about the failure.
## Http's class diagram
![Http's class diagram](./assets/http.svg)
It were we centralize what the app can render, and what the api can receive.
Then, we got the "basic" response (HttpResponse) that just render a HttpCodes.
We have two successors for now. ViewHttpResponse render not only a code but also a view, either react or twig ones.
Finally, we have the JsonHttpResponse that renders, as it's name says, some Json.
## Session's class diagram
![Session's class diagram](./assets/session.svg)
It encapsulates the PHP's array "$_SESSION". With two interfaces that dictate how a session should be handled, and same for a mutable one.
## Model View Controller
All class diagram, separated by their range of action, of the imposed MVC architecture.
All of them have a controller that validates entries with the validation system and check the permission the user has,and whether or not actually do the action.
These controllers are composed by a Model that handle the pure data and is the point of contact between these and the gateways.
Speaking of which, Gateways are composing Models. They use the connection class to access the database and send their query.
### Team
![team's mvc](./assets/team.svg)
### Editor
![editor's mvc](./assets/editor.svg)
### Authentification
![auth's mvc](./assets/auth.svg)

@ -0,0 +1,60 @@
@startuml
'https://plantuml.com/component-diagram
package front{
package assets
package components
package model
package style
package views
}
database sql{
}
package src {
package "Api"{
}
package "App" {
package Controller
package Session
package Views
}
package Core{
package Data
package Gateway
package Http
package Model
package Validation
[Connection]
}
}
[sql] -- [Connection]
[views] -- [style]
[views] -- [components]
[views] -- [assets]
[views] -- [model]
[Gateway] -- [Connection]
[Validation] -- [Controller]
[Controller] -- [Session]
[Controller] -- [Http]
[Controller] -- [Views]
[Controller] -- [views]
[Controller] -- [Model]
[Model] -- [Gateway]
[Api] -- [Validation]
[Api] -- [Model]
[Api] -- [Http]
@enduml

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 32 KiB

@ -15,37 +15,51 @@ class HttpRequest implements ArrayAccess {
class HttpResponse { class HttpResponse {
- code: int - code: int
+ __construct(code: int) - headers : array
+ __construct(code: int,headers:array)
+ getCode(): int + getCode(): int
+ getHeaders(): array
<u>fromCode(code: int): HttpResponse + redirect(url:string, code:int): HttpResponse {static}
+ fromCode(code: int): HttpResponse {static}
} }
class JsonHttpResponse extends HttpResponse { class JsonHttpResponse extends HttpResponse {
- payload: mixed - payload: mixed
+ __construct(payload: mixed, code: int = HttpCodes::OK) + __construct(payload: mixed, code: int)
+ getJson(): string + getJson(): string
} }
class ViewHttpResponse extends HttpResponse { class ViewHttpResponse extends HttpResponse {
+ <u>TWIG_VIEW: int {frozen} + TWIG_VIEW: int {frozen} {static}
+ <u>REACT_VIEW: int {frozen} + REACT_VIEW: int {frozen} {static}
- file: string - file: string
- arguments: array - arguments: array
- kind: int - kind: int
- __construct(kind: int, file: string, arguments: array, code: int = HttpCodes::OK) - __construct(kind: int, file: string, arguments: array, code: int)
+ getViewKind(): int + getViewKind(): int
+ getFile(): string + getFile(): string
+ getArguments(): array + getArguments(): array
+ <u>twig(file: string, arguments: array, code: int = HttpCodes::OK): ViewHttpResponse + <u>twig(file: string, arguments: array, code: int): ViewHttpResponse
+ <u>react(file: string, arguments: array, code: int = HttpCodes::OK): ViewHttpResponse + <u>react(file: string, arguments: array, code: int): ViewHttpResponse
} }
note right of ViewHttpResponse note right of ViewHttpResponse
Into src/App Into src/App
end note end note
class HttpCodes{
+ OK : int {static} {frozen}
+ FOUND : int {static} {frozen}
+ BAD_REQUEST : int {static} {frozen}
+ UNAUTHORIZED : int {static} {frozen}
+ FORBIDDEN : int {static} {frozen}
+ NOT_FOUND : int {static} {frozen}
}
HttpCodes <.. ViewHttpResponse
HttpCodes <.. HttpResponse
@enduml @enduml

@ -6,70 +6,93 @@ class TacticInfo {
- creationDate: string - creationDate: string
- ownerId: string - ownerId: string
- content: string - content: string
+ __construct(id:int,name:string,creationDate:int,ownerId:int,courtType:CourtType,content:string)
+ getId(): int + getId(): int
+ getOwnerId(): int + getOwnerId(): int
+ getCreationTimestamp(): int + getCreationTimestamp(): int
+ getName(): string + getName(): string
+ getContent(): string + getContent(): string
+ getCourtType() : CourtType
} }
TacticInfo -->"- courtType" CourtType
class CourtType{
- value : int
- COURT_PLAIN : int {static} {frozen}
- COURT_HALF : int {static} {frozen}
- __construct(val:int)
+ plain() : CourtType {static}
+ half() : CourtType {static}
+ name() : string
+ fromName(name:string) : CourtType
+ isPlain() : bool
+ isHalf() : bool
}
note bottom: Basically an evoluated enum
class Account { class Account {
- email: string
- token: string - token: string
- name: string
- id: int
+ getMailAddress(): string + __construct(token:string,user:User)
+ getToken(): string + getUser() : User
+ getName(): string + getToken() : string
+ getId(): int
} }
Account -->"- user" User
class Member { class Member {
- userId: int
- teamId: int - teamId: int
- role : string
+ __construct(role : MemberRole) + __construct(role : string)
+ getUserId(): int + getUser(): User
+ getTeamId(): int + getTeamId(): int
+ getRole(): MemberRole + getRole(): string
} }
Member --> "- role" MemberRole note bottom: Member's role is either "Coach" or "Player"
enum MemberRole {
PLAYER
COACH
}
Member -->"- user" User
class TeamInfo { class TeamInfo {
- creationDate: int
- name: string - name: string
- picture: string - picture: string
- mainColor : string
- secondColor : string
+ __construct(id:int,name:string,picture:string,mainColor:string,secondColor:string)
+ getName(): string + getName(): string
+ getPicture(): string + getPicture(): string
+ getMainColor(): Color + getMainColor(): string
+ getSecondColor(): Color + getSecondColor(): string
} }
TeamInfo --> "- mainColor" Color note left: Both team's color are the hex code of the color
TeamInfo --> "- secondaryColor" Color
class Team { class Team {
getInfo(): TeamInfo + __construct(info:TeamInfo,members: Member[])
listMembers(): Member[] + getInfo(): TeamInfo
+ listMembers(): Member[]
} }
Team --> "- info" TeamInfo Team --> "- info" TeamInfo
Team --> "- members *" Member Team --> "- members *" Member
class Color { class User{
- value: int - id : int
- name : string
+ getValue(): int - email : string
- profilePicture : string
+ __construct(id : int,name : string,email: string,profilePicture:string)
+ getId() : id
+ getName() : string
+ getEmail() : string
+ getProfilePicture() : string
} }
@enduml @enduml

@ -7,26 +7,26 @@ class AuthController {
+ displayLogin() : HttpResponse + displayLogin() : HttpResponse
+ login(request : array , session : MutableSessionHandle) : HttpResponse + login(request : array , session : MutableSessionHandle) : HttpResponse
} }
AuthController --> "- model" AuthModel AuthController *-- "- model" AuthModel
class AuthModel { class AuthModel {
+__construct(gateway : AccountGateway) + __construct(gateway : AccountGateway)
+ register(username : string, password : string, confirmPassword : string, email : string, failures : array): Account + register(username:string, password:string, confirmPassword:string, email:string, &failures:array): ?Account + generateToken() : string
+ generateToken() : string + generateToken(): string
+ login(email : string, password : string) + login(email:string, password:string, &failures:array): ?Account
} }
AuthModel --> "- gateway" AccountGateway AuthModel *-- "- gateway" AccountGateway
class AccountGateway {
-con : Connection
+__construct(con : Connection)
+ insertAccount(name : string, email : string, hash : string, token : string) : int
+ getRowsFromMail(email : string): array
+ getHash(email : string) : array
+ exists(email : string) : bool
+ getAccountFromMail(email : string ): Account
+ getAccountFromToken(email : string ): Account
class AccountGateway{
+ __construct(con : Connexion)
+ insertAccount(name:string, email:string, token:string, hash:string, profilePicture:string): int
+ getRowsFromMail(email:string): ?array
+ getHash(email:string): ?string
+ exists(email:string): bool
+ getAccountFromMail(email:string): ?Account
+ getAccountFromToken(token:string): ?Account
} }
AccountGateway *--"- con" Connexion
@enduml @enduml

@ -0,0 +1,44 @@
@startuml
class EditorController {
+__construct (model : TacticModel)
+ openEditorFor(tactic:TacticInfo): ViewHttpResponse
+ createNew(): ViewHttpResponse
+ openTestEditor(courtType:CourtType): ViewHttpResponse
+ createNewOfKind(type:CourtType, session:SessionHandle): ViewHttpResponse
+ openEditor(id:int, session:SessionHandle): ViewHttpResponse
}
EditorController *-- "- model" TacticModel
class TacticModel {
+ TACTIC_DEFAULT_NAME:int {static}{frozen}
+ __construct(tactics : TacticInfoGateway)
+ makeNew(name:string, ownerId:int, type:CourtType): TacticInfo
+ makeNewDefault(ownerId:int, type:CourtType): ?TacticInfo
+ get(id:int): ?TacticInfo
+ getLast(nb:int, ownerId:int): array
+ getAll(ownerId:int): ?array
+ updateName(id:int, name:string, authId:int): array
+ updateContent(id:int, json:string): ?ValidationFail
}
TacticModel *-- "- tactics" TacticInfoGateway
class TacticInfoGateway{
+ __construct(con : Connexion)
+ get(id:int): ?TacticInfo
+ getLast(nb:int, ownerId:int): ?array
+ getAll(ownerId:int): ?array
+ insert(name:string, owner:int, type:CourtType): int
+ updateName(id:int, name:string): bool
+ updateContent(id:int, json:string): bool
}
TacticInfoGateway *--"- con" Connexion
class TacticValidator{
+ validateAccess(tacticId:int, tactic:?TacticInfo, ownerId:int): ?ValidationFail {static}
}
EditorController ..> TacticValidator
@enduml

@ -1,63 +1,87 @@
@startuml @startuml
class Team {
- name: string
- picture: Url
- members: array<int, MemberRole>
+ __construct(name : string, picture : string, mainColor : Colo, secondColor : Color)
+ getName(): string
+ getPicture(): Url
+ getMainColor(): Color
+ getSecondColor(): Color
+ listMembers(): array<Member>
}
Team --> "- mainColor" Color
Team --> "- secondColor" Color
class Color {
- value: string
- __construct(value : string)
+ getValue(): string
+ from(value: string): Color
+ tryFrom(value : string) : ?Color
}
class TeamGateway{ class TeamGateway{
--
+ __construct(con : Connexion) + __construct(con : Connexion)
+ insert(name : string ,picture : string, mainColor : Color, secondColor : Color) + insert(name : string ,picture : string, mainColor : Color, secondColor : Color)
+ listByName(name : string): array + listByName(name : string): array
+ getTeamById(id:int): ?TeamInfo
+ getTeamIdByName(name:string): ?int
+ deleteTeam(idTeam:int): void
+ editTeam(idTeam:int, newName:string, newPicture:string, newMainColor:string, newSecondColor:string)
+ getAll(user:int): array
} }
TeamGateway *--"- con" Connexion TeamGateway *--"- con" Connexion
TeamGateway ..> Color
class MemberGateway{
+ __construct(con : Connexion)
+ insert(idTeam:int, userId:int, role:string): void
+ getMembersOfTeam(teamId:int): array
+ remove(idTeam:int, idMember:int): void
+ isCoach(email:string, idTeam:int): bool
+ isMemberOfTeam(idTeam:int, idCurrentUser:int): bool
}
MemberGateway *--"- con" Connexion
class AccountGateway{
+ __construct(con : Connexion)
+ insertAccount(name:string, email:string, token:string, hash:string, profilePicture:string): int
+ getRowsFromMail(email:string): ?array
+ getHash(email:string): ?string
+ exists(email:string): bool
+ getAccountFromMail(email:string): ?Account
+ getAccountFromToken(token:string): ?Account
}
AccountGateway *--"- con" Connexion
class TeamModel{ class TeamModel{
---
+ __construct(gateway : TeamGateway) + __construct(gateway : TeamGateway)
+ createTeam(name : string,picture : string, mainColorValue : int, secondColorValue : int, errors : array) + createTeam(name : string,picture : string, mainColorValue : int, secondColorValue : int, errors : array)
+ addMember(mail:string, teamId:int, role:string): int
+ listByName(name : string ,errors : array) : ?array + listByName(name : string ,errors : array) : ?array
+ displayTeam(id : int): Team + getTeam(idTeam:int, idCurrentUser:int): ?Team
+ deleteMember(idMember:int, teamId:int): int
+ deleteTeam(email:string, idTeam:int): int
+ isCoach(idTeam:int, email:string): bool
+ editTeam(idTeam:int, newName:string, newPicture:string, newMainColor:string, newSecondColor:string)
+ getAll(user:int): array
} }
TeamModel *--"- gateway" TeamGateway TeamModel *--"- members" MemberGateway
TeamModel ..> Team TeamModel *--"- teams" TeamGateway
TeamModel ..> Color TeamModel *--"- teams" AccountGateway
class TeamController{ class TeamController{
- twig : Environement + __construct( model : TeamModel)
-- + displayCreateTeam(session:SessionHandle): ViewHttpResponse
+ __construct( model : TeamModel, twig : Environement) + displayDeleteMember(session:SessionHandle): ViewHttpResponse
+ displaySubmitTeam() : HttpResponse + submitTeam(request:array, session:SessionHandle): HttpResponse
+ submitTeam(request : array) : HttpResponse + displayListTeamByName(session:SessionHandle): ViewHttpResponse
+ displayListTeamByName(): HttpResponse + listTeamByName(request:array, session:SessionHandle): HttpResponse
+ listTeamByName(request : array) : HttpResponse + deleteTeamById(id:int, session:SessionHandle): HttpResponse
+ displayTeam(id : int): HttpResponse + displayTeam(id:int, session:SessionHandle): ViewHttpResponse
+ displayAddMember(idTeam:int, session:SessionHandle): ViewHttpResponse
+ addMember(idTeam:int, request:array, session:SessionHandle): HttpResponse
+ deleteMember(idTeam:int, idMember:int, session:SessionHandle): HttpResponse
+ displayEditTeam(idTeam:int, session:SessionHandle): ViewHttpResponse
+ editTeam(idTeam:int, request:array, session:SessionHandle): HttpResponse
} }
TeamController *--"- model" TeamModel TeamController *--"- model" TeamModel
class Connexion { } class Connexion { }
@enduml @enduml

@ -0,0 +1,27 @@
@startuml
interface SessionHandle{
+ getInitialTarget(): ?string {abstract}
+ getAccount(): ?Account {abstract}
}
interface MutableSessionHandle{
+ setInitialTarget(url:?string): void
+ setAccount(account:Account): void
+ destroy(): void
}
class PhpSessionHandle{
+ init(): self {static}
+ getAccount(): ?Account
+ getInitialTarget(): ?string
+ setAccount(account:Account): void
+ setInitialTarget(url:?string): void
+ destroy(): void
}
PhpSessionHandle ..|> MutableSessionHandle
MutableSessionHandle ..|> SessionHandle
@enduml

@ -1,18 +1,20 @@
@startuml @startuml
abstract class Validator { abstract class Validator {
+ validate(name: string, val: mixed): array + validate(name: string, val: mixed): array {abstract}
+ then(other: Validator): Validator + then(other: Validator): Validator
} }
class ComposedValidator extends Validator { class ComposedValidator extends Validator {
- first: Validator
- then: Validator
+ __construct(first: Validator, then: Validator) + __construct(first: Validator, then: Validator)
validate(name: string, val: mixed): array + validate(name: string, val: mixed): array
} }
ComposedValidator -->"- first" Validator
ComposedValidator -->"- then" Validator
class SimpleFunctionValidator extends Validator { class SimpleFunctionValidator extends Validator {
- predicate: callable - predicate: callable
- error_factory: callable - error_factory: callable
@ -28,9 +30,9 @@ class ValidationFail implements JsonSerialize {
+ __construct(kind: string, message: string) + __construct(kind: string, message: string)
+ getMessage(): string + getMessage(): string
+ getKind(): string + getKind(): string
+ jsonSerialize()
+ <u>notFound(message: string): ValidationFail + <u>notFound(message: string): ValidationFail
+ <u>unauthorized(message:string): ValidationFail
+ <u>error(message:string): ValidationFail
} }
class FieldValidationFail extends ValidationFail { class FieldValidationFail extends ValidationFail {
@ -49,13 +51,31 @@ class Validation {
<u> + validate(val: mixed, valName: string, failures: &array, validators: Validator...): bool <u> + validate(val: mixed, valName: string, failures: &array, validators: Validator...): bool
} }
class Validators { Validation ..> Validator
---
class DefaultValidators {
+ <u>nonEmpty(): Validator + <u>nonEmpty(): Validator
+ <u>shorterThan(limit: int): Validator + <u>shorterThan(limit: int): Validator
+ <u>userString(maxLen: int): Validator + <u>userString(maxLen: int): Validator
... + <u>regex(regex:string, msg:string): Validator
+ <u>hex(msg:string): Validator
+ <u>name(msg:string): Validator
+ <u>nameWithSpaces(): Validator
+ <u>lenBetween(min:int, max:int): Validator
+ <u>email(msg:string): Validator
+ <u>isInteger(): Validator
+ <u>isIntInRange(min:int, max:int): Validator
+ <u>isURL(): Validator
}
DefaultValidators ..> Validator
class FunctionValidator{
- validate_fn: callable
+ __construct(validate_fn:callable)
+ validate(name:string, val:mixed): array
} }
Validator <|-- FunctionValidator
@enduml @enduml

@ -8,7 +8,7 @@ use IQBall\Core\Http\HttpRequest;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\JsonHttpResponse; use IQBall\Core\Http\JsonHttpResponse;
use IQBall\Core\Model\AuthModel; use IQBall\Core\Model\AuthModel;
use IQBall\Core\Validation\Validators; use IQBall\Core\Validation\DefaultValidators;
class APIAuthController { class APIAuthController {
private AuthModel $model; private AuthModel $model;
@ -27,8 +27,8 @@ class APIAuthController {
*/ */
public function authorize(): HttpResponse { public function authorize(): HttpResponse {
return Control::runChecked([ return Control::runChecked([
"email" => [Validators::email(), Validators::lenBetween(5, 256)], "email" => [DefaultValidators::email(), DefaultValidators::lenBetween(5, 256)],
"password" => [Validators::lenBetween(6, 256)], "password" => [DefaultValidators::lenBetween(6, 256)],
], function (HttpRequest $req) { ], function (HttpRequest $req) {
$failures = []; $failures = [];
$account = $this->model->login($req["email"], $req["password"], $failures); $account = $this->model->login($req["email"], $req["password"], $failures);

@ -10,7 +10,7 @@ use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Http\JsonHttpResponse; use IQBall\Core\Http\JsonHttpResponse;
use IQBall\Core\Model\TacticModel; use IQBall\Core\Model\TacticModel;
use IQBall\Core\Validation\FieldValidationFail; use IQBall\Core\Validation\FieldValidationFail;
use IQBall\Core\Validation\Validators; use IQBall\Core\Validation\DefaultValidators;
/** /**
* API endpoint related to tactics * API endpoint related to tactics
@ -33,7 +33,7 @@ class APITacticController {
*/ */
public function updateName(int $tactic_id, Account $account): HttpResponse { public function updateName(int $tactic_id, Account $account): HttpResponse {
return Control::runChecked([ return Control::runChecked([
"name" => [Validators::lenBetween(1, 50), Validators::nameWithSpaces()], "name" => [DefaultValidators::lenBetween(1, 50), DefaultValidators::nameWithSpaces()],
], function (HttpRequest $request) use ($tactic_id, $account) { ], function (HttpRequest $request) use ($tactic_id, $account) {
$failures = $this->model->updateName($tactic_id, $request["name"], $account->getUser()->getId()); $failures = $this->model->updateName($tactic_id, $request["name"], $account->getUser()->getId());

@ -11,7 +11,7 @@ use IQBall\Core\Validation\Validator;
class Control { class Control {
/** /**
* Runs given callback, if the request's json validates the given schema. * Runs given callback, if the request's json validates the given schema.
* @param array<string, Validator[]> $schema an array of `fieldName => Validators` which represents the request object schema * @param array<string, Validator[]> $schema an array of `fieldName => DefaultValidators` which represents the request object schema
* @param callable(HttpRequest): HttpResponse $run the callback to run if the request is valid according to the given schema. * @param callable(HttpRequest): HttpResponse $run the callback to run if the request is valid according to the given schema.
* THe callback must accept an HttpRequest, and return an HttpResponse object. * THe callback must accept an HttpRequest, and return an HttpResponse object.
* @return HttpResponse * @return HttpResponse
@ -30,7 +30,7 @@ class Control {
/** /**
* Runs given callback, if the given request data array validates the given schema. * Runs given callback, if the given request data array validates the given schema.
* @param array<string, mixed> $data the request's data array. * @param array<string, mixed> $data the request's data array.
* @param array<string, Validator[]> $schema an array of `fieldName => Validators` which represents the request object schema * @param array<string, Validator[]> $schema an array of `fieldName => DefaultValidators` which represents the request object schema
* @param callable(HttpRequest): HttpResponse $run the callback to run if the request is valid according to the given schema. * @param callable(HttpRequest): HttpResponse $run the callback to run if the request is valid according to the given schema.
* THe callback must accept an HttpRequest, and return an HttpResponse object. * THe callback must accept an HttpRequest, and return an HttpResponse object.
* @return HttpResponse * @return HttpResponse

@ -7,7 +7,7 @@ use IQBall\App\ViewHttpResponse;
use IQBall\Core\Http\HttpRequest; use IQBall\Core\Http\HttpRequest;
use IQBall\Core\Http\HttpResponse; use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Model\AuthModel; use IQBall\Core\Model\AuthModel;
use IQBall\Core\Validation\Validators; use IQBall\Core\Validation\DefaultValidators;
class AuthController { class AuthController {
private AuthModel $model; private AuthModel $model;
@ -32,10 +32,10 @@ class AuthController {
public function register(array $request, MutableSessionHandle $session): HttpResponse { public function register(array $request, MutableSessionHandle $session): HttpResponse {
$fails = []; $fails = [];
HttpRequest::from($request, $fails, [ HttpRequest::from($request, $fails, [
"username" => [Validators::name(), Validators::lenBetween(2, 32)], "username" => [DefaultValidators::name(), DefaultValidators::lenBetween(2, 32)],
"password" => [Validators::lenBetween(6, 256)], "password" => [DefaultValidators::lenBetween(6, 256)],
"confirmpassword" => [Validators::lenBetween(6, 256)], "confirmpassword" => [DefaultValidators::lenBetween(6, 256)],
"email" => [Validators::email(), Validators::lenBetween(5, 256)], "email" => [DefaultValidators::email(), DefaultValidators::lenBetween(5, 256)],
]); ]);
if (!empty($fails)) { if (!empty($fails)) {

@ -11,7 +11,7 @@ use IQBall\Core\Http\HttpResponse;
use IQBall\Core\Model\TeamModel; use IQBall\Core\Model\TeamModel;
use IQBall\Core\Validation\FieldValidationFail; use IQBall\Core\Validation\FieldValidationFail;
use IQBall\Core\Validation\ValidationFail; use IQBall\Core\Validation\ValidationFail;
use IQBall\Core\Validation\Validators; use IQBall\Core\Validation\DefaultValidators;
class TeamController { class TeamController {
private TeamModel $model; private TeamModel $model;
@ -48,10 +48,10 @@ class TeamController {
public function submitTeam(array $request, SessionHandle $session): HttpResponse { public function submitTeam(array $request, SessionHandle $session): HttpResponse {
$failures = []; $failures = [];
$request = HttpRequest::from($request, $failures, [ $request = HttpRequest::from($request, $failures, [
"name" => [Validators::lenBetween(1, 32), Validators::nameWithSpaces()], "name" => [DefaultValidators::lenBetween(1, 32), DefaultValidators::nameWithSpaces()],
"main_color" => [Validators::hexColor()], "main_color" => [DefaultValidators::hexColor()],
"second_color" => [Validators::hexColor()], "second_color" => [DefaultValidators::hexColor()],
"picture" => [Validators::isURL()], "picture" => [DefaultValidators::isURL()],
]); ]);
if (!empty($failures)) { if (!empty($failures)) {
$badFields = []; $badFields = [];
@ -84,7 +84,7 @@ class TeamController {
public function listTeamByName(array $request, SessionHandle $session): HttpResponse { public function listTeamByName(array $request, SessionHandle $session): HttpResponse {
$errors = []; $errors = [];
$request = HttpRequest::from($request, $errors, [ $request = HttpRequest::from($request, $errors, [
"name" => [Validators::lenBetween(1, 32), Validators::nameWithSpaces()], "name" => [DefaultValidators::lenBetween(1, 32), DefaultValidators::nameWithSpaces()],
]); ]);
if (!empty($errors) && $errors[0] instanceof FieldValidationFail) { if (!empty($errors) && $errors[0] instanceof FieldValidationFail) {
@ -166,7 +166,7 @@ class TeamController {
], HttpCodes::FORBIDDEN); ], HttpCodes::FORBIDDEN);
} }
$request = HttpRequest::from($request, $errors, [ $request = HttpRequest::from($request, $errors, [
"email" => [Validators::email(), Validators::lenBetween(5, 256)], "email" => [DefaultValidators::email(), DefaultValidators::lenBetween(5, 256)],
]); ]);
if(!empty($errors)) { if(!empty($errors)) {
return ViewHttpResponse::twig('add_member.html.twig', ['badEmail' => true,'idTeam' => $idTeam]); return ViewHttpResponse::twig('add_member.html.twig', ['badEmail' => true,'idTeam' => $idTeam]);
@ -226,10 +226,10 @@ class TeamController {
} }
$failures = []; $failures = [];
$request = HttpRequest::from($request, $failures, [ $request = HttpRequest::from($request, $failures, [
"name" => [Validators::lenBetween(1, 32), Validators::nameWithSpaces()], "name" => [DefaultValidators::lenBetween(1, 32), DefaultValidators::nameWithSpaces()],
"main_color" => [Validators::hexColor()], "main_color" => [DefaultValidators::hexColor()],
"second_color" => [Validators::hexColor()], "second_color" => [DefaultValidators::hexColor()],
"picture" => [Validators::isURL()], "picture" => [DefaultValidators::isURL()],
]); ]);
if (!empty($failures)) { if (!empty($failures)) {
$badFields = []; $badFields = [];

@ -24,7 +24,6 @@ class TeamInfo implements \JsonSerializable {
$this->secondColor = $secondColor; $this->secondColor = $secondColor;
} }
public function getId(): int { public function getId(): int {
return $this->id; return $this->id;
} }
@ -48,6 +47,4 @@ class TeamInfo implements \JsonSerializable {
public function jsonSerialize() { public function jsonSerialize() {
return get_object_vars($this); return get_object_vars($this);
} }
} }

@ -11,7 +11,6 @@ use IQBall\Core\Validation\ValidationFail;
class TacticModel { class TacticModel {
public const TACTIC_DEFAULT_NAME = "Nouvelle tactique"; public const TACTIC_DEFAULT_NAME = "Nouvelle tactique";
private TacticInfoGateway $tactics; private TacticInfoGateway $tactics;
/** /**
@ -52,13 +51,6 @@ class TacticModel {
return $this->tactics->get($id); return $this->tactics->get($id);
} }
/**
* Return the nb last tactics created
*
* @param integer $nb
* @return array<array<string,mixed>>
*/
/** /**
* Return the nb last tactics * Return the nb last tactics
* *

@ -5,7 +5,7 @@ namespace IQBall\Core\Validation;
/** /**
* A collection of standard validators * A collection of standard validators
*/ */
class Validators { class DefaultValidators {
/** /**
* @return Validator a validator that validates a given regex * @return Validator a validator that validates a given regex
*/ */
Loading…
Cancel
Save