Commit c01c5bec authored by Jordan Breton's avatar Jordan Breton

Merge branch 'rts' into dev

parents 64380250 bd861b7d
Ce document est également disponible en [français](README.md)
# Foreword
The **wfw** framework (for Web FrameWork) have been designed to create websites, webservices and
more or less complicated web applications. It natively supports multilang and have been written in **PHP 7.2**.
The purpose is to provide a support to **Event-sourced** projects and a design which encourages
use of **CQRS**. If you want to know more about those principles, please takes a look to **Greg Young**'s
conferences on youtube.
The wfw design don't use a MVC pattern (and no one of it's derivatives) because it should
be used to design long-running process. Often missused, or used where it shouldn't, it leads
to structural problem in most web softwares. For more informations about this complex subject,
I let you take a look to a bunch of articles written by Tom Butler about MVC, including this one
beautifully entititled [MVC : Model-View-Confusion](https://r.je/views-are-not-templates.html).
Because of the way HTTP works, I choose to implements a handlers based architecture created to
be easy-to-use to create websites. I tried to make it flexible to handle most use-cases.
Furthermore, I decided to avoid use of third party libraries to keep control on the framework's
evolutions without depending on other projetcs and sustain it.
Code reuse is a beautifull concept, when applyed carefully. In my opinion, a project which depends
upon ten or more other projects become a maintenance nightmare after few years.
# Attribution
On of the wfw's principal concern is to avoid third party libraries, But I still integrated three of them
in the framework's core :
- [PHPMailer](https://github.com/PHPMailer/PHPMailer)
- [HTMLPurifier](http://htmlpurifier.org/)
- [Dice](https://github.com/Level-2/Dice)
Why ? Because those libraries seems essentials to me, and beacause it's far beyond what I can
ever do myself :
- **HTMLPurifier**, a very good protection against XSS.
- **PHPMailer**, which I shouldn't have to introduce, to easily send mails.
- **Dice**, the only one dependency injection container which is efficient and not over-complicated.
(To be as convinced as I am, please take the time to read [this](https://github.com/Level-2/Dice#performance)
about performances and it's well written documentation)
Finally, even if this libraries have been integrated in the framework's core, they can be
replaced by watever you want. I tried to design this framework as flexible as I can, so I
hope that it's a success.
# Documentation
The full documenation can be found on it's [dedicated website](https://wfwdoc.bee-color.fr).
# Contribution
Feel free to contribute !
I do my best to write this documentation in two langs : English and French. Since I'm a french
guy, I try to traduce it as I can, so please do not hesitate to correct me when I'm wrong, it
would be appreciated.
Finally, I try to produce a well written doc, as clear and detailed as possible, so, once again,
if something is missing or unclear, don't hesistate to contact me.
\ No newline at end of file
This document is also available in [english](README.en.md).
# Documentation update
# Avant-propos
**Since a major update is about to be released, the current documentation website is outdated and will
be entierly rewritten to be clearer and takes new functionnalities into consideration.**
Le framework **wfw** (pour Web FrameWork) est un framework prévu pour la réalisation
de sites web et/ou services et/ou application plus ou moins complexes et est
déjà équipé d'un système de gestion des langues et a été écrit en **PHP 7.2**.
# Foreword
Le but est de promouvoir un support de base pour la création de projets articulés autour
du principe **CQRS** et pour offrir un support de base à l'**Event-sourcing**. Si vous souhaitez
vous documenter sur ces sujets, n'hésitez pas à visionner les conférences de **Greg Young** et
de ses confrères.
The **wfw** framework (for Web FrameWork) have been designed to create websites, webservices and
more or less complicated web applications. It natively supports multilang and have been written in **PHP 7.2**.
Son architecture ne se base pas sur MVC (ou aucun autre de ses dérivés) parce
que ce pattern est avant tout destiné à des long-running process et qu'il est bien
souvent utilisé à tort et à travers, et souvent mal appliqué (je vous renvoie
sur les articles éclairés et documentés de Tom Butler sur ce design
pattern, et notamment les deux articles très justement appelés
[MVC : Model-View-Confusion](https://r.je/views-are-not-templates.html)).
The purpose is to provide a support to **Event-sourced** projects and a design which encourages
use of **CQRS**. If you want to know more about those principles, please takes a look to **Greg Young**'s
conferences on youtube.
Un serveur http ayant un fonctionnement totalement différent, j'ai choisi d'implémenter
un pattern personnalisé à base de handlers, prévu pour simplifier au maximum
la création de sites internet sans impacter le nombre de possibilités d'utilisation.
The wfw design don't use a MVC pattern (and no one of it's derivatives) because it should
be used to design long-running process. Often missused, or used where it shouldn't, it leads
to structural problem in most web softwares. For more informations about this complex subject,
I let you take a look to a bunch of articles written by Tom Butler about MVC, including this one
beautifully entititled [MVC : Model-View-Confusion](https://r.je/views-are-not-templates.html).
De plus, j'ai choisi volontairement de limiter au strict minimum le recours à
des librairies tierces afin de garder la maîtrise de l'évolution du framework
sans avoir à dépendre d'autres projets, afin de pérenniser mon travail.
Because of the way HTTP works, I choose to implements a handlers based architecture created to
be easy-to-use to create websites. I tried to make it flexible to handle most use-cases.
La réutilisation du code est une très bonne chose, lorsqu'elle est faite avec
intelligence et discernement. Un projet qui a besoin de plus de 10 autres projets
indépendants devient très difficile à maintenir avec le temps.
Furthermore, I decided to avoid use of third party libraries to keep control on the framework's
evolutions without depending on other projetcs and sustain it.
Code reuse is a beautifull concept, when applyed carefully. In my opinion, a project which depends
upon ten or more other projects become a maintenance nightmare after few years.
## Attribution :
# Attribution
Si l'un des principaux buts de ce framework est de limiter le recours aux dépendances
à d'autres projets, j'en ai tout de même intégré trois au coeur du framework :
- [PHPMailer](https://github.com/PHPMailer/PHPMailer)
On of the wfw's principal concern is to avoid third party libraries, But I still integrated three of them
in the framework's core :
- [PHPMailer](https://github.com/PHPMailer/PHPMailer)
- [HTMLPurifier](http://htmlpurifier.org/)
- [Dice](https://github.com/Level-2/Dice)
Pourquoi ? Parce que ces librairies me semblent parfaitement indispensables et
surtout sont bien plus abouties que tout ce que j'aurais pu coder moi même:
- **HTMLPurifier** est un projet brillant qui demande des connaissances que je ne
possède pas dans le domaine des failles XSS.
- **PHPMailer**, qu'il est inutile de présenter, est une fantastique librairie pour
les envois de mails.
- **Dice** est le seul conteneur d'injection de dépendances qui joue son rôle avec
efficacité sans dévier de son objectif principal. Ses performances rivalisent avec
les DIC les plus aboutis (et les surpassent même, voir les tests de performance
[ici](https://github.com/Level-2/Dice#performance)).
Il est par ailleurs à noter que ces librairies sont intégrées au coeur du framework,
mais peuvent être remplacées si vous le souhaitez par celles de votre choix.
WFW se veut totalement souple, et j'espère que ce pari est réussi.
Why ? Because those libraries seems essentials to me, and beacause it's far beyond what I can
ever do myself :
- **HTMLPurifier**, a very good protection against XSS.
- **PHPMailer**, which I shouldn't have to introduce, to easily send mails.
- **Dice**, the only one dependency injection container which is efficient and not over-complicated.
(To be as convinced as I am, please take the time to read [this](https://github.com/Level-2/Dice#performance)
about performances and it's well written documentation)
Finally, even if this libraries have been integrated in the framework's core, they can be
replaced by watever you want. I tried to design this framework as flexible as I can, so I
hope that it's a success.
# Documentation
La documentation complète est disponible sur un [site internet dédié](https://wfwdoc.bee-color.fr).
The full documenation can be found on it's [dedicated website](https://wfwdoc.bee-color.fr).
# Contribution
N'hésitez pas à contribuer !
Feel free to contribute !
Je fais actuellement de mon mieux pour essayer de proposer
la documentation en deux langues : anglais et français. Si vous avez des corrections
à apporter, ou des traductions à proposer, je les accepte volontiers.
I do my best to write this documentation in two langs : English and French. Since I'm a french
guy, I try to traduce it as I can, so please do not hesitate to correct me when I'm wrong, it
would be appreciated.
Enfin, je fais tout mon possible pour produire une documentation aussi claire et
détaillée que possible, mais je ne suis pas à l'abri d'erreurs, notamment dans
la documentation en anglais. Plus que votre indulgence, votre participation sera
grandement appréciée.
\ No newline at end of file
Finally, I try to produce a well written doc, as clear and detailed as possible, so, once again,
if something is missing or unclear, don't hesistate to contact me.
\ No newline at end of file
#!/usr/bin/php -q
<?php
use wfw\cli\backup\Backup;
use wfw\cli\backup\BackupManager;
use wfw\cli\backup\conf\BackupManagerConf;
......@@ -16,7 +15,7 @@ use wfw\engine\lib\data\string\serializer\LightSerializer;
use wfw\engine\lib\data\string\serializer\PHPSerializer;
use wfw\engine\lib\PHP\types\PHPString;
require_once dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR."init.environment.php";
require_once dirname(__FILE__,2)."/init.environment.php";
$argvReader = new ArgvReader(new ArgvParser(new ArgvOptMap([
new ArgvOpt("-list","Liste tous les backups du manager",0,null,true),
......@@ -29,7 +28,10 @@ $argvReader = new ArgvReader(new ArgvParser(new ArgvOptMap([
])),$argv);
try{
$confs = new BackupManagerConf(ENGINE.'/config/conf.json', SITE.'/config/conf.json');
$confs = new BackupManagerConf(
dirname(__DIR__,2).'/engine/config/conf.json',
dirname(__DIR__,2).'/site/config/conf.json'
);
$saveFile = $confs->getManagerFolder().'/manager.backup';
$serializer = new LightSerializer(new GZCompressor(), new PHPSerializer());
......@@ -41,7 +43,7 @@ try{
else $manager = new BackupManager($confs->getMaxBackups());
$args=[];
if(count($argv) === 1 || count($argv) === 2 && $argvReader->exists("-make")){
$dirs = glob(ROOT."/*",GLOB_ONLYDIR);
$dirs = glob(dirname(__DIR__,2)."/*",GLOB_ONLYDIR);
foreach($dirs as &$v){ $v = basename($v); }
$args = array_merge(["dbs"],array_diff($dirs,["backups",".",".."]));
var_dump($args);
......@@ -63,7 +65,7 @@ try{
array_shift($args);
$path = array_shift($args);
if(!(new PHPString($path))->startBy('/'))
$path = CLI."/$path";
$path = dirname(__DIR__)."/$path";
if(!is_dir($path))
throw new InvalidArgumentException("$path is not a valide directory");
$backupFolder = $path;
......@@ -91,11 +93,11 @@ try{
);
}
}else{
if(is_dir(ROOT."/$v")){
$backups[] = new LocalFilesBackup(ROOT."/$v",$backupFolder);
if(is_dir(dirname(__DIR__,2)."/$v")){
$backups[] = new LocalFilesBackup(dirname(__DIR__,2)."/$v",$backupFolder);
}else{
throw new InvalidArgumentException(
"Unknown backup type '$v' : Only direct folders under ".ROOT
"Unknown backup type '$v' : Only direct folders under ".dirname(__DIR__,2)
." or special keyword 'dbs' are accepted !"
);
}
......
......@@ -29,7 +29,8 @@ final class BackupManagerConf {
* @param string $basepath Chemin de base pour la résolution de chemins relatifs
* @throws \InvalidArgumentException
*/
public function __construct(string $engineConf,?string $siteConf, string $basepath = CLI) {
public function __construct(string $engineConf,?string $siteConf, ?string $basepath = null) {
if(is_null($basepath)) $basepath = dirname(__DIR__,2);
$this->_basepath = $basepath;
$confIo = new JSONConfIOAdapter();
$conf = new FileBasedConf($engineConf,$confIo);
......
<?php
require_once dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR."engine".DIRECTORY_SEPARATOR."webroot".DIRECTORY_SEPARATOR."init.environment.php";
require_once dirname(__FILE__,2)."/engine/webroot/init.environment.php";
(new \wfw\engine\core\errors\handlers\DefaultErrorHandler(false))->handle();
\ No newline at end of file
......@@ -6,7 +6,7 @@ use wfw\engine\lib\cli\argv\ArgvOptMap;
use wfw\engine\lib\cli\argv\ArgvParser;
use wfw\engine\lib\cli\argv\ArgvReader;
require_once dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR."init.environment.php";
require_once dirname(__FILE__,2)."/init.environment.php";
$argvReader = new ArgvReader(new ArgvParser(new ArgvOptMap([
new ArgvOpt('-install','Installe un package pour le projet courant',null,null,true),
......@@ -23,47 +23,67 @@ try{
);
};
$site = dirname(__DIR__,2)."/site";
$engine = dirname(__DIR__,2)."/engine";
$modules = dirname(__DIR__,2)."/modules";
if($argvReader->exists('-install')){
$args = $argvReader->get('-install');
foreach($args as $package){
$tmp = explode("/",$package);
$location = SITE.'/package';
$location = $site.'/package';
$l = 'site';
if(count($tmp)===2){
$location = ($tmp[0] === 'engine')
? ENGINE."/package/".($p=$tmp[1]) : "$location/".($p=$tmp[1]);
$l = $tmp[0];
}
else $location = "$location/".($p = $tmp[0]);
if(is_dir($location)){
$webroot = array_diff(scandir("$location/webroot"),['..','.']);
foreach($webroot as $dir){
if(!is_dir(SITE."/webroot/$dir")) mkdir(SITE."/webroot/$dir");
if(is_link(SITE."/webroot/$dir/$p")) unlink(SITE."/webroot/$dir/$p");
chdir(SITE."/webroot/$dir");
$exec("ln -s \"../../../$l/package/$p/webroot/$dir\" \"$p\"");
$m = false;
if(count($tmp) > 1){
$l = array_shift($tmp);
$p = implode("/",$tmp);
switch($l){
case 'engine' :
$location = "$engine/package/$p";
break;
case 'modules' :
$location = "$modules/$p";
$m = true;
break;
default :
$location = "$location/$p";
}
}else fwrite(STDOUT,"\e[33mWFW_installer UNKNOWN_PACKAGE\e[0m : $package\n");
fwrite(STDOUT,"$package installed.\n");
} else $location = "$location/".($p = $tmp[0]);
if(is_dir("$location")){
if(is_dir("$location/webroot")){
$webroot = array_diff(scandir("$location/webroot"),['..','.']);
foreach($webroot as $dir){
if(!is_dir("$site/webroot/$dir")) mkdir("$site/webroot/$dir");
if(is_link("$site/webroot/$dir/$p")) unlink("$site/webroot/$dir/$p");
chdir("$site/webroot/$dir");
if(!is_dir(dirname($p))) mkdir(dirname($p),0777,true);
$relativeAdapt = str_repeat("../",count(explode("/",$p))+2);
$relativeAdapt = substr($relativeAdapt,0,-1);
if(!$m) $exec("ln -s \"$relativeAdapt/$l/package/$p/webroot/$dir\" \"$p\"");
else $exec("ln -s \"$relativeAdapt/$l/$p/webroot/$dir\" \"$p\"");
}
fwrite(STDOUT,"$package installed.\n");
}else fwrite(STDOUT,"$package : nothing to do (no webroot folder found).\n");
}else fwrite(STDOUT,"\e[33mWFW_installer UNKNOWN_PACKAGE\e[0m : $package : $location doesn't exists\n");
}
}else if($argvReader->exists('-uninstall')){
$args = $argvReader->get('-uninstall');
foreach($args as $package){
$tmp = explode("/",$package);
$location = SITE.'/package';
$location = $site.'/package';
$l = 'site';
if(count($tmp)===2){
$location = ($tmp[0] === 'engine')
? ENGINE."/package/".($p=$tmp[1]) : "$location/".($p=$tmp[1]);
? $engine."/package/".($p=$tmp[1]) : "$location/".($p=$tmp[1]);
$l = $tmp[0];
}
else $location = "$location/".($p = $tmp[0]);
if(is_dir($location)){
if(is_dir("$location/webroot")){
$webroot = array_diff(scandir("$location/webroot"),['..','.']);
foreach($webroot as $dir){
unlink(SITE."/webroot/$dir/$p");
unlink("$site/webroot/$dir/$p");
}
}else fwrite(STDOUT,"\e[33mWFW_installer UNKNOWN_PACKAGE\e[0m : $package\n");
}else fwrite(STDOUT,"\e[33mWFW_installer UNKNOWN_PACKAGE\e[0m : $package : $location/webroot doesn't exists\n");
}
}else throw new InvalidArgumentException("Unknown command $argv[1]");
}catch(\InvalidArgumentException $e){
......
@LOGDIR/*.log @LOGDIR/*/*.log @LOGDIR/*/*/*.log @LOGDIR/*/*/*/*.log{
daily
size 100M
size 10M
rotate 15
compress
delaycompress
missingok
create 644 root root
create 744 www-data www-data
}
\ No newline at end of file
[Unit]
Description=WFW real time server (rts)
[Service]
Type=simple
User=www-data
KillSignal=SIGALRM
KillMode=process
ExecStart=/usr/bin/php -q @ROOT/daemons/rts/RTSLauncher.php
Restart=always
[Install]
WantedBy=multi-user.target
\ No newline at end of file
......@@ -3,7 +3,6 @@ Alias /wfw @ROOT/cli/webroot
AllowOverride none
</Directory>
<Directory @ROOT/cli/webroot>
Require host localhost
Require ip 127.0.0.1
AllowOverride none
</Directory>
\ No newline at end of file
......@@ -36,7 +36,7 @@ fi
echo ""
declare -a services=("sctl" "kvs" "msserver")
declare -a services=("sctl" "kvs" "rts" "msserver")
for i in "${services[@]}"; do
#Reset the file if exists
DAEMONCONF="$INSTALLPATH/config/$i.systemctl"
......@@ -65,16 +65,6 @@ done
ln -s "$INSTALLPATH/../wfw/WFWGlobalLauncher.php" "/usr/bin/wfw"
echo "Created symlink $INSTALLPATH/../wfw/WFWGlobalLauncher.php -> /usr/bin/wfw"
echo ""
echo "Creating $A2CONF...";
cat "$INSTALLPATH/config/wfw-global.conf.template" | sed -e "s+@ROOT+$ROOTPATH+g" >> "$A2CONF"
echo "Moving $A2CONF to $A2CONF_PATH..."
mv "$A2CONF" "$A2CONF_PATH"
echo "Enabling wfw-global.conf..."
a2enconf wfw-global
echo "Reloading apache2..."
systemctl reload apache2
echo ""
echo "Creating $CONFPATH..."
mkdir -p "$CONFPATH"
......@@ -118,5 +108,15 @@ echo ""
ln -s "$A2_SITES_CONFS" "$A2PATH/wfw-sites"
echo "Created symlink $A2_SITES_CONFS -> $A2PATH/wfw-sites"
echo ""
echo "Creating $A2CONF...";
cat "$INSTALLPATH/config/wfw-global.conf.template" | sed -e "s+@ROOT+$ROOTPATH+g" >> "$A2CONF"
echo "Moving $A2CONF to $A2CONF_PATH..."
mv "$A2CONF" "$A2CONF_PATH"
echo "Enabling wfw-global.conf..."
a2enconf wfw-global
echo "Reloading apache2..."
systemctl reload apache2