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;
|
||||
|
||||
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