Skip to content
Snippets Groups Projects
Commit 79cfbf05 authored by Jean-Philippe Metivier's avatar Jean-Philippe Metivier
Browse files

init

parents
No related branches found
No related tags found
No related merge requests found
Pipeline #19682 passed
Showing
with 735 additions and 0 deletions
.idea
image: registre.unicaen.fr:5000/unicaen-dev-php7.3-apache
stages:
- publish
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- vendor/
update-satis:
stage: publish
script:
- curl https://gest.unicaen.fr/packagist/update
<?php
namespace UnicaenSynchro;
use Laminas\Mvc\ModuleRouteListener;
use Laminas\Mvc\MvcEvent;
use Laminas\Config\Factory as ConfigFactory;
use Laminas\Stdlib\ArrayUtils;
use Laminas\Stdlib\Glob;
class Module
{
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
public function getConfig()
{
$configInit = [
__DIR__ . '/config/module.config.php'
];
$configFiles = ArrayUtils::merge(
$configInit,
Glob::glob(__DIR__ . '/config/merged/{,*.}{config}.php', Glob::GLOB_BRACE)
);
return ConfigFactory::fromFiles($configFiles);
}
public function getAutoloaderConfig()
{
return array(
'Laminas\Loader\StandardAutoloader' => array(
'namespaces' => array(
__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,
),
),
);
}
}
{
"name": "unicaen/synchro",
"description": "Module de synchronisation",
"repositories": [
{
"type": "composer",
"url": "https://gest.unicaen.fr/packagist"
}
],
"require": {
"unicaen/privilege": "^5||^6"
},
"autoload": {
"psr-0": [],
"classmap": [
"./Module.php"
]
}
}
<?php
namespace UnicaenSynchro;
use UnicaenSynchro\Service\SqlHelper\SqlHelperService;
use UnicaenSynchro\Service\SqlHelper\SqlHelperServiceFactory;
return [
'bjyauthorize' => [
'guards' => [
],
],
'router' => [
'routes' => [
],
],
'service_manager' => [
'factories' => [
SqlHelperService::class => SqlHelperServiceFactory::class
],
],
'controllers' => [
'factories' => [],
],
'form_elements' => [
'factories' => [],
],
'hydrators' => [
'factories' => [],
]
];
\ No newline at end of file
<?php
namespace UnicaenSynchro;
use Laminas\Mvc\Console\Router\Simple;
use UnicaenSynchro\Controller\SynchronisationConsoleController;
use UnicaenSynchro\Controller\SynchronisationConsoleControllerFactory;
use UnicaenSynchro\Service\Synchronisation\SynchronisationService;
use UnicaenSynchro\Service\Synchronisation\SynchronisationServiceFactory;
use UnicaenPrivilege\Guard\PrivilegeController;
return [
'bjyauthorize' => [
'guards' => [
PrivilegeController::class => [
[
'controller' => SynchronisationConsoleController::class,
'action' => [
'synchroniser-all',
'synchroniser',
],
'roles' => [],
],
],
],
],
'console' => [
'router' => [
'routes' => [
'synchroniser-all' => [
'type' => Simple::class,
'options' => [
'route' => 'synchroniser-all',
'defaults' => [
/** @see SynchronisationConsoleController::synchroniserAllAction() */
'controller' => SynchronisationConsoleController::class,
'action' => 'synchroniser-all'
],
],
],
'synchroniser' => [
'type' => Simple::class,
'options' => [
'route' => 'synchroniser [--name=]',
'defaults' => [
/** @see SynchronisationConsoleController::synchroniserAction() */
'controller' => SynchronisationConsoleController::class,
'action' => 'synchroniser'
],
],
],
],
],
],
'router' => [
'routes' => [
],
],
'service_manager' => [
'factories' => [
SynchronisationService::class => SynchronisationServiceFactory::class,
],
],
'controllers' => [
'factories' => [
SynchronisationConsoleController::class => SynchronisationConsoleControllerFactory::class
],
],
'form_elements' => [
'factories' => [],
],
'hydrators' => [
'factories' => [],
]
];
\ No newline at end of file
<?php
namespace UnicaenSynchro;
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
use Doctrine\ORM\Mapping\Driver\XmlDriver;
use UnicaenPrivilege\Guard\PrivilegeController;
return [
'bjyauthorize' => [
'guards' => [
PrivilegeController::class => [
],
],
],
'doctrine' => [
'driver' => [
'orm_default' => [
'class' => MappingDriverChain::class,
'drivers' => [
'UnicaenSynchro\Entity\Db' => 'orm_default_xml_driver',
],
],
'orm_default_xml_driver' => [
'class' => XmlDriver::class,
'cache' => 'apc',
'paths' => [
__DIR__ . '/../src/UnicaenSynchro/Entity/Db/Mapping',
],
],
],
'cache' => [
'apc' => [
'namespace' => 'UnicaenSynchro__' . __NAMESPACE__,
],
],
],
'service_manager' => [
'factories' => [
],
],
'controllers' => [
'factories' => [
]
],
'form_elements' => [
'factories' => [
],
],
'hydrators' => [
'factories' => [
],
],
'view_helpers' => [
'invokables' => [
],
],
'view_manager' => [
'template_path_stack' => [
__DIR__ . '/../view',
],
],
];
Module Unicaen Synchronisation
=======================
------------------------
Description
-----------
Le module **unicaen/synchro** est en charge
Description du fonctionnement
============================
Tables pour les données du modules
==================================
Dépendances extérieurs
======================
<?php
namespace UnicaenSynchro\Controller;
use Laminas\Mvc\Console\Controller\AbstractConsoleController;
use Laminas\Mvc\Controller\AbstractActionController;
use UnicaenSynchro\Service\Synchronisation\SynchronisationServiceAwareTrait;
class SynchronisationConsoleController extends AbstractConsoleController {
use SynchronisationServiceAwareTrait;
private array $configs;
public function setConfigs(array $configs) : void
{
$this->configs = $configs;
}
public function synchroniserAllAction() : string
{
$jobs = $this->configs;
// usort($works, function ($a,$b) { return $a['order'] > $b['order'];});
foreach ($jobs as $name => $job) {
echo $this->getSynchronisationService()->synchronise($name);
}
return "done!\n";
}
public function synchroniserAction() : string
{
$request = $this->getRequest();
$name = $request->getParam('name');
echo $this->getSynchronisationService()->synchronise($name);
return "done!\n";
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Controller;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use UnicaenSynchro\Service\Synchronisation\SynchronisationService;
class SynchronisationConsoleControllerFactory {
/**
* @param ContainerInterface $container
* @return SynchronisationConsoleController
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function __invoke(ContainerInterface $container) : SynchronisationConsoleController
{
$synchronisationService = $container->get(SynchronisationService::class);
$configs = $container->get('Config')['synchros'];
$controller = new SynchronisationConsoleController();
$controller->setConfigs($configs);
$controller->setSynchronisationService($synchronisationService);
return $controller;
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Entity\Db;
use DateTime;
interface IsSynchronisableInterface {
public function getCreatedOn() : ?DateTime;
public function getUpdatedOn() : ?DateTime;
public function getDeletedOn() : ?DateTime;
public function isDeleted(?DateTime $date = null) : bool;
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Entity\Db;
use DateTime;
trait IsSynchronisableTrait {
private ?Datetime $createdOn;
private ?Datetime $updatedOn;
private ?Datetime $deletedOn;
public function getInsertedOn(): ?DateTime
{
return $this->createdOn;
}
public function setInsertedOn(?DateTime $createdOn): void
{
$this->createdOn = $createdOn;
}
public function getUpdatedOn(): ?DateTime
{
return $this->updatedOn;
}
public function setUpdatedOn(?DateTime $updatedOn): void
{
$this->updatedOn = $updatedOn;
}
public function getDeletedOn(): ?DateTime
{
return $this->deletedOn;
}
public function setDeletedOn(?DateTime $deletedOn): void
{
$this->deletedOn = $deletedOn;
}
public function isDeleted(?DateTime $date = null) : bool
{
if ($date === null) $date = new DateTime();
if ($this->deletedOn === null OR $this->deletedOn > $date) return false;
return true;
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Service\SqlHelper;
use Doctrine\DBAL\Driver\Exception as DRV_Exception;
use Doctrine\DBAL\Exception as DBA_Exception;
use Doctrine\ORM\EntityManager;
use DoctrineModule\Persistence\ProvidesObjectManager;
use RuntimeException;
class SqlHelperService {
use ProvidesObjectManager;
public function executeRequeteRef(EntityManager $entityManager, string $sql, array $params) : array
{
try {
$res = $entityManager->getConnection()->executeQuery($sql, $params);
try {
$tmp = $res->fetchAllAssociative();
} catch (DRV_Exception $e) {
throw new RuntimeException("Un problème est survenu [DRV_Exception]", 0, $e);
}
} catch (DBA_Exception $e) {
throw new RuntimeException("Un problème est survenu [DBA_Exception]", 0, $e);
}
return $tmp;
}
public function fetch(EntityManager $entityManager, string $table, array $correspondance, string $type, string $id) : array
{
$columns = [];
foreach ($correspondance as $s=>$d) {
if ($type === 'source') $columns[] = $s;
if ($type === 'destination') $columns[] = $d;
}
if ($type === 'destination') $columns[] = 'deleted_on';
if ($type === 'destination') $columns[] = 'source_id';
$sql = "select ".implode(" , ", $columns)." from ".$table;
$data = $this->executeRequeteRef($entityManager, $sql, []);
$values = [];
foreach ($data as $item) {
$values[$item[$id]] = $item;
}
return $values;
}
//todo que ce passe t'il pour les booleans
public function echapValue(?string $value) : string
{
if ($value === null or $value === '') return "null";
return "'". str_replace("'","''",$value) . "'";
}
public function insert(EntityManager $entityManager, string $table, array $item, array $correspondance, ?string $source = null) : void
{
$columns = []; foreach ($correspondance as $d) $columns[] = $d; $columns[] = "created_on";
if ($source !== null) $columns[] = 'source_id';
$values = []; foreach ($correspondance as $s => $d) $values[] = $this->echapValue($item[$s]); $values[] = "now()";
if ($source !== null) $values[] = "'".$source."'";
$sql = "insert into ".$table." (".implode(',',$columns).") values (".implode(',',$values).")";
$this->executeRequeteRef($entityManager, $sql, []);
}
public function update(EntityManager $entityManager, string $table, array $item, array $correspondance, string $id, ?string $source = null) : void
{
$values = []; foreach ($correspondance as $s => $d) $values[] = $d."=".$this->echapValue($item[$s]);
if ($source !== null) $values[] = "source_id='".$source."'";
$values[] = "updated_on=now()";
$sql = "update ".$table. " set " . implode(" , ", $values). " where id=:id";
$this->executeRequeteRef($entityManager, $sql, ["id" => $id]);
}
public function restore(EntityManager $entityManager, string $table, string $id) : void
{
$sql = "update ".$table." set deleted_on=NULL where id=:id";
$this->executeRequeteRef($entityManager, $sql, ["id" => $id]);
}
public function delete(EntityManager $entityManager, string $table, string $id) : void
{
$sql = "update ".$table." set deleted_on=now() where id=:id";
$this->executeRequeteRef($entityManager, $sql, ["id" => $id]);
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Service\SqlHelper;
trait SqlHelperServiceAwareTrait
{
private SqlHelperService $sqlHelperService;
public function getSqlHelperService(): SqlHelperService
{
return $this->sqlHelperService;
}
public function setSqlHelperService(SqlHelperService $sqlHelperService): void
{
$this->sqlHelperService = $sqlHelperService;
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Service\SqlHelper;
use Psr\Container\ContainerInterface;
class SqlHelperServiceFactory {
/**
* @param ContainerInterface $container
* @return SqlHelperService
*/
public function __invoke(ContainerInterface $container) : SqlHelperService
{
$service = new SqlHelperService();
return $service;
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Service\Synchronisation;
use DateTime;
use UnicaenSynchro\Service\SqlHelper\SqlHelperServiceAwareTrait;
class SynchronisationService {
use SqlHelperServiceAwareTrait;
private array $entityManagers = [];
public function setEntityManagers(array $entityManagers): void
{
$this->entityManagers = $entityManagers;
}
private array $configs = [];
public function setConfigs(array $configs): void
{
$this->configs = $configs;
}
public function getFromConfig(string $name, string $key)
{
return $this->configs[$name][$key];
}
private function checkDifferences(array $itemSource, array $itemDestination, array $correspondance, ?string $source = null) : bool {
foreach ($correspondance as $idSource => $idCorrespondance) {
if ($itemSource[$idSource] != $itemDestination[$idCorrespondance]) {
// var_dump($itemSource[$idSource]);
// var_dump($itemDestination[$idCorrespondance]);
// var_dump("Diff: " . $idSource . " >>> " . $itemSource[$idSource] . "!=" . $itemDestination[$idCorrespondance]);
// die();
return true;
}
}
if ($source !== null) {
// var_dump($source);
// var_dump($itemDestination);
// die();
// var_dump($itemDestination['source_id']);
// die();
if ($itemDestination['source_id'] !== $source) return true;
}
return false;
}
public function synchronise(string $name) : string
{
echo "Synchronisation [".$name."]\n"; flush();
$debut = new DateTime();
echo "Debut: ".$debut->format('d/m/y H:i:s:u')."\n"; flush();
$correspondance = $this->getFromConfig($name, 'correspondance');
$orm_source = $this->entityManagers[$this->getFromConfig($name, 'orm_source')];
$orm_destination = $this->entityManagers[$this->getFromConfig($name, 'orm_destination')];
$table_source = $this->getFromConfig($name, 'table_source');
$table_destination = $this->getFromConfig($name, 'table_destination');
$id_source = $this->getFromConfig($name, 'id');
$source = $this->getFromConfig($name, 'source');
$id_destination = $correspondance[$id_source];
$data_source = $this->getSqlHelperService()->fetch($orm_source, $table_source, $correspondance, 'source', $id_source);
echo count($data_source). " entrées dans les données sources.\n"; flush();
$data_destination = $this->getSqlHelperService()->fetch($orm_destination, $table_destination, $correspondance, 'destination', $id_destination);
$data_destination_on = []; $data_destination_off = [];
foreach ($data_destination as $item) {
if ($item['deleted_on'] !== null) $data_destination_off[] = $item; else $data_destination_on[] = $item;
}
echo count($data_destination_on) . "(~". count($data_destination_off).")". " entrées dans les données cibles actives.\n"; flush();
$read = new DateTime();
echo "Lecture: ".$read->format('d/m/y H:i:s:u'). "(" . ($read->diff($debut))->format('%H:%m:%s:%F').")\n"; flush();
//check for removal
$nbRetrait = 0;
// $texte_retrait = "";
foreach ($data_destination as $id => $item) {
if ($item['deleted_on'] === null AND !isset($data_source[$id])) {
$nbRetrait++;
// $texte_retrait .= "Retrait de ".$id." des données destination.\n";
$this->getSqlHelperService()->delete($orm_destination, $table_destination, $id);
}
}
echo "#Retrait: ".$nbRetrait."\n"; flush();
// $log .= $texte_retrait;
//check for adding
$nbAjout = 0;
// $texte_ajout = "";
foreach ($data_source as $id => $item) {
if (!isset($data_destination[$id])) {
$nbAjout++;
// $texte_ajout .= "Ajout de ".$id." des données sources.\n";
$this->getSqlHelperService()->insert($orm_destination, $table_destination, $item, $correspondance, $source);
}
}
echo "#Ajout: ".$nbAjout."\n"; flush();
// $log .= $texte_ajout;
//check for restauration
$nbRestauration = 0;
// $texte_restauration = "";
foreach ($data_source as $id => $item) {
if (isset($data_destination[$id]) AND $data_destination[$id]["deleted_on"] !== null) {
$nbRestauration++;
// $texte_restauration .= "Restauration de ".$id." des données destinations.\n";
$this->getSqlHelperService()->restore($orm_destination, $table_destination, $id);
}
}
echo "#Restauration: ".$nbRestauration."\n"; flush();
// $log .= $texte_restauration;
//check for modification
$nbModification = 0;
// $texte_modication = "";
foreach ($data_source as $id => $item) {
if (isset($data_destination[$id]) AND $this->checkDifferences($item, $data_destination[$id], $correspondance, $source)) {
$nbModification++;
// $texte_modication .= "Modif de ".$id." des données sources.\n";
$this->getSqlHelperService()->update($orm_destination, $table_destination, $item, $correspondance, $id, $source);
}
}
echo "#Modification: ".$nbModification."\n"; flush();
// $log .= $texte_modication;
$fin = new DateTime();
echo "Fin: ".$fin->format('d/m/y H:i:s:u')."\n";
echo "Durée de la synchronisation: " . ($fin->diff($debut))->format('%H:%m:%s:%F') . "\n";
return "";
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Service\Synchronisation;
trait SynchronisationServiceAwareTrait
{
private SynchronisationService $synchronisationService;
public function getSynchronisationService(): SynchronisationService
{
return $this->synchronisationService;
}
public function setSynchronisationService(SynchronisationService $synchronisationService): void
{
$this->synchronisationService = $synchronisationService;
}
}
\ No newline at end of file
<?php
namespace UnicaenSynchro\Service\Synchronisation;
use Doctrine\ORM\EntityManager;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\NotFoundExceptionInterface;
use UnicaenSynchro\Service\SqlHelper\SqlHelperService;
class SynchronisationServiceFactory {
/**
* @param ContainerInterface $container
* @return SynchronisationService
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function __invoke(ContainerInterface $container) : SynchronisationService
{
/**
* @var EntityManager $source
* @var EntityManager $destination
* @var SqlHelperService $sqlHelper
*/
$source = $container->get('doctrine.entitymanager.orm_octopus');
$destination = $container->get('doctrine.entitymanager.orm_default');
$entityManagers = [
'orm_octopus' => $source,
'orm_default' => $destination,
];
$sqlHelper = $container->get(SqlHelperService::class);
$configs = $container->get('Config')['synchros'];
$service = new SynchronisationService();
$service->setSqlHelperService($sqlHelper);
$service->setConfigs($configs);
$service->setEntityManagers($entityManagers);
return $service;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment