commit
ef572e5a2b
@ -1,61 +0,0 @@
|
|||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: HeartWave
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
|
|
||||||
steps:
|
|
||||||
|
|
||||||
# Test ✔️
|
|
||||||
- name: test
|
|
||||||
image: composer:2.6
|
|
||||||
commands:
|
|
||||||
- cd Sources
|
|
||||||
# Installe les dépendances PHP si nécessaire
|
|
||||||
- composer install --no-interaction
|
|
||||||
- ./vendor/bin/phpunit tests
|
|
||||||
|
|
||||||
# Sonar static code analisis deployment
|
|
||||||
# TODO : use an image that already have unzip
|
|
||||||
- name: code-analysis
|
|
||||||
image: php:8.1-cli
|
|
||||||
environment:
|
|
||||||
SONAR_TOKEN:
|
|
||||||
from_secret: SONAR_TOKEN
|
|
||||||
commands:
|
|
||||||
- apt-get update && apt-get install -y curl unzip
|
|
||||||
- export SONAR_SCANNER_VERSION=4.7.0.2747
|
|
||||||
- export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
|
|
||||||
- curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
|
|
||||||
- unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
|
|
||||||
- export PATH=$SONAR_SCANNER_HOME/bin:$PATH
|
|
||||||
- export SONAR_SCANNER_OPTS="-server"
|
|
||||||
- cd Sources
|
|
||||||
- sonar-scanner -D sonar.projectKey=HeartTrack -D sonar.host.url=https://codefirst.iut.uca.fr/sonar
|
|
||||||
depends_on: [ test ]
|
|
||||||
|
|
||||||
# build image and push on the registry ✔️
|
|
||||||
- name: docker-build-and-push
|
|
||||||
image: plugins/docker
|
|
||||||
settings:
|
|
||||||
dockerfile: Sources/config/Dockerfile
|
|
||||||
context: Sources
|
|
||||||
registry: hub.codefirst.iut.uca.fr
|
|
||||||
repo: hub.codefirst.iut.uca.fr/david.d_almeida/web
|
|
||||||
username:
|
|
||||||
from_secret: SECRET_REGISTRY_USERNAME
|
|
||||||
password:
|
|
||||||
from_secret: SECRET_REGISTRY_PASSWORD
|
|
||||||
|
|
||||||
- name: notify
|
|
||||||
image: ruby:2.1
|
|
||||||
when:
|
|
||||||
status: [ success ]
|
|
||||||
ref:
|
|
||||||
include:
|
|
||||||
- refs/tags/*-demo
|
|
||||||
commands:
|
|
||||||
- sh ./notifymail.sh
|
|
||||||
depends_on: [ docker-build-and-push ]
|
|
Binary file not shown.
@ -0,0 +1,131 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Router\Request\IRequest;
|
||||||
|
use App\Router\Response\Response;
|
||||||
|
use Database\ActivityGateway;
|
||||||
|
use Database\ActivityMapper;
|
||||||
|
use Database\Connexion;
|
||||||
|
use Json\JsonSerializer;
|
||||||
|
use Manager\UserManager;
|
||||||
|
use Shared\Attributes\Route;
|
||||||
|
use Shared\Log;
|
||||||
|
|
||||||
|
class ApiController extends BaseController
|
||||||
|
{
|
||||||
|
private UserManager $userMgr;
|
||||||
|
public function __construct(UserManager $manager){
|
||||||
|
parent::__construct();
|
||||||
|
$this->userMgr = $manager;
|
||||||
|
}
|
||||||
|
#[Route(path: '/api/activities', name: 'api-activities', methods: ['GET'])]
|
||||||
|
public function apiActivities(IRequest $request)
|
||||||
|
{
|
||||||
|
$activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
|
||||||
|
$listSearch = $activityGateway->getActivity();
|
||||||
|
$map = new ActivityMapper();
|
||||||
|
$activityGateway = $map->activitySqlToEntity($listSearch);
|
||||||
|
$listActivity = [];
|
||||||
|
foreach ($activityGateway as $entity) {
|
||||||
|
$activity = $map->activityEntityToModel($entity);
|
||||||
|
$listActivity[] = ['idactivity' => number_format($activity->getIdActivity()), 'type' => $activity->getType(),
|
||||||
|
'date' => $activity->getDate()->format("Y-m-d"), 'heureDebut' => $activity->getHeureDebut()->format("Y-m-d"), 'heureFin' => $activity->getHeureFin()->format("Y-m-d"),
|
||||||
|
'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
|
||||||
|
'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
|
||||||
|
'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' => $activity->getAvrTemperature()];
|
||||||
|
}
|
||||||
|
|
||||||
|
$jsonSerializer = new JsonSerializer();
|
||||||
|
$jsonData = $jsonSerializer::serialize($listActivity);
|
||||||
|
|
||||||
|
$response = new Response();
|
||||||
|
$response->setContent($jsonData);
|
||||||
|
$response->setHeader('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cela ne trouve pas la methode avec la route '/api/activities/1'
|
||||||
|
#[Route(path: '/api/activities/{id}', name: 'api-activities-by-id', methods: ['GET'])]
|
||||||
|
public function apiActivityById(IRequest $request, int $id)
|
||||||
|
{
|
||||||
|
$activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
|
||||||
|
$listSearch = $activityGateway->getActivityById($id);
|
||||||
|
Log::dd($listSearch);
|
||||||
|
$map = new ActivityMapper();
|
||||||
|
$activityGateway = $map->activitySqlToEntity($listSearch);
|
||||||
|
$listActivity = [];
|
||||||
|
foreach ($activityGateway as $entity) {
|
||||||
|
$activity = $map->activityEntityToModel($entity);
|
||||||
|
$listActivity[] = ['idactivity' => number_format($activity->getIdActivity()), 'type' => $activity->getType(),
|
||||||
|
'date' => $activity->getDate()->format("Y-m-d"), 'heureDebut' => $activity->getHeureDebut()->format("Y-m-d"), 'heureFin' => $activity->getHeureFin()->format("Y-m-d"),
|
||||||
|
'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
|
||||||
|
'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
|
||||||
|
'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' => $activity->getAvrTemperature()];
|
||||||
|
}
|
||||||
|
|
||||||
|
$jsonSerializer = new JsonSerializer();
|
||||||
|
$jsonData = $jsonSerializer::serialize($listActivity);
|
||||||
|
|
||||||
|
$response = new Response();
|
||||||
|
$response->setContent($jsonData);
|
||||||
|
$response->setHeader('Content-Type', 'application/json');
|
||||||
|
// pour delete renvoyer 204 pour dire ok et supprimer
|
||||||
|
// update 200
|
||||||
|
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// #[Route(path: '/api/activities', name: 'api-activities-post', methods: ['POST'])]
|
||||||
|
// public function apiAddActivity(IRequest $request)
|
||||||
|
// {
|
||||||
|
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
|
||||||
|
// $listSearch = $activityGateway->getActivity();
|
||||||
|
// $map = new ActivityMapper();
|
||||||
|
// $activityGateway = $map->activitySqlToEntity($listSearch);
|
||||||
|
// $listActivity = [];
|
||||||
|
// foreach ($activityGateway as $entity) {
|
||||||
|
// $activity = $map->activityEntityToModel($entity);
|
||||||
|
// $listActivity[] = ['idactivity' => number_format($activity->getIdActivity()), 'type' => $activity->getType(),
|
||||||
|
// 'date' => $activity->getDate()->format("Y-m-d"), 'heureDebut' => $activity->getHeureDebut()->format("Y-m-d"), 'heureFin' => $activity->getHeureFin()->format("Y-m-d"),
|
||||||
|
// 'effortRessenti' => $activity->getEffortRessenti(), 'variabilite' => $activity->getVariability(), 'variance' => $activity->getVariance(),
|
||||||
|
// 'ecartType' => $activity->getStandardDeviation(), 'moyenne' => $activity->getAverage(),
|
||||||
|
// 'max' => $activity->getMaximum(), 'min' => $activity->getMinimum(), 'temperature' => $activity->getAvrTemperature()];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// $jsonSerializer = new JsonSerializer();
|
||||||
|
// $jsonData = $jsonSerializer::serialize($listActivity);
|
||||||
|
//
|
||||||
|
// $response = new Response();
|
||||||
|
// $response->setContent($jsonData);
|
||||||
|
// $response->setHeader('Content-Type', 'application/json');
|
||||||
|
//
|
||||||
|
// return $response;
|
||||||
|
// }
|
||||||
|
// #[Route(path: '/api/activities/{id}', name: 'api-activities-post', methods: ['DELETE'])]
|
||||||
|
// public function apiDeleteActivity(IRequest $request, int $id)
|
||||||
|
// {
|
||||||
|
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
|
||||||
|
// $listSearch = $activityGateway->removeActivityById($id);
|
||||||
|
//
|
||||||
|
// $response = new Response();
|
||||||
|
// $response->setContent($jsonData);
|
||||||
|
// $response->setHeader('Content-Type', 'application/json');
|
||||||
|
//
|
||||||
|
// return $response;
|
||||||
|
// }
|
||||||
|
// #[Route(path: '/api/activities/{id}', name: 'api-activities-post', methods: ['PUT'])]
|
||||||
|
// public function apiUpdateActivity(IRequest $request, int $id)
|
||||||
|
// {
|
||||||
|
// $activityGateway = new ActivityGateway(new Connexion(DSN, DB_USER, DB_PASSWORD));
|
||||||
|
// $listSearch = $activityGateway->updateActivity($id);
|
||||||
|
//
|
||||||
|
// $response = new Response();
|
||||||
|
// $response->setContent($jsonData);
|
||||||
|
// $response->setHeader('Content-Type', 'application/json');
|
||||||
|
//
|
||||||
|
// return $response;
|
||||||
|
// }
|
||||||
|
}
|
@ -1,127 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database;
|
|
||||||
|
|
||||||
class ActiviteEntity {
|
|
||||||
private $idActivite;
|
|
||||||
private $type;
|
|
||||||
private $date;
|
|
||||||
private $heureDebut;
|
|
||||||
private $heureFin;
|
|
||||||
private $effortRessenti;
|
|
||||||
private $variabilite;
|
|
||||||
private $variance;
|
|
||||||
private $ecartType;
|
|
||||||
private $moyenne;
|
|
||||||
private $maximum;
|
|
||||||
private $minimum;
|
|
||||||
private $temperatureMoyenne;
|
|
||||||
|
|
||||||
// Getters
|
|
||||||
public function getIdActivite() {
|
|
||||||
return $this->idActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getType() {
|
|
||||||
return $this->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDate() {
|
|
||||||
return $this->date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHeureDebut() {
|
|
||||||
return $this->heureDebut;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getHeureFin() {
|
|
||||||
return $this->heureFin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEffortRessenti() {
|
|
||||||
return $this->effortRessenti;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVariabilite() {
|
|
||||||
return $this->variabilite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVariance() {
|
|
||||||
return $this->variance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getEcartType() {
|
|
||||||
return $this->ecartType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMoyenne() {
|
|
||||||
return $this->moyenne;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMaximum() {
|
|
||||||
return $this->maximum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMinimum() {
|
|
||||||
return $this->minimum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTemperatureMoyenne() {
|
|
||||||
return $this->temperatureMoyenne;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setters
|
|
||||||
public function setIdActivite($idActivite) {
|
|
||||||
$this->idActivity = $idActivity;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setType($type) {
|
|
||||||
$this->type = $type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setDate($date) {
|
|
||||||
$this->date = $date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setHeureDebut($heureDebut) {
|
|
||||||
$this->heureDebut = $heureDebut;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setHeureFin($heureFin) {
|
|
||||||
$this->heureFin = $heureFin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setEffortRessenti($effortRessenti) {
|
|
||||||
$this->effortRessenti = $effortRessenti;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setVariabilite($variabilite) {
|
|
||||||
$this->variabilite = $variabilite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setVariance($variance) {
|
|
||||||
$this->variance = $variance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setEcartType($ecartType) {
|
|
||||||
$this->ecartType = $ecartType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setMoyenne($moyenne) {
|
|
||||||
$this->moyenne = $moyenne;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setMaximum($maximum) {
|
|
||||||
$this->maximum = $maximum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setMinimum($minimum) {
|
|
||||||
$this->minimum = $minimum;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTemperatureMoyenne($temperatureMoyenne) {
|
|
||||||
$this->temperatureMoyenne = $temperatureMoyenne;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,120 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database;
|
|
||||||
|
|
||||||
class ActiviteGateway {
|
|
||||||
private $connection;
|
|
||||||
|
|
||||||
public function __construct(Connection $connection) {
|
|
||||||
$this->connection = $connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActivite() {
|
|
||||||
$query = "SELECT * FROM Activite";
|
|
||||||
return $this->connection->executeWithErrorHandling($query);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActiviteById(int $activiteId) {
|
|
||||||
$query = "SELECT * FROM Activite WHERE idActivite = :id";
|
|
||||||
$params = [':id' => [$activiteId, PDO::PARAM_INT]];
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActiviteByType(string $type) {
|
|
||||||
$query = "SELECT * FROM Activite WHERE type = :type";
|
|
||||||
$params = [':type' => [$type, PDO::PARAM_STR]];
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActiviteByDate(string $date) {
|
|
||||||
$query = "SELECT * FROM Activite WHERE date = :date";
|
|
||||||
$params = [':date' => [$date, PDO::PARAM_STR]];
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActiviteByTimeRange(string $startTime, string $endTime) {
|
|
||||||
$query = "SELECT * FROM Activite WHERE heureDebut >= :startTime AND heureFin <= :endTime";
|
|
||||||
$params = [
|
|
||||||
':startTime' => [$startTime, PDO::PARAM_STR],
|
|
||||||
':endTime' => [$endTime, PDO::PARAM_STR]
|
|
||||||
];
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActiviteByEffort(int $effortRessenti) {
|
|
||||||
$query = "SELECT * FROM Activite WHERE effortRessenti = :effort";
|
|
||||||
$params = [':effort' => [$effortRessenti, PDO::PARAM_INT]];
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActiviteByVariability(int $variabilite) {
|
|
||||||
$query = "SELECT * FROM Activite WHERE variabilite = :variability";
|
|
||||||
$params = [':variability' => [$variabilite, PDO::PARAM_INT]];
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getActiviteByTemperature(int $temperatureMoyenne) {
|
|
||||||
$query = "SELECT * FROM Activite WHERE temperatureMoyenne = :temperature";
|
|
||||||
$params = [':temperature' => [$temperatureMoyenne, PDO::PARAM_INT]];
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addActivite(ActiviteEntity $activite) {
|
|
||||||
$query = "INSERT INTO Activite (type, date, heureDebut, heureDeFin, effortRessenti, variabilite, variance, ecartType, moyenne, maximum, minimum, temperatureMoyenne)
|
|
||||||
VALUES (:type, :date, :heureDebut, :heureDeFin, :effortRessenti, :variabilite, :variance, :ecartType, :moyenne, :maximum, :minimum, :temperatureMoyenne)";
|
|
||||||
|
|
||||||
$params = [
|
|
||||||
':type' => $activite->getType(),
|
|
||||||
':date' => $activite->getDate()->format('Y-m-d'), // Format date pour SQL
|
|
||||||
':heureDebut' => $activite->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
|
|
||||||
':heureDeFin' => $activite->getHeureFin()->format('H:i:s'), // Format heure pour SQL
|
|
||||||
':effortRessenti' => $activite->getEffortRessenti(),
|
|
||||||
':variabilite' => $activite->getVariabilite(),
|
|
||||||
':variance' => $activite->getVariance(),
|
|
||||||
':ecartType' => $activite->getEcartType(),
|
|
||||||
':moyenne' => $activite->getMoyenne(),
|
|
||||||
':maximum' => $activite->getMaximum(),
|
|
||||||
':minimum' => $activite->getMinimum(),
|
|
||||||
':temperatureMoyenne' => $activite->getTemperatureMoyenne(),
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updateActivite(ActiviteEntity $oldActivite, ActiviteEntity $newActivite) {
|
|
||||||
$query = "UPDATE Activite
|
|
||||||
SET type = :type, date = :date, heureDebut = :heureDebut, heureDeFin = :heureDeFin,
|
|
||||||
effortRessenti = :effortRessenti, variabilite = :variabilite, variance = :variance, ecartType = :ecartType, moyenne = :moyenne, maximum = :maximum, minimum = :minimum, temperatureMoyenne = :temperatureMoyenne
|
|
||||||
WHERE idActivite = :idActivite";
|
|
||||||
|
|
||||||
$params = [
|
|
||||||
':idActivite' => $oldActivite->getIdActivite(),
|
|
||||||
':type' => $newActivite->getType(),
|
|
||||||
':date' => $newActivite->getDate()->format('Y-m-d'), // Format date pour SQL
|
|
||||||
':heureDebut' => $newActivite->getHeureDebut()->format('H:i:s'), // Format heure pour SQL
|
|
||||||
':heureDeFin' => $newActivite->getHeureFin()->format('H:i:s'), // Format heure pour SQL
|
|
||||||
':effortRessenti' => $newActivite->getEffortRessenti(),
|
|
||||||
':variabilite' => $newActivite->getVariabilite(),
|
|
||||||
':variance' => $newActivite->getVariance(),
|
|
||||||
':ecartType' => $newActivite->getEcartType(),
|
|
||||||
':moyenne' => $newActivite->getMoyenne(),
|
|
||||||
':maximum' => $newActivite->getMaximum(),
|
|
||||||
':minimum' => $newActivite->getMinimum(),
|
|
||||||
':temperatureMoyenne' => $newActivite->getTemperatureMoyenne(),
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deleteActivite(int $idActivite) {
|
|
||||||
$query = "DELETE FROM Activite WHERE idActivite = :idActivite";
|
|
||||||
|
|
||||||
$params = [
|
|
||||||
':idActivite' => $idActivite,
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->connection->executeWithErrorHandling($query, $params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -1,51 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Database;
|
|
||||||
use Model\Activite;
|
|
||||||
|
|
||||||
class ActiviteMapper {
|
|
||||||
public function map(array $data):ActiviteEntity {
|
|
||||||
$activite = new ActiviteEntity();
|
|
||||||
$activite->setIdActivite($data['idActivite']);
|
|
||||||
$activite->setType($data['type']);
|
|
||||||
$activite->setDate($data['date']);
|
|
||||||
$activite->setHeureDebut($data['heureDebut']);
|
|
||||||
$activite->setHeureFin($data['heureFin']);
|
|
||||||
$activite->setEffortRessenti($data['effortRessenti']);
|
|
||||||
$activite->setVariabilite($data['variabilite']);
|
|
||||||
$activite->setVariance($data['variance']);
|
|
||||||
$activite->setEcartType($data['ecartType']);
|
|
||||||
$activite->setMoyenne($data['moyenne']);
|
|
||||||
$activite->setMaximum($data['maximum']);
|
|
||||||
$activite->setMinimum($data['minimum']);
|
|
||||||
$activite->setTemperatureMoyenne($data['temperatureMoyenne']);
|
|
||||||
|
|
||||||
return $activite;
|
|
||||||
}
|
|
||||||
|
|
||||||
//public function ActiviteEntityToModel(ActiviteEntity entity): Activite;
|
|
||||||
|
|
||||||
public function ActiviteEntityToModel(ActiviteEntity $activiteEntity):Activite{
|
|
||||||
|
|
||||||
$act = new Activite(
|
|
||||||
$activiteEntity->getIdActivite(),
|
|
||||||
$activiteEntity->getType(),
|
|
||||||
$activiteEntity->getDate(),
|
|
||||||
$activiteEntity->getHeureDebut(),
|
|
||||||
$activiteEntity->getHeureFin(),
|
|
||||||
$activiteEntity->getEffortRessenti(),
|
|
||||||
$activiteEntity->getVariabilite(),
|
|
||||||
$activiteEntity->getVariance(),
|
|
||||||
$activiteEntity->getEcartType(),
|
|
||||||
$activiteEntity->getMoyenne(),
|
|
||||||
$activiteEntity->getMaximum(),
|
|
||||||
$activiteEntity->getMinimum(),
|
|
||||||
$activiteEntity->getTemperatureMoyenne()
|
|
||||||
);
|
|
||||||
|
|
||||||
return $act;
|
|
||||||
}
|
|
||||||
//public function ActiviteToEntity(Activite model): ActiviteEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Json;
|
||||||
|
|
||||||
|
use Shared\Log;
|
||||||
|
|
||||||
|
class JsonSerializer
|
||||||
|
{
|
||||||
|
public static function serialize($data): string
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return json_encode($data);
|
||||||
|
} catch (\JsonException $e) {
|
||||||
|
// Gérer l'erreur ici, par exemple, journaliser l'exception
|
||||||
|
error_log('Erreur de sérialisation JSON : ' . $e->getMessage());
|
||||||
|
return ''; // Ou retournez une valeur par défaut, selon vos besoins
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,215 @@
|
|||||||
|
<?php
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
|
||||||
|
//use Database\{Connexion, AthleteGateway,AthleteEntity};
|
||||||
|
use Database\AthleteEntity;
|
||||||
|
use Database\AthleteGateway;
|
||||||
|
use Database\Connexion;
|
||||||
|
use Database\AthleteMapper;
|
||||||
|
use Database\CoachGateway;
|
||||||
|
use Database\CoachEntity;
|
||||||
|
use Database\CoachMapper;
|
||||||
|
|
||||||
|
class GatewayTest extends TestCase {
|
||||||
|
|
||||||
|
//Partie concernant les Athlètes
|
||||||
|
|
||||||
|
public function testGetAthlete() {
|
||||||
|
|
||||||
|
//$dsn = "pgsql:host=londres;port=8888;dbname=dbkemonteiro2;user=kemonteiro2;password=Mdp";
|
||||||
|
|
||||||
|
require "loginDatabase.php";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
|
||||||
|
$athleteGateway = new AthleteGateway($connexion);
|
||||||
|
$result = $athleteGateway->getAthlete();
|
||||||
|
//var_dump($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fonctionne mais en commentaire pour pas add et del a chaque fois
|
||||||
|
public function testAddAthlete(){
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
|
||||||
|
$athleteGateway = new AthleteGateway($connexion);
|
||||||
|
|
||||||
|
$dateSpecifique = "2023-11-26";
|
||||||
|
$timestamp = strtotime($dateSpecifique);
|
||||||
|
$dateSQL = date("Y-m-d", $timestamp);
|
||||||
|
|
||||||
|
$athleteEntity = new AthleteEntity();
|
||||||
|
$athleteEntity->setNom('John');
|
||||||
|
$athleteEntity->setPrenom('Doe');
|
||||||
|
$athleteEntity->setIdAthlete(1234);
|
||||||
|
$athleteEntity->setEmail('kevin.monteiro@gmail.fr');
|
||||||
|
$athleteEntity->setSexe('H');
|
||||||
|
$athleteEntity->setTaille(169);
|
||||||
|
$athleteEntity->setPoids(69);
|
||||||
|
$athleteEntity->setMotDePasse('motdepasse');
|
||||||
|
$athleteEntity->setDateNaissance($dateSQL);
|
||||||
|
|
||||||
|
$result2 = $athleteGateway->addAthlete($athleteEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testDeleteAthlete(){
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
$athleteGateway = new AthleteGateway($connexion);
|
||||||
|
$result = $athleteGateway->deleteAthlete( //idAthlete );
|
||||||
|
var_dump($result);
|
||||||
|
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public function testUpdateAthlete(){
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
$athleteGateway = new AthleteGateway($connexion);
|
||||||
|
|
||||||
|
$dateSpecifique = "2004-08-26";
|
||||||
|
$timestamp = strtotime($dateSpecifique);
|
||||||
|
$dateSQL = date("Y-m-d", $timestamp);
|
||||||
|
|
||||||
|
$athleteEntity = new AthleteEntity();
|
||||||
|
$athleteEntity->setNom('John');
|
||||||
|
$athleteEntity->setPrenom('Doe');
|
||||||
|
$athleteEntity->setIdAthlete(13);
|
||||||
|
$athleteEntity->setEmail('kevin.monteiro@gmail.fr');
|
||||||
|
$athleteEntity->setSexe('H');
|
||||||
|
$athleteEntity->setTaille(169);
|
||||||
|
$athleteEntity->setPoids(69);
|
||||||
|
$athleteEntity->setMotDePasse('motdepasse');
|
||||||
|
$athleteEntity->setDateNaissance($dateSQL);
|
||||||
|
$athleteEntity->setIsCoach(FALSE);
|
||||||
|
$athleteEntity->setCoachId(NULL);
|
||||||
|
|
||||||
|
$athleteEntity2 = new AthleteEntity();
|
||||||
|
$athleteEntity2->setNom('Monteiro');
|
||||||
|
$athleteEntity2->setPrenom('Kevin');
|
||||||
|
$athleteEntity2->setIdAthlete(13);
|
||||||
|
$athleteEntity2->setEmail('kevin.monteiro@gmail.fr');
|
||||||
|
$athleteEntity2->setSexe('H');
|
||||||
|
$athleteEntity2->setTaille(169);
|
||||||
|
$athleteEntity2->setPoids(69);
|
||||||
|
$athleteEntity2->setMotDePasse('motdepasse');
|
||||||
|
$athleteEntity2->setDateNaissance($dateSQL);
|
||||||
|
$athleteEntity2->setIsCoach(TRUE);
|
||||||
|
$athleteEntity2->setCoachId(1);
|
||||||
|
|
||||||
|
$result = $athleteGateway->updateAthlete($athleteEntity, $athleteEntity2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Partie concernant les Coachs
|
||||||
|
|
||||||
|
public function testGetCoach() {
|
||||||
|
|
||||||
|
//$dsn = "pgsql:host=londres;port=8888;dbname=dbkemonteiro2;user=kemonteiro2;password=Mdp";
|
||||||
|
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
|
||||||
|
$coachGateway = new CoachGateway($connexion);
|
||||||
|
$result = $coachGateway->getCoach();
|
||||||
|
var_dump($result);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
//Fonctionne PAS A PARTIR DE LA
|
||||||
|
public function testAddCoach(){
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
|
||||||
|
$coachGateway = new CoachGateway($connexion);
|
||||||
|
|
||||||
|
$dateSpecifique = "2023-11-26";
|
||||||
|
$timestamp = strtotime($dateSpecifique);
|
||||||
|
$dateSQL = date("Y-m-d", $timestamp);
|
||||||
|
|
||||||
|
$coachEntity = new CoachEntity();
|
||||||
|
$coachEntity->setNom('John');
|
||||||
|
$coachEntity->setPrenom('Doe');
|
||||||
|
$coachEntity->setIdCoach(1234);
|
||||||
|
$coachEntity->setEmail('kevin.monteiro@gmail.fr');
|
||||||
|
$coachEntity->setSexe('H');
|
||||||
|
$coachEntity->setTaille(169);
|
||||||
|
$coachEntity->setPoids(69);
|
||||||
|
$coachEntity->setMotDePasse('motdepasse');
|
||||||
|
$coachEntity->setDateNaissance($dateSQL);
|
||||||
|
|
||||||
|
$result2 = $coachGateway->addCoach($coachEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testDeleteAthlete(){
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
$athleteGateway = new AthleteGateway($connexion);
|
||||||
|
$result = $athleteGateway->deleteAthlete( //idAthlete );
|
||||||
|
var_dump($result);
|
||||||
|
|
||||||
|
}*/
|
||||||
|
/*
|
||||||
|
public function testUpdateAthlete(){
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
$athleteGateway = new AthleteGateway($connexion);
|
||||||
|
|
||||||
|
$dateSpecifique = "2004-08-26";
|
||||||
|
$timestamp = strtotime($dateSpecifique);
|
||||||
|
$dateSQL = date("Y-m-d", $timestamp);
|
||||||
|
|
||||||
|
$athleteEntity = new AthleteEntity();
|
||||||
|
$athleteEntity->setNom('John');
|
||||||
|
$athleteEntity->setPrenom('Doe');
|
||||||
|
$athleteEntity->setIdAthlete(13);
|
||||||
|
$athleteEntity->setEmail('kevin.monteiro@gmail.fr');
|
||||||
|
$athleteEntity->setSexe('H');
|
||||||
|
$athleteEntity->setTaille(169);
|
||||||
|
$athleteEntity->setPoids(69);
|
||||||
|
$athleteEntity->setMotDePasse('motdepasse');
|
||||||
|
$athleteEntity->setDateNaissance($dateSQL);
|
||||||
|
|
||||||
|
$athleteEntity2 = new AthleteEntity();
|
||||||
|
$athleteEntity2->setNom('Monteiro');
|
||||||
|
$athleteEntity2->setPrenom('Kevin');
|
||||||
|
$athleteEntity2->setIdAthlete(13);
|
||||||
|
$athleteEntity2->setEmail('kevin.monteiro@gmail.fr');
|
||||||
|
$athleteEntity2->setSexe('H');
|
||||||
|
$athleteEntity2->setTaille(169);
|
||||||
|
$athleteEntity2->setPoids(69);
|
||||||
|
$athleteEntity2->setMotDePasse('motdepasse');
|
||||||
|
$athleteEntity2->setDateNaissance($dateSQL);
|
||||||
|
|
||||||
|
$result = $athleteGateway->updateAthlete($athleteEntity, $athleteEntity2);
|
||||||
|
}*/
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
use Model\User;
|
||||||
|
use Database\AthleteEntity;
|
||||||
|
use Database\AthleteGateway;
|
||||||
|
use Database\Connexion;
|
||||||
|
use Database\AthleteMapper;
|
||||||
|
|
||||||
|
class MapperTest extends TestCase {
|
||||||
|
|
||||||
|
public function testMapperAthlete() {
|
||||||
|
|
||||||
|
//$dsn = "pgsql:host=londres;port=8888;dbname=dbkemonteiro2;user=kemonteiro2;password=Mdp";
|
||||||
|
|
||||||
|
$dsn = "mysql:host=londres;dbname=dbkemonteiro2;";
|
||||||
|
$username = "kemonteiro2";
|
||||||
|
$password = "#Phpmyadmin63";
|
||||||
|
|
||||||
|
$connexion = new Connexion($dsn,$username,$password);
|
||||||
|
|
||||||
|
|
||||||
|
$athleteGateway = new AthleteGateway($connexion);
|
||||||
|
$result = $athleteGateway->getAthlete();
|
||||||
|
|
||||||
|
$map = new AthleteMapper ();
|
||||||
|
//SQL To AthleteEntity
|
||||||
|
$athleteEntity = $map->athleteSqlToEntity($result);
|
||||||
|
|
||||||
|
|
||||||
|
foreach($athleteEntity as $ath){
|
||||||
|
|
||||||
|
$result = $ath->getNom();
|
||||||
|
var_dump($result);
|
||||||
|
//Pour chaque AthleteEntity : Athlete Entity To User avec Role Athlete(Model)
|
||||||
|
$user = $map->athleteEntityToModel($ath);
|
||||||
|
var_dump($user->getId());
|
||||||
|
//Pour chaque Athlete du Model -> Athlete Entity
|
||||||
|
$res = $map->athleteToEntity($user);
|
||||||
|
var_dump($res->getIdAthlete());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$dsn = "psql:host=localhost;dbname=sae_3;";
|
||||||
|
$username = "Perederii";
|
||||||
|
$password = "";
|
||||||
|
|
||||||
|
?>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$finder = PhpCsFixer\Finder::create()
|
||||||
|
->exclude('PhpParser/Parser')
|
||||||
|
->in(__DIR__ . '/lib')
|
||||||
|
->in(__DIR__ . '/test')
|
||||||
|
->in(__DIR__ . '/grammar')
|
||||||
|
;
|
||||||
|
|
||||||
|
$config = new PhpCsFixer\Config();
|
||||||
|
return $config->setRiskyAllowed(true)
|
||||||
|
->setRules([
|
||||||
|
'@PSR12' => true,
|
||||||
|
// We use PSR12 with consistent brace placement.
|
||||||
|
'curly_braces_position' => [
|
||||||
|
'functions_opening_brace' => 'same_line',
|
||||||
|
'classes_opening_brace' => 'same_line',
|
||||||
|
],
|
||||||
|
// declare(strict_types=1) on the same line as <?php.
|
||||||
|
'blank_line_after_opening_tag' => false,
|
||||||
|
'declare_strict_types' => true,
|
||||||
|
// Keep argument formatting for now.
|
||||||
|
'method_argument_space' => ['on_multiline' => 'ignore'],
|
||||||
|
'phpdoc_align' => ['align' => 'left'],
|
||||||
|
'phpdoc_trim' => true,
|
||||||
|
'no_empty_phpdoc' => true,
|
||||||
|
'no_superfluous_phpdoc_tags' => ['allow_mixed' => true],
|
||||||
|
'no_extra_blank_lines' => true,
|
||||||
|
])
|
||||||
|
->setFinder($finder)
|
||||||
|
;
|
@ -0,0 +1,10 @@
|
|||||||
|
.PHONY: phpstan php-cs-fixer
|
||||||
|
|
||||||
|
tools/vendor:
|
||||||
|
composer install -d tools
|
||||||
|
|
||||||
|
phpstan: tools/vendor
|
||||||
|
tools/vendor/bin/phpstan
|
||||||
|
|
||||||
|
php-cs-fixer: tools/vendor
|
||||||
|
tools/vendor/bin/php-cs-fixer fix
|
@ -1,30 +0,0 @@
|
|||||||
What do all those files mean?
|
|
||||||
=============================
|
|
||||||
|
|
||||||
* `php5.y`: PHP 5 grammar written in a pseudo language
|
|
||||||
* `php7.y`: PHP 7 grammar written in a pseudo language
|
|
||||||
* `tokens.y`: Tokens definition shared between PHP 5 and PHP 7 grammars
|
|
||||||
* `parser.template`: A `kmyacc` parser prototype file for PHP
|
|
||||||
* `tokens.template`: A `kmyacc` prototype file for the `Tokens` class
|
|
||||||
* `rebuildParsers.php`: Preprocesses the grammar and builds the parser using `kmyacc`
|
|
||||||
|
|
||||||
.phpy pseudo language
|
|
||||||
=====================
|
|
||||||
|
|
||||||
The `.y` file is a normal grammar in `kmyacc` (`yacc`) style, with some transformations
|
|
||||||
applied to it:
|
|
||||||
|
|
||||||
* Nodes are created using the syntax `Name[..., ...]`. This is transformed into
|
|
||||||
`new Name(..., ..., attributes())`
|
|
||||||
* Some function-like constructs are resolved (see `rebuildParsers.php` for a list)
|
|
||||||
|
|
||||||
Building the parser
|
|
||||||
===================
|
|
||||||
|
|
||||||
Run `php grammar/rebuildParsers.php` to rebuild the parsers. Additional options:
|
|
||||||
|
|
||||||
* The `KMYACC` environment variable can be used to specify an alternative `kmyacc` binary.
|
|
||||||
By default the `phpyacc` dev dependency will be used. To use the original `kmyacc`, you
|
|
||||||
need to compile [moriyoshi's fork](https://github.com/moriyoshi/kmyacc-forked).
|
|
||||||
* The `--debug` option enables emission of debug symbols and creates the `y.output` file.
|
|
||||||
* The `--keep-tmp-grammar` option preserves the preprocessed grammar file.
|
|
@ -1,106 +0,0 @@
|
|||||||
<?php
|
|
||||||
$meta #
|
|
||||||
#semval($) $this->semValue
|
|
||||||
#semval($,%t) $this->semValue
|
|
||||||
#semval(%n) $stackPos-(%l-%n)
|
|
||||||
#semval(%n,%t) $stackPos-(%l-%n)
|
|
||||||
|
|
||||||
namespace PhpParser\Parser;
|
|
||||||
|
|
||||||
use PhpParser\Error;
|
|
||||||
use PhpParser\Node;
|
|
||||||
use PhpParser\Node\Expr;
|
|
||||||
use PhpParser\Node\Name;
|
|
||||||
use PhpParser\Node\Scalar;
|
|
||||||
use PhpParser\Node\Stmt;
|
|
||||||
#include;
|
|
||||||
|
|
||||||
/* This is an automatically GENERATED file, which should not be manually edited.
|
|
||||||
* Instead edit one of the following:
|
|
||||||
* * the grammar files grammar/php5.y or grammar/php7.y
|
|
||||||
* * the skeleton file grammar/parser.template
|
|
||||||
* * the preprocessing script grammar/rebuildParsers.php
|
|
||||||
*/
|
|
||||||
class #(-p) extends \PhpParser\ParserAbstract
|
|
||||||
{
|
|
||||||
protected $tokenToSymbolMapSize = #(YYMAXLEX);
|
|
||||||
protected $actionTableSize = #(YYLAST);
|
|
||||||
protected $gotoTableSize = #(YYGLAST);
|
|
||||||
|
|
||||||
protected $invalidSymbol = #(YYBADCH);
|
|
||||||
protected $errorSymbol = #(YYINTERRTOK);
|
|
||||||
protected $defaultAction = #(YYDEFAULT);
|
|
||||||
protected $unexpectedTokenRule = #(YYUNEXPECTED);
|
|
||||||
|
|
||||||
protected $YY2TBLSTATE = #(YY2TBLSTATE);
|
|
||||||
protected $numNonLeafStates = #(YYNLSTATES);
|
|
||||||
|
|
||||||
protected $symbolToName = array(
|
|
||||||
#listvar terminals
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $tokenToSymbol = array(
|
|
||||||
#listvar yytranslate
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $action = array(
|
|
||||||
#listvar yyaction
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $actionCheck = array(
|
|
||||||
#listvar yycheck
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $actionBase = array(
|
|
||||||
#listvar yybase
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $actionDefault = array(
|
|
||||||
#listvar yydefault
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $goto = array(
|
|
||||||
#listvar yygoto
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $gotoCheck = array(
|
|
||||||
#listvar yygcheck
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $gotoBase = array(
|
|
||||||
#listvar yygbase
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $gotoDefault = array(
|
|
||||||
#listvar yygdefault
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $ruleToNonTerminal = array(
|
|
||||||
#listvar yylhs
|
|
||||||
);
|
|
||||||
|
|
||||||
protected $ruleToLength = array(
|
|
||||||
#listvar yylen
|
|
||||||
);
|
|
||||||
#if -t
|
|
||||||
|
|
||||||
protected $productions = array(
|
|
||||||
#production-strings;
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
protected function initReduceCallbacks() {
|
|
||||||
$this->reduceCallbacks = [
|
|
||||||
#reduce
|
|
||||||
%n => function ($stackPos) {
|
|
||||||
%b
|
|
||||||
},
|
|
||||||
#noact
|
|
||||||
%n => function ($stackPos) {
|
|
||||||
$this->semValue = $this->semStack[$stackPos];
|
|
||||||
},
|
|
||||||
#endreduce
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#tailcode;
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,184 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
///////////////////////////////
|
|
||||||
/// Utility regex constants ///
|
|
||||||
///////////////////////////////
|
|
||||||
|
|
||||||
const LIB = '(?(DEFINE)
|
|
||||||
(?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\')
|
|
||||||
(?<doubleQuotedString>"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+")
|
|
||||||
(?<string>(?&singleQuotedString)|(?&doubleQuotedString))
|
|
||||||
(?<comment>/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/)
|
|
||||||
(?<code>\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+})
|
|
||||||
)';
|
|
||||||
|
|
||||||
const PARAMS = '\[(?<params>[^[\]]*+(?:\[(?¶ms)\][^[\]]*+)*+)\]';
|
|
||||||
const ARGS = '\((?<args>[^()]*+(?:\((?&args)\)[^()]*+)*+)\)';
|
|
||||||
|
|
||||||
///////////////////////////////
|
|
||||||
/// Preprocessing functions ///
|
|
||||||
///////////////////////////////
|
|
||||||
|
|
||||||
function preprocessGrammar($code) {
|
|
||||||
$code = resolveNodes($code);
|
|
||||||
$code = resolveMacros($code);
|
|
||||||
$code = resolveStackAccess($code);
|
|
||||||
|
|
||||||
return $code;
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveNodes($code) {
|
|
||||||
return preg_replace_callback(
|
|
||||||
'~\b(?<name>[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~',
|
|
||||||
function($matches) {
|
|
||||||
// recurse
|
|
||||||
$matches['params'] = resolveNodes($matches['params']);
|
|
||||||
|
|
||||||
$params = magicSplit(
|
|
||||||
'(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
|
|
||||||
$matches['params']
|
|
||||||
);
|
|
||||||
|
|
||||||
$paramCode = '';
|
|
||||||
foreach ($params as $param) {
|
|
||||||
$paramCode .= $param . ', ';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())';
|
|
||||||
},
|
|
||||||
$code
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveMacros($code) {
|
|
||||||
return preg_replace_callback(
|
|
||||||
'~\b(?<!::|->)(?!array\()(?<name>[a-z][A-Za-z]++)' . ARGS . '~',
|
|
||||||
function($matches) {
|
|
||||||
// recurse
|
|
||||||
$matches['args'] = resolveMacros($matches['args']);
|
|
||||||
|
|
||||||
$name = $matches['name'];
|
|
||||||
$args = magicSplit(
|
|
||||||
'(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,',
|
|
||||||
$matches['args']
|
|
||||||
);
|
|
||||||
|
|
||||||
if ('attributes' === $name) {
|
|
||||||
assertArgs(0, $args, $name);
|
|
||||||
return '$this->startAttributeStack[#1] + $this->endAttributes';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('stackAttributes' === $name) {
|
|
||||||
assertArgs(1, $args, $name);
|
|
||||||
return '$this->startAttributeStack[' . $args[0] . ']'
|
|
||||||
. ' + $this->endAttributeStack[' . $args[0] . ']';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('init' === $name) {
|
|
||||||
return '$$ = array(' . implode(', ', $args) . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('push' === $name) {
|
|
||||||
assertArgs(2, $args, $name);
|
|
||||||
|
|
||||||
return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('pushNormalizing' === $name) {
|
|
||||||
assertArgs(2, $args, $name);
|
|
||||||
|
|
||||||
return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }'
|
|
||||||
. ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('toArray' == $name) {
|
|
||||||
assertArgs(1, $args, $name);
|
|
||||||
|
|
||||||
return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('parseVar' === $name) {
|
|
||||||
assertArgs(1, $args, $name);
|
|
||||||
|
|
||||||
return 'substr(' . $args[0] . ', 1)';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('parseEncapsed' === $name) {
|
|
||||||
assertArgs(3, $args, $name);
|
|
||||||
|
|
||||||
return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {'
|
|
||||||
. ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('makeNop' === $name) {
|
|
||||||
assertArgs(3, $args, $name);
|
|
||||||
|
|
||||||
return '$startAttributes = ' . $args[1] . ';'
|
|
||||||
. ' if (isset($startAttributes[\'comments\']))'
|
|
||||||
. ' { ' . $args[0] . ' = new Stmt\Nop($startAttributes + ' . $args[2] . '); }'
|
|
||||||
. ' else { ' . $args[0] . ' = null; }';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('makeZeroLengthNop' == $name) {
|
|
||||||
assertArgs(2, $args, $name);
|
|
||||||
|
|
||||||
return '$startAttributes = ' . $args[1] . ';'
|
|
||||||
. ' if (isset($startAttributes[\'comments\']))'
|
|
||||||
. ' { ' . $args[0] . ' = new Stmt\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); }'
|
|
||||||
. ' else { ' . $args[0] . ' = null; }';
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('prependLeadingComments' === $name) {
|
|
||||||
assertArgs(1, $args, $name);
|
|
||||||
|
|
||||||
return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; '
|
|
||||||
. 'if (!empty($attrs[\'comments\'])) {'
|
|
||||||
. '$stmts[0]->setAttribute(\'comments\', '
|
|
||||||
. 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $matches[0];
|
|
||||||
},
|
|
||||||
$code
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertArgs($num, $args, $name) {
|
|
||||||
if ($num != count($args)) {
|
|
||||||
die('Wrong argument count for ' . $name . '().');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveStackAccess($code) {
|
|
||||||
$code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code);
|
|
||||||
$code = preg_replace('/#(\d+)/', '$$1', $code);
|
|
||||||
return $code;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeTrailingWhitespace($code) {
|
|
||||||
$lines = explode("\n", $code);
|
|
||||||
$lines = array_map('rtrim', $lines);
|
|
||||||
return implode("\n", $lines);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
/// Regex helper functions ///
|
|
||||||
//////////////////////////////
|
|
||||||
|
|
||||||
function regex($regex) {
|
|
||||||
return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~';
|
|
||||||
}
|
|
||||||
|
|
||||||
function magicSplit($regex, $string) {
|
|
||||||
$pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string);
|
|
||||||
|
|
||||||
foreach ($pieces as &$piece) {
|
|
||||||
$piece = trim($piece);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($pieces === ['']) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $pieces;
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require __DIR__ . '/phpyLang.php';
|
|
||||||
|
|
||||||
$grammarFileToName = [
|
|
||||||
__DIR__ . '/php5.y' => 'Php5',
|
|
||||||
__DIR__ . '/php7.y' => 'Php7',
|
|
||||||
];
|
|
||||||
|
|
||||||
$tokensFile = __DIR__ . '/tokens.y';
|
|
||||||
$tokensTemplate = __DIR__ . '/tokens.template';
|
|
||||||
$skeletonFile = __DIR__ . '/parser.template';
|
|
||||||
$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy';
|
|
||||||
$tmpResultFile = __DIR__ . '/tmp_parser.php';
|
|
||||||
$resultDir = __DIR__ . '/../lib/PhpParser/Parser';
|
|
||||||
$tokensResultsFile = $resultDir . '/Tokens.php';
|
|
||||||
|
|
||||||
$kmyacc = getenv('KMYACC');
|
|
||||||
if (!$kmyacc) {
|
|
||||||
// Use phpyacc from dev dependencies by default.
|
|
||||||
$kmyacc = __DIR__ . '/../vendor/bin/phpyacc';
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = array_flip($argv);
|
|
||||||
$optionDebug = isset($options['--debug']);
|
|
||||||
$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']);
|
|
||||||
|
|
||||||
///////////////////
|
|
||||||
/// Main script ///
|
|
||||||
///////////////////
|
|
||||||
|
|
||||||
$tokens = file_get_contents($tokensFile);
|
|
||||||
|
|
||||||
foreach ($grammarFileToName as $grammarFile => $name) {
|
|
||||||
echo "Building temporary $name grammar file.\n";
|
|
||||||
|
|
||||||
$grammarCode = file_get_contents($grammarFile);
|
|
||||||
$grammarCode = str_replace('%tokens', $tokens, $grammarCode);
|
|
||||||
$grammarCode = preprocessGrammar($grammarCode);
|
|
||||||
|
|
||||||
file_put_contents($tmpGrammarFile, $grammarCode);
|
|
||||||
|
|
||||||
$additionalArgs = $optionDebug ? '-t -v' : '';
|
|
||||||
|
|
||||||
echo "Building $name parser.\n";
|
|
||||||
$output = execCmd("$kmyacc $additionalArgs -m $skeletonFile -p $name $tmpGrammarFile");
|
|
||||||
|
|
||||||
$resultCode = file_get_contents($tmpResultFile);
|
|
||||||
$resultCode = removeTrailingWhitespace($resultCode);
|
|
||||||
|
|
||||||
ensureDirExists($resultDir);
|
|
||||||
file_put_contents("$resultDir/$name.php", $resultCode);
|
|
||||||
unlink($tmpResultFile);
|
|
||||||
|
|
||||||
echo "Building token definition.\n";
|
|
||||||
$output = execCmd("$kmyacc -m $tokensTemplate $tmpGrammarFile");
|
|
||||||
rename($tmpResultFile, $tokensResultsFile);
|
|
||||||
|
|
||||||
if (!$optionKeepTmpGrammar) {
|
|
||||||
unlink($tmpGrammarFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
/// Utility helper functions ///
|
|
||||||
////////////////////////////////
|
|
||||||
|
|
||||||
function ensureDirExists($dir) {
|
|
||||||
if (!is_dir($dir)) {
|
|
||||||
mkdir($dir, 0777, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function execCmd($cmd) {
|
|
||||||
$output = trim(shell_exec("$cmd 2>&1"));
|
|
||||||
if ($output !== "") {
|
|
||||||
echo "> " . $cmd . "\n";
|
|
||||||
echo $output;
|
|
||||||
}
|
|
||||||
return $output;
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
$meta #
|
|
||||||
#semval($) $this->semValue
|
|
||||||
#semval($,%t) $this->semValue
|
|
||||||
#semval(%n) $this->stackPos-(%l-%n)
|
|
||||||
#semval(%n,%t) $this->stackPos-(%l-%n)
|
|
||||||
|
|
||||||
namespace PhpParser\Parser;
|
|
||||||
#include;
|
|
||||||
|
|
||||||
/* GENERATED file based on grammar/tokens.y */
|
|
||||||
final class Tokens
|
|
||||||
{
|
|
||||||
#tokenval
|
|
||||||
const %s = %n;
|
|
||||||
#endtokenval
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
/* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for
|
|
||||||
* both. This is enforced by sharing this token file. */
|
|
||||||
|
|
||||||
%right T_THROW
|
|
||||||
%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE
|
|
||||||
%left ','
|
|
||||||
%left T_LOGICAL_OR
|
|
||||||
%left T_LOGICAL_XOR
|
|
||||||
%left T_LOGICAL_AND
|
|
||||||
%right T_PRINT
|
|
||||||
%right T_YIELD
|
|
||||||
%right T_DOUBLE_ARROW
|
|
||||||
%right T_YIELD_FROM
|
|
||||||
%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL T_COALESCE_EQUAL
|
|
||||||
%left '?' ':'
|
|
||||||
%right T_COALESCE
|
|
||||||
%left T_BOOLEAN_OR
|
|
||||||
%left T_BOOLEAN_AND
|
|
||||||
%left '|'
|
|
||||||
%left '^'
|
|
||||||
%left T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG
|
|
||||||
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP
|
|
||||||
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
|
|
||||||
%left T_SL T_SR
|
|
||||||
%left '+' '-' '.'
|
|
||||||
%left '*' '/' '%'
|
|
||||||
%right '!'
|
|
||||||
%nonassoc T_INSTANCEOF
|
|
||||||
%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
|
|
||||||
%right T_POW
|
|
||||||
%right '['
|
|
||||||
%nonassoc T_NEW T_CLONE
|
|
||||||
%token T_EXIT
|
|
||||||
%token T_IF
|
|
||||||
%left T_ELSEIF
|
|
||||||
%left T_ELSE
|
|
||||||
%left T_ENDIF
|
|
||||||
%token T_LNUMBER
|
|
||||||
%token T_DNUMBER
|
|
||||||
%token T_STRING
|
|
||||||
%token T_STRING_VARNAME
|
|
||||||
%token T_VARIABLE
|
|
||||||
%token T_NUM_STRING
|
|
||||||
%token T_INLINE_HTML
|
|
||||||
%token T_ENCAPSED_AND_WHITESPACE
|
|
||||||
%token T_CONSTANT_ENCAPSED_STRING
|
|
||||||
%token T_ECHO
|
|
||||||
%token T_DO
|
|
||||||
%token T_WHILE
|
|
||||||
%token T_ENDWHILE
|
|
||||||
%token T_FOR
|
|
||||||
%token T_ENDFOR
|
|
||||||
%token T_FOREACH
|
|
||||||
%token T_ENDFOREACH
|
|
||||||
%token T_DECLARE
|
|
||||||
%token T_ENDDECLARE
|
|
||||||
%token T_AS
|
|
||||||
%token T_SWITCH
|
|
||||||
%token T_MATCH
|
|
||||||
%token T_ENDSWITCH
|
|
||||||
%token T_CASE
|
|
||||||
%token T_DEFAULT
|
|
||||||
%token T_BREAK
|
|
||||||
%token T_CONTINUE
|
|
||||||
%token T_GOTO
|
|
||||||
%token T_FUNCTION
|
|
||||||
%token T_FN
|
|
||||||
%token T_CONST
|
|
||||||
%token T_RETURN
|
|
||||||
%token T_TRY
|
|
||||||
%token T_CATCH
|
|
||||||
%token T_FINALLY
|
|
||||||
%token T_THROW
|
|
||||||
%token T_USE
|
|
||||||
%token T_INSTEADOF
|
|
||||||
%token T_GLOBAL
|
|
||||||
%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC T_READONLY
|
|
||||||
%token T_VAR
|
|
||||||
%token T_UNSET
|
|
||||||
%token T_ISSET
|
|
||||||
%token T_EMPTY
|
|
||||||
%token T_HALT_COMPILER
|
|
||||||
%token T_CLASS
|
|
||||||
%token T_TRAIT
|
|
||||||
%token T_INTERFACE
|
|
||||||
%token T_ENUM
|
|
||||||
%token T_EXTENDS
|
|
||||||
%token T_IMPLEMENTS
|
|
||||||
%token T_OBJECT_OPERATOR
|
|
||||||
%token T_NULLSAFE_OBJECT_OPERATOR
|
|
||||||
%token T_DOUBLE_ARROW
|
|
||||||
%token T_LIST
|
|
||||||
%token T_ARRAY
|
|
||||||
%token T_CALLABLE
|
|
||||||
%token T_CLASS_C
|
|
||||||
%token T_TRAIT_C
|
|
||||||
%token T_METHOD_C
|
|
||||||
%token T_FUNC_C
|
|
||||||
%token T_LINE
|
|
||||||
%token T_FILE
|
|
||||||
%token T_START_HEREDOC
|
|
||||||
%token T_END_HEREDOC
|
|
||||||
%token T_DOLLAR_OPEN_CURLY_BRACES
|
|
||||||
%token T_CURLY_OPEN
|
|
||||||
%token T_PAAMAYIM_NEKUDOTAYIM
|
|
||||||
%token T_NAMESPACE
|
|
||||||
%token T_NS_C
|
|
||||||
%token T_DIR
|
|
||||||
%token T_NS_SEPARATOR
|
|
||||||
%token T_ELLIPSIS
|
|
||||||
%token T_NAME_FULLY_QUALIFIED
|
|
||||||
%token T_NAME_QUALIFIED
|
|
||||||
%token T_NAME_RELATIVE
|
|
||||||
%token T_ATTRIBUTE
|
|
||||||
%token T_ENUM
|
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace PhpParser;
|
namespace PhpParser;
|
||||||
|
|
||||||
class ConstExprEvaluationException extends \Exception
|
class ConstExprEvaluationException extends \Exception {
|
||||||
{}
|
}
|
||||||
|
@ -0,0 +1,237 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace PhpParser\Internal;
|
||||||
|
|
||||||
|
if (\PHP_VERSION_ID >= 80000) {
|
||||||
|
class TokenPolyfill extends \PhpToken {
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a polyfill for the PhpToken class introduced in PHP 8.0. We do not actually polyfill
|
||||||
|
* PhpToken, because composer might end up picking a different polyfill implementation, which does
|
||||||
|
* not meet our requirements.
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class TokenPolyfill {
|
||||||
|
/** @var int The ID of the token. Either a T_* constant of a character code < 256. */
|
||||||
|
public int $id;
|
||||||
|
/** @var string The textual content of the token. */
|
||||||
|
public string $text;
|
||||||
|
/** @var int The 1-based starting line of the token (or -1 if unknown). */
|
||||||
|
public int $line;
|
||||||
|
/** @var int The 0-based starting position of the token (or -1 if unknown). */
|
||||||
|
public int $pos;
|
||||||
|
|
||||||
|
/** @var array<int, bool> Tokens ignored by the PHP parser. */
|
||||||
|
private const IGNORABLE_TOKENS = [
|
||||||
|
\T_WHITESPACE => true,
|
||||||
|
\T_COMMENT => true,
|
||||||
|
\T_DOC_COMMENT => true,
|
||||||
|
\T_OPEN_TAG => true,
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var array<int, bool> Tokens that may be part of a T_NAME_* identifier. */
|
||||||
|
private static array $identifierTokens;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Token with the given ID and text, as well optional line and position information.
|
||||||
|
*/
|
||||||
|
final public function __construct(int $id, string $text, int $line = -1, int $pos = -1) {
|
||||||
|
$this->id = $id;
|
||||||
|
$this->text = $text;
|
||||||
|
$this->line = $line;
|
||||||
|
$this->pos = $pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the token. For single-char tokens this will be the token character.
|
||||||
|
* Otherwise it will be a T_* style name, or null if the token ID is unknown.
|
||||||
|
*/
|
||||||
|
public function getTokenName(): ?string {
|
||||||
|
if ($this->id < 256) {
|
||||||
|
return \chr($this->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = token_name($this->id);
|
||||||
|
return $name === 'UNKNOWN' ? null : $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the token is of the given kind. The kind may be either an integer that matches
|
||||||
|
* the token ID, a string that matches the token text, or an array of integers/strings. In the
|
||||||
|
* latter case, the function returns true if any of the kinds in the array match.
|
||||||
|
*
|
||||||
|
* @param int|string|(int|string)[] $kind
|
||||||
|
*/
|
||||||
|
public function is($kind): bool {
|
||||||
|
if (\is_int($kind)) {
|
||||||
|
return $this->id === $kind;
|
||||||
|
}
|
||||||
|
if (\is_string($kind)) {
|
||||||
|
return $this->text === $kind;
|
||||||
|
}
|
||||||
|
if (\is_array($kind)) {
|
||||||
|
foreach ($kind as $entry) {
|
||||||
|
if (\is_int($entry)) {
|
||||||
|
if ($this->id === $entry) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} elseif (\is_string($entry)) {
|
||||||
|
if ($this->text === $entry) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new \TypeError(
|
||||||
|
'Argument #1 ($kind) must only have elements of type string|int, ' .
|
||||||
|
gettype($entry) . ' given');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw new \TypeError(
|
||||||
|
'Argument #1 ($kind) must be of type string|int|array, ' .gettype($kind) . ' given');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether this token would be ignored by the PHP parser. Returns true for T_WHITESPACE,
|
||||||
|
* T_COMMENT, T_DOC_COMMENT and T_OPEN_TAG, and false for everything else.
|
||||||
|
*/
|
||||||
|
public function isIgnorable(): bool {
|
||||||
|
return isset(self::IGNORABLE_TOKENS[$this->id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the textual content of the token.
|
||||||
|
*/
|
||||||
|
public function __toString(): string {
|
||||||
|
return $this->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenize the given source code and return an array of tokens.
|
||||||
|
*
|
||||||
|
* This performs certain canonicalizations to match the PHP 8.0 token format:
|
||||||
|
* * Bad characters are represented using T_BAD_CHARACTER rather than omitted.
|
||||||
|
* * T_COMMENT does not include trailing newlines, instead the newline is part of a following
|
||||||
|
* T_WHITESPACE token.
|
||||||
|
* * Namespaced names are represented using T_NAME_* tokens.
|
||||||
|
*
|
||||||
|
* @return static[]
|
||||||
|
*/
|
||||||
|
public static function tokenize(string $code, int $flags = 0): array {
|
||||||
|
self::init();
|
||||||
|
|
||||||
|
$tokens = [];
|
||||||
|
$line = 1;
|
||||||
|
$pos = 0;
|
||||||
|
$origTokens = \token_get_all($code, $flags);
|
||||||
|
|
||||||
|
$numTokens = \count($origTokens);
|
||||||
|
for ($i = 0; $i < $numTokens; $i++) {
|
||||||
|
$token = $origTokens[$i];
|
||||||
|
if (\is_string($token)) {
|
||||||
|
if (\strlen($token) === 2) {
|
||||||
|
// b" and B" are tokenized as single-char tokens, even though they aren't.
|
||||||
|
$tokens[] = new static(\ord('"'), $token, $line, $pos);
|
||||||
|
$pos += 2;
|
||||||
|
} else {
|
||||||
|
$tokens[] = new static(\ord($token), $token, $line, $pos);
|
||||||
|
$pos++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$id = $token[0];
|
||||||
|
$text = $token[1];
|
||||||
|
|
||||||
|
// Emulate PHP 8.0 comment format, which does not include trailing whitespace anymore.
|
||||||
|
if ($id === \T_COMMENT && \substr($text, 0, 2) !== '/*' &&
|
||||||
|
\preg_match('/(\r\n|\n|\r)$/D', $text, $matches)
|
||||||
|
) {
|
||||||
|
$trailingNewline = $matches[0];
|
||||||
|
$text = \substr($text, 0, -\strlen($trailingNewline));
|
||||||
|
$tokens[] = new static($id, $text, $line, $pos);
|
||||||
|
$pos += \strlen($text);
|
||||||
|
|
||||||
|
if ($i + 1 < $numTokens && $origTokens[$i + 1][0] === \T_WHITESPACE) {
|
||||||
|
// Move trailing newline into following T_WHITESPACE token, if it already exists.
|
||||||
|
$origTokens[$i + 1][1] = $trailingNewline . $origTokens[$i + 1][1];
|
||||||
|
$origTokens[$i + 1][2]--;
|
||||||
|
} else {
|
||||||
|
// Otherwise, we need to create a new T_WHITESPACE token.
|
||||||
|
$tokens[] = new static(\T_WHITESPACE, $trailingNewline, $line, $pos);
|
||||||
|
$line++;
|
||||||
|
$pos += \strlen($trailingNewline);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emulate PHP 8.0 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and
|
||||||
|
// T_STRING into a single token.
|
||||||
|
if (($id === \T_NS_SEPARATOR || isset(self::$identifierTokens[$id]))) {
|
||||||
|
$newText = $text;
|
||||||
|
$lastWasSeparator = $id === \T_NS_SEPARATOR;
|
||||||
|
for ($j = $i + 1; $j < $numTokens; $j++) {
|
||||||
|
if ($lastWasSeparator) {
|
||||||
|
if (!isset(self::$identifierTokens[$origTokens[$j][0]])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$lastWasSeparator = false;
|
||||||
|
} else {
|
||||||
|
if ($origTokens[$j][0] !== \T_NS_SEPARATOR) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$lastWasSeparator = true;
|
||||||
|
}
|
||||||
|
$newText .= $origTokens[$j][1];
|
||||||
|
}
|
||||||
|
if ($lastWasSeparator) {
|
||||||
|
// Trailing separator is not part of the name.
|
||||||
|
$j--;
|
||||||
|
$newText = \substr($newText, 0, -1);
|
||||||
|
}
|
||||||
|
if ($j > $i + 1) {
|
||||||
|
if ($id === \T_NS_SEPARATOR) {
|
||||||
|
$id = \T_NAME_FULLY_QUALIFIED;
|
||||||
|
} elseif ($id === \T_NAMESPACE) {
|
||||||
|
$id = \T_NAME_RELATIVE;
|
||||||
|
} else {
|
||||||
|
$id = \T_NAME_QUALIFIED;
|
||||||
|
}
|
||||||
|
$tokens[] = new static($id, $newText, $line, $pos);
|
||||||
|
$pos += \strlen($newText);
|
||||||
|
$i = $j - 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokens[] = new static($id, $text, $line, $pos);
|
||||||
|
$line += \substr_count($text, "\n");
|
||||||
|
$pos += \strlen($text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Initialize private static state needed by tokenize(). */
|
||||||
|
private static function init(): void {
|
||||||
|
if (isset(self::$identifierTokens)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on semi_reserved production.
|
||||||
|
self::$identifierTokens = \array_fill_keys([
|
||||||
|
\T_STRING,
|
||||||
|
\T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY,
|
||||||
|
\T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND,
|
||||||
|
\T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE,
|
||||||
|
\T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH,
|
||||||
|
\T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO,
|
||||||
|
\T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT,
|
||||||
|
\T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS,
|
||||||
|
\T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN,
|
||||||
|
\T_MATCH,
|
||||||
|
], true);
|
||||||
|
}
|
||||||
|
}
|
@ -1,47 +0,0 @@
|
|||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PhpParser\Lexer\TokenEmulator;
|
|
||||||
|
|
||||||
use PhpParser\Lexer\Emulative;
|
|
||||||
|
|
||||||
final class CoaleseEqualTokenEmulator extends TokenEmulator
|
|
||||||
{
|
|
||||||
public function getPhpVersion(): string
|
|
||||||
{
|
|
||||||
return Emulative::PHP_7_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isEmulationNeeded(string $code): bool
|
|
||||||
{
|
|
||||||
return strpos($code, '??=') !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function emulate(string $code, array $tokens): array
|
|
||||||
{
|
|
||||||
// We need to manually iterate and manage a count because we'll change
|
|
||||||
// the tokens array on the way
|
|
||||||
$line = 1;
|
|
||||||
for ($i = 0, $c = count($tokens); $i < $c; ++$i) {
|
|
||||||
if (isset($tokens[$i + 1])) {
|
|
||||||
if ($tokens[$i][0] === T_COALESCE && $tokens[$i + 1] === '=') {
|
|
||||||
array_splice($tokens, $i, 2, [
|
|
||||||
[\T_COALESCE_EQUAL, '??=', $line]
|
|
||||||
]);
|
|
||||||
$c--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (\is_array($tokens[$i])) {
|
|
||||||
$line += substr_count($tokens[$i][1], "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reverseEmulate(string $code, array $tokens): array
|
|
||||||
{
|
|
||||||
// ??= was not valid code previously, don't bother.
|
|
||||||
return $tokens;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace PhpParser\Lexer\TokenEmulator;
|
|
||||||
|
|
||||||
use PhpParser\Lexer\Emulative;
|
|
||||||
|
|
||||||
final class FlexibleDocStringEmulator extends TokenEmulator
|
|
||||||
{
|
|
||||||
const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX'
|
|
||||||
/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n
|
|
||||||
(?:.*\r?\n)*?
|
|
||||||
(?<indentation>\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
|
|
||||||
REGEX;
|
|
||||||
|
|
||||||
public function getPhpVersion(): string
|
|
||||||
{
|
|
||||||
return Emulative::PHP_7_3;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isEmulationNeeded(string $code) : bool
|
|
||||||
{
|
|
||||||
return strpos($code, '<<<') !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function emulate(string $code, array $tokens): array
|
|
||||||
{
|
|
||||||
// Handled by preprocessing + fixup.
|
|
||||||
return $tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function reverseEmulate(string $code, array $tokens): array
|
|
||||||
{
|
|
||||||
// Not supported.
|
|
||||||
return $tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function preprocessCode(string $code, array &$patches): string {
|
|
||||||
if (!preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE)) {
|
|
||||||
// No heredoc/nowdoc found
|
|
||||||
return $code;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep track of how much we need to adjust string offsets due to the modifications we
|
|
||||||
// already made
|
|
||||||
$posDelta = 0;
|
|
||||||
foreach ($matches as $match) {
|
|
||||||
$indentation = $match['indentation'][0];
|
|
||||||
$indentationStart = $match['indentation'][1];
|
|
||||||
|
|
||||||
$separator = $match['separator'][0];
|
|
||||||
$separatorStart = $match['separator'][1];
|
|
||||||
|
|
||||||
if ($indentation === '' && $separator !== '') {
|
|
||||||
// Ordinary heredoc/nowdoc
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($indentation !== '') {
|
|
||||||
// Remove indentation
|
|
||||||
$indentationLen = strlen($indentation);
|
|
||||||
$code = substr_replace($code, '', $indentationStart + $posDelta, $indentationLen);
|
|
||||||
$patches[] = [$indentationStart + $posDelta, 'add', $indentation];
|
|
||||||
$posDelta -= $indentationLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($separator === '') {
|
|
||||||
// Insert newline as separator
|
|
||||||
$code = substr_replace($code, "\n", $separatorStart + $posDelta, 0);
|
|
||||||
$patches[] = [$separatorStart + $posDelta, 'remove', "\n"];
|
|
||||||
$posDelta += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $code;
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue