Compare commits

...

146 Commits

Author SHA1 Message Date
xdrm-brackets 55b379cd8c fix 2018-11-05 10:18:35 +01:00
xdrm-brackets 6712b33841 [build.generic.view.*group*.twig] fixed block clause that blocks counters to check if has no result 2018-04-17 16:41:44 +02:00
xdrm-brackets 73be58df63 [public.css.container] fixed card layout #rev.2 2018-04-17 16:31:27 +02:00
xdrm-brackets 7af0fefdc1 [public.css.container] fixed card layout 2018-04-17 16:28:47 +02:00
xdrm-brackets ee9f7871e4 [public.css.*.css] updated css builds 2018-04-17 15:42:09 +02:00
xdrm-brackets bba94f5630 [public.css.layout] fixed popup footer out-of-flow 2018-04-17 15:40:21 +02:00
xdrm-brackets ec3560beb5 [build.generic.view.settings.admin.create.main.twig] now 'generated password' when creating admin is selectable (copiable) 2018-04-17 15:39:25 +02:00
xdrm-brackets 3b2c707618 upd: fixed page-manager (dependencies' file content was downloaded in Ajax but never used, only checks if the file exists, so now <script> or <style> tags are filled with the downloaded content -> so more efficient) 2018-02-08 11:39:06 +01:00
xdrm-brackets 0c0f34c7d4 fix: http.core.HttpRequest (now manages both Apache/nginx, especially php-fpm because the function 'getallheaders()' is not available, so gess it from (solution from http://php.net/manual/en/function.getallheaders.php\#84262)) 2018-02-07 14:52:21 +01:00
xdrm-brackets f1c338853f fix: router.core.router (now manages URI with beginning slash '/' (removes it)) 2018-02-07 14:50:36 +01:00
xdrm-brackets eb604f2299 upd: composer.lock 2018-02-07 14:50:04 +01:00
xdrm-brackets 2709a109c7 fixed build.api.module.machineDefault (added argument id_warehouse to machine.state (in view machine.listAll)) 2018-01-29 22:26:22 +01:00
xdrm-brackets 1f91f4feb1 Fix header icon -1px (border-bottom of header) 2017-11-13 16:42:28 +01:00
xdrm-brackets d5a0cf7977 Update database backup 2017-11-13 14:20:05 +01:00
xdrm-brackets b38822e506 Fix history.archive layout 2017-11-13 13:49:32 +01:00
xdrm-brackets ea66003d27 Created TreeTokenNull to disable the 'TreeToken' build at will + use it in index 2017-11-13 13:43:14 +01:00
xdrm-brackets d064e304ee When no history.search.value -> display all 2017-11-13 13:37:50 +01:00
xdrm-brackets f99d1a8435 Update repo machine/search to match any keywords (space-separated) with a OR condition + minfix user 2017-11-13 13:34:38 +01:00
xdrm-brackets b745c9ef08 Update repo user/search to match any keywords (space-separated) with a OR condition + if no search input -> display all 2017-11-13 13:28:18 +01:00
xdrm-brackets d30ec35636 Now history.view.search searches through users+machines (as on its views) + TODO: manage space separated keywords 2017-11-13 12:17:26 +01:00
xdrm-brackets ad4143771c Make LIKE sql WHERE clause lower case 2017-11-13 11:51:25 +01:00
xdrm-brackets 061d473cad Reversed history.timeline order (DESC) 2017-11-13 11:42:08 +01:00
xdrm-brackets 3c642732b2 Now scroll to timeline.event when loading sub-section 2017-11-13 11:40:13 +01:00
xdrm-brackets 9d49c7fd10 Now on click on timeline.event -> load this event entry 2017-11-12 18:34:52 +01:00
xdrm-brackets 545d99d212 Added dates + hours to events history.timeline 2017-11-12 18:09:57 +01:00
xdrm-brackets 067f12cc1a Removed infobox popup js 2017-11-12 17:24:25 +01:00
xdrm-brackets 20baf93bf3 Now history.timeline is vertical 2017-11-12 17:22:35 +01:00
xdrm-brackets 57d7abb7b6 Updated css 2017-11-12 15:10:40 +01:00
xdrm-brackets 6616916013 Fix fonts.css -> font.css 2017-11-12 15:09:06 +01:00
xdrm-brackets 0390bdf7ad Now a little circle 'below' the event circle when same user 2017-11-12 14:53:33 +01:00
xdrm-brackets bc1df78120 History details.timeline ASC order (not reverse as history.view) 2017-11-12 14:53:06 +01:00
xdrm-brackets 43e626d32d Added module historyDefault/getById to check current user in history.details.view + Refactor css + added info in svg tags + javascript began management (only launch event, implementation TODO) 2017-11-12 13:01:29 +01:00
xdrm-brackets b0f9cfae1e session timeout management in views: warehouse, admin + if no response, logout just .5min after the session timeout 2017-11-12 11:45:47 +01:00
xdrm-brackets 0faaee0040 serverinfo.js now shows a popup when session time out + api.js reset the timeout when an API call have an error=0 + if no answer to popup in 5min logout 2017-11-12 11:29:52 +01:00
xdrm-brackets 172f1e5935 Updated container.scss to be a 'pointer' on timeline events 2017-11-11 18:50:01 +01:00
xdrm-brackets b73f71c652 Svg generation + historyDefault/get_timeline + repo history/getByIdMachine + container.scss to generate machine timeline 2017-11-11 18:46:43 +01:00
xdrm-brackets 34ffdae4fe Fix tests according to branch 'api-refactor' 2017-11-11 13:09:30 +01:00
xdrm-brackets 6b9bd03d9e Pop-Up manages 'background.click' to send FALSE to the 'handler' + hide (equivalent to CANCEL action) 2017-11-11 13:03:30 +01:00
xdrm-brackets a2d575e94f Added confirmation Pop-Up for: 1. history.archive 2. machine.delete 3. user.delete 2017-11-11 12:56:46 +01:00
xdrm-brackets db71c0400d Removed 'POST::' in the config file 2017-11-10 13:38:15 +01:00
xdrm-brackets dfdb84e8a0 Dispatched 'Request::remote' to 'Loader::remote' as a builder adapter 2017-11-09 12:56:00 +01:00
xdrm-brackets 0fed2ee61e Fixed css (added grey buttons) + Created js PopUp lib + use in admin list to remove one admin 2017-11-09 12:38:00 +01:00
xdrm-brackets 4213d8b132 Migrated admin methods from 'authenticationDefault' to new 'adminDefault' module 2017-11-09 12:37:27 +01:00
xdrm-brackets 088683d2bf Removed /lib folder added 'Twig' to default composer + cleaned autoloader file 2017-11-09 10:19:51 +01:00
xdrm-brackets 79216f6edc Fix menu-side :unhover:after not working on chrome 3x 2017-11-09 10:07:46 +01:00
xdrm-brackets ed771b20a9 updated documentationDefault/apiBlueprint 2017-11-09 10:06:43 +01:00
xdrm-brackets 0a3d4d9a0a Blocks in view: group.permission 2017-11-08 21:08:32 +01:00
xdrm-brackets 574e218da4 Blocks in view: group.view 2017-11-08 20:53:21 +01:00
xdrm-brackets 047a71d822 minfix 2017-11-08 16:07:40 +01:00
xdrm-brackets 45984b4a93 Blocks in view: group.choice.* 2017-11-08 14:23:07 +01:00
xdrm-brackets 8ac65dc399 Blocks in view: group.form.* 2017-11-08 14:16:51 +01:00
xdrm-brackets 937515997c Blocks in view: user.view + added blocks to machine.view 2017-11-08 14:10:38 +01:00
xdrm-brackets 4897fad9e6 Blocks in view: user.group 2017-11-08 14:05:16 +01:00
xdrm-brackets 6c94f1064b Blocks in view: user.form.remove 2017-11-08 14:01:51 +01:00
xdrm-brackets 73b7b26b63 Blocks in view: user.form.edit 2017-11-08 14:00:27 +01:00
xdrm-brackets 7a2248f7da Blocks in view: user.form.create 2017-11-08 13:58:19 +01:00
xdrm-brackets ccf11739e2 Blocks in view: settings/password 2017-11-08 13:52:37 +01:00
xdrm-brackets d0515239c5 Blocks in view: settings/admin/create 2017-11-08 13:51:55 +01:00
xdrm-brackets 775a9caee4 Blocks in view: settings/admin/view 2017-11-08 13:51:00 +01:00
xdrm-brackets 3d99edc000 Blocks in view: profile/password 2017-11-08 13:49:28 +01:00
xdrm-brackets aec043a67e Blocks in view: history/view 2017-11-08 13:49:18 +01:00
xdrm-brackets 5b205939ca git ignore now /tmp and /public_html/tmp 2017-11-08 13:47:40 +01:00
xdrm-brackets 0c2e031885 Added history/archive to 'view'-er + fixed views' class 2017-11-08 13:46:57 +01:00
xdrm-brackets be6b3502be Created 'i_patch' to patch the 'i_view' each one have the same name as the associated 'warehouse module' + it can bind multiple files to a main's block each + done machine/view + its patch 'motheure' + machine refactored (blockized the templates) 2017-11-08 13:04:49 +01:00
xdrm-brackets d161f464fb Done view settings/admins (lists the admins of the warehouse) 2017-11-07 12:58:32 +01:00
xdrm-brackets e1c5acf96c Fixed history *flex* direction + if not much data, align to top 2017-11-07 12:41:08 +01:00
xdrm-brackets 6b123765b6 Added module 'authenticationDefault/get_admins' to fetch all admins of the warehouse 2017-11-07 12:16:13 +01:00
xdrm-brackets a5b22a4836 Added 'in-dev' flag for incomplete views + added 'add' icon for sub-menu + migrated views for: profile, settings 2017-11-07 12:08:45 +01:00
xdrm-brackets df6d5e47c0 minfix: missing 'use' 2017-11-07 11:40:33 +01:00
xdrm-brackets e51d56e7a5 Added forms to View() views: group, machine, user + comment and indent correctly 2017-11-07 11:37:18 +01:00
xdrm-brackets a066b4b7c1 minmod 2017-11-07 11:31:56 +01:00
xdrm-brackets 550b1bd849 Removed build/viewer + migrated forms of machine/* 2017-11-07 11:21:27 +01:00
xdrm-brackets 77e3fc6f98 Added views history/* 2017-11-06 15:23:49 +01:00
xdrm-brackets 3a730ccfbd Created /generic/core/i_view and the 'View' builder + migrated views : user/*, machine/*, group/* 2017-11-06 15:15:24 +01:00
xdrm-brackets 5d3beefb30 Added 'serverinfo.js' to have the module list in order for JAVASCRIPT to load module-specific content or not 2017-11-05 11:17:53 +01:00
xdrm-brackets eb79b1d8bb fixed infinite loader when loading current page 2017-11-03 10:22:34 +01:00
xdrm-brackets 7992c15449 Minfix composer.json autoload 2017-11-03 09:36:04 +01:00
xdrm-brackets 38b790c82d Fixed log for SATS (or if no TreeToken received) 2017-10-27 18:17:07 +02:00
xdrm-brackets 00f1efb38d minfix + avoid session_guard.child for SATS api call 2017-10-27 18:15:37 +02:00
xdrm-brackets 51f1f6f80c rename 'window._token_' to 'window._tree_token_' in api.js 2017-10-27 18:15:15 +02:00
xdrm-brackets 267ef71d36 Updated .gitignore to ignore .log files 2017-10-27 18:02:36 +02:00
xdrm-brackets 63fa7eb5a0 Manage TreeToken.parent + TreeToken.child 2017-10-27 18:02:11 +02:00
xdrm-brackets 4e99d042ab Fixed pages '/warehouse/' and '/admin/' added /src/logauth.ico + mininfied version of api.js 2017-10-27 18:01:42 +02:00
xdrm-brackets 3c04f3cc50 Updated API to manage TokenTree 2017-10-27 18:00:53 +02:00
xdrm-brackets 4e40f26e64 Fixed composer autoloader-s for added xdrm-framework's parts 2017-10-27 18:00:11 +02:00
xdrm-brackets 4f2144f64b Added build/core/TreeToken 2017-10-27 17:59:46 +02:00
xdrm-brackets 0cbb21ece8 Added build/log/core 2017-10-27 17:58:39 +02:00
xdrm-brackets 4245df37c7 machine/view sync icon faded 2017-10-19 18:01:13 +02:00
xdrm-brackets ffa5c1060e authenticationDefault::create_admin + iface to create a new admin and return its new generated password 2017-10-19 14:57:37 +02:00
xdrm-brackets 7e0f028db4 authenticationDefault::update_warehouse + iface to update warehouse access code (password) 2017-10-19 14:21:20 +02:00
xdrm-brackets a87911e76f Renamed authentification/authentication + authenticationDefault::update_admin + iface to update admin password 2017-10-19 14:07:38 +02:00
xdrm-brackets 8e430ff242 Motheure-simple now to 'ms' no 'h' anymore 2017-10-14 16:46:35 +02:00
xdrm-brackets eb7f94dce9 Add instead of replacing when updating motheure::increment 2017-10-13 19:47:49 +02:00
xdrm-brackets dad2125544 debug 2017-10-13 19:38:22 +02:00
xdrm-brackets 22c59b7a1d Fixed motheure::increment() param missing 2017-10-13 19:28:52 +02:00
xdrm-brackets 1a37de514c [fix] Fixed modules.js motheure::increment type from array of ints to int 2017-10-13 19:25:33 +02:00
xdrm-brackets 288aba7c6e Revert "Fix modules.json motheure::increment count data type"
This reverts commit e67ef1ae4b.
2017-10-13 19:13:28 +02:00
xdrm-brackets e67ef1ae4b Fix modules.json motheure::increment count data type 2017-10-13 19:12:24 +02:00
xdrm-brackets 22795697a3 debug to fetchDefault::dispatch from its dispatchers error to 'saved' field for the etree feature Err:: code negative 2017-10-13 19:11:24 +02:00
xdrm-brackets 21570a7328 Added 'saved': 0 by default if fetchDefault::dispatch error in dispatched method 2017-10-13 19:07:35 +02:00
xdrm-brackets 0c5d528813 Revert 13da1d8e71 2017-10-13 19:01:55 +02:00
xdrm-brackets b655e737c6 Fixed motheure::increment param name 2017-10-13 19:00:43 +02:00
xdrm-brackets 13da1d8e71 Propagate fetchDefault::dispatch to api.response with 'saved': 0 by default 2017-10-13 18:46:28 +02:00
xdrm-brackets c3e1a5d4d6 Fixed fetchDefault::motheure_simple code 2017-10-13 18:43:52 +02:00
xdrm-brackets 2655edee5d [fix] added in modules.json fetchDefault::motheure_simple 2017-10-13 18:41:02 +02:00
xdrm-brackets 474d60394d Dev. motheure::increment + fetchDefault::motheure_simple calling motheure::increment 2017-10-13 16:46:30 +02:00
xdrm-brackets 9dbfe754b4 Added module 'motheure' + displayed motor count in machine view 2017-10-12 22:10:24 +02:00
xdrm-brackets 75f40bd806 Fixed admin+warehouse creation 2017-10-12 14:29:52 +02:00
xdrm-brackets 79ec314782 Fixed machine/create failure because added 'ap' and 'ip' fields -> insert check failed 2017-10-11 14:14:10 +02:00
xdrm-brackets aacfad3772 Added icon when machine not synced 2017-09-29 11:31:00 +02:00
xdrm-brackets 19936cd333 bugfix 2017-09-28 23:09:20 +02:00
xdrm-brackets 010ed78bd2 Make 'chips' and 'states' global, not of rfid-read 2017-09-28 19:13:22 +02:00
xdrm-brackets 69758aead6 debug 2017-09-28 17:46:09 +02:00
xdrm-brackets b851826a9b [1] Created 'deployDefault' and renamed 'moduleDefault' to 'fetchDefault'[2] Implemented 'deployDefault/dispatch' which has the same kind of implementation as 'fetchDefault/dispatch'[3] Implemented 'deployDefault/rfid_read' with the useful data for it to work properly[4] Integrated deployDefault to machineDefault::getMachineWorkingInformation 2017-09-28 16:57:30 +02:00
xdrm-brackets 4d1a7fed5a Fixed missing extract() for *moduleDefault/rfid_read* 2017-09-27 18:32:30 +02:00
xdrm-brackets 978aed690f [1] machineDefault/update uses `moduleDefault/dispatch` to manage data for each feature
[2] `moduleDefault/dispatch` is now implemented
[3] `moduleDefault/rfid_read` implemented and caught by the *dispatcher*
[4] Added repo method etree/parse to get useable data from 'moduleName-etreeDaemonName'
2017-09-26 17:34:17 +02:00
xdrm-brackets d1f7f4f18f Removed debug 2017-09-26 16:42:52 +02:00
xdrm-brackets ebf2b301d6 Fixed authdefault 2017-09-26 00:05:52 +02:00
xdrm-brackets a14d9c4da0 testfix permission (authdefault) 2017-09-25 23:52:53 +02:00
xdrm-brackets 352dfdc995 Fixed permission issues for *SATS* 2017-09-25 23:40:14 +02:00
xdrm-brackets 97c7b8474b minmod 2017-09-25 23:32:36 +02:00
xdrm-brackets f15db0a3a9 Fixed according to *SATS* api/sync log @2 2017-09-25 23:23:42 +02:00
xdrm-brackets f4271043c8 Fixed according to *SATS* api/sync log 2017-09-25 23:21:42 +02:00
xdrm-brackets 3914b85a36 Updated composer 2017-09-25 17:00:20 +02:00
xdrm-brackets e7e36162a1 Added composer.lock 2017-09-25 16:57:37 +02:00
xdrm-brackets 60b6d7663b Update composer.json license 2017-09-25 16:54:45 +02:00
xdrm-brackets 586f759d77 Merge branch 'dev' 2017-09-25 16:39:55 +02:00
xdrm-brackets bef2d6c7ce Updated database 2017-09-25 16:37:59 +02:00
xdrm-brackets a4534a194d Cleaned _config/modules.json_ from 'module' sample module + removed fake modules: 'download' & 'upload' 2017-09-25 16:18:23 +02:00
xdrm-brackets ba4cb04925 Update `machineDefault::getMachineWorkingInformation` to send *ETREE* 2017-09-25 16:11:10 +02:00
xdrm-brackets 05d1ef50e0 Update *module_merge* to link `id_etree` instead of `id_module` (impacts 5. 6. 8.) 2017-09-25 15:29:15 +02:00
xdrm-brackets 261398d4a8 updated getMachineWorkingInformation according to previous database changes 2017-09-24 19:48:31 +02:00
xdrm-brackets 9a9a030ef6 Fixed option display because it was the 'displayed' id ('m' prefix) and not the real one 2017-09-24 19:47:33 +02:00
xdrm-brackets 6d1bfcead1 updated state, now contains the value of each pin of a chip (#id_chip and no more #id_pin_merge) 2017-09-24 19:47:00 +02:00
xdrm-brackets 0945b7da1b Now there is no more 'pin_merge' so CHIP have their 'pins' in itself 2017-09-24 19:46:35 +02:00
xdrm-brackets a24e0569da Removed from database 2017-09-24 19:45:49 +02:00
xdrm-brackets a5429b7ead Update considering last database update 2017-09-24 19:45:31 +02:00
xdrm-brackets d75d7e6519 Updated database (redesign of genericity) 2017-09-24 19:45:18 +02:00
xdrm-brackets 4e4e031d3f Merge branch 'dev' 2017-09-23 20:01:55 +02:00
xdrm-brackets f9f0074609 minfix layout (check-table) 2017-09-23 20:01:43 +02:00
xdrm-brackets fcfbd2a36a minfix layout (check-table) 2017-09-23 19:58:39 +02:00
xdrm-brackets 475ea6d0b3 Updated schema 2017-09-23 19:46:37 +02:00
xdrm-brackets 9fe1bf3072 'extension' renamed to 'option' + showed in machine_cluster lists (machine/groups + groups/view) + module in term of design / option in term of user explanation 2017-09-23 19:40:37 +02:00
xdrm-brackets fd7bc472ec Schema updated for modules (also called 'extensions') + the view 'analytics' became 'extensions' and now there is the default layout for choosing extensions + TODO: extensions.js + POST::link / POST::unlink to add to 'clusterDefault' or create 'extensionDefault' + TODO: rename module to extension 2017-09-23 19:05:54 +02:00
xdrm-brackets fd0d9cef56 Replaced page 'analytics' by 'extensions' 2017-09-23 15:44:06 +02:00
xdrm-brackets 939ec1f42c updated sass vscode:ext + updated group-members view flexbox 2017-09-23 15:07:14 +02:00
183 changed files with 11255 additions and 4487 deletions

6
.gitignore vendored
View File

@ -4,5 +4,11 @@
*.swp *.swp
/lib/vendor /lib/vendor
*.lock *.lock
!/composer.lock
/vendor/ /vendor/
/phpunit/coverage /phpunit/coverage
.vscode
TODO
*.log
/tmp
/public_html/tmp

View File

@ -8,32 +8,6 @@
if( !defined('__PUBLIC__') ) define('__PUBLIC__', __ROOT__.'/public_html' ); if( !defined('__PUBLIC__') ) define('__PUBLIC__', __ROOT__.'/public_html' );
/* [1] On définit __SERVER_HOST__ et __SERVER_ROOT__ si c'est pas déja fait
=========================================================*/
if( !defined('__SERVER_HOST__') || !defined('__SERVER_ROOT__') ){
/* (1) On charge le fichier de configuration */
$json = json_decode( file_get_contents(__ROOT__.'/config/server.json'), true );
// Si pas d'erreur, on définit
if( !is_null($json) ){
/* (2) Gestion de la config si server local ou remote */
if( !isset($_SERVER['SERVER_NAME']) || !checkdnsrr($_SERVER['SERVER_NAME'], 'NS') )
$config = $json['local'];
else
$config = $json['remote'];
/* (3) Création des constantes */
define('__SERVER_HOST__', $config['host']);
define('__SERVER_ROOT__', $config['root']);
}
}
/* ACTIVE LE DEBUGGAGE (WARNING + EXCEPTION) /* ACTIVE LE DEBUGGAGE (WARNING + EXCEPTION)
* *
*/ */
@ -48,69 +22,23 @@
/* SECURE SHA1 ALGORITHM */ /* SECURE SHA1 ALGORITHM */
/*************************/ /*************************/
function secure_hash($data, $salt='">\[..|{@#))', $depth=1){ function secure_hash($data, $salt='">\[..|{@#))', $depth=1){
/* (1) On hash @depth fois /* (1) On hash @depth fois
---------------------------------------------------------*/ ---------------------------------------------------------*/
$hash = $data; $hash = $data;
$c = 0; $c = 0;
for( $h = 0 ; $h < $depth ; $h++ ){ for( $h = 0 ; $h < $depth ; $h++ ){
$hash = hash('sha512', $salt.hash('sha512', $hash.'_)Q@#((%*_$%(@#') ); $hash = hash('sha512', $salt.hash('sha512', $hash.'_)Q@#((%*_$%(@#') );
$c++; $c++;
}
/* (2) On renvoie le résultat
---------------------------------------------------------*/
return $hash;
} }
/* (2) On renvoie le résultat
---------------------------------------------------------*/
return $hash;
/* AUTOLOADER
*
* @className<String> Nom de la classe appelee
*
*/
function autoloader($className){
/* [1] Basic processing
=========================================================*/
/* (1) Explode classname by namespaces */
$path = explode('\\', $className);
/* (2) Check if at least a filename */
if( count($path) < 1 )
throw new \Exception('Missing classname for autoloader.');
/* (3) Detect if build class or lib class */
$type = $path[0] === 'lib' ? 'lib' : 'build';
/* [2] Manage type and check file
=========================================================*/
/* (1) Build path according to type */
if( $type === 'lib' )
$file = __ROOT__.'/'.implode('/', $path).'.php';
else
$file = __BUILD__.'/'.implode('/', $path).'.php';
/* (2) Check file */
if( file_exists($file) )
require_once $file;
} }
// // On definit l'autoloader comme autoloader (obvious)
// spl_autoload_register('autoloader', false, true);
\session_start();
/* On demarre la session securisee PHP
=========================================================*/
session_start();
// \manager\sessionManager::session_start();
?> ?>

View File

@ -232,17 +232,17 @@
/* (1) Si entrepot requis, mais manquant /* (1) Si entrepot requis, mais manquant
---------------------------------------------------------*/ ---------------------------------------------------------*/
if( in_array('warehouse', $expected) && self::auth() < 1 ) if( in_array('warehouse', $expected) && ( self::auth() < 1 || !isset($_SESSION['WAREHOUSE']['id']) ) )
return Err::PermissionError; return Err::PermissionError;
/* (2) Si admin requis, mais manquant /* (2) Si admin requis, mais manquant
---------------------------------------------------------*/ ---------------------------------------------------------*/
if( in_array('admin', $expected) && self::auth() != 2 ) if( in_array('admin', $expected) && ( self::auth() != 2 || !isset($_SESSION['ADMIN']['id']) ) )
return Err::PermissionError; return Err::PermissionError;
/* (3) Si SATS requis, mais manquant /* (3) Si SATS requis, mais manquant
---------------------------------------------------------*/ ---------------------------------------------------------*/
if( in_array('sats', $expected) && self::auth() < 3 ) if( in_array('sats', $expected) && ( self::auth() < 3 || !isset($_SESSION['SATS']['id']) ) )
return Err::TokenError; return Err::TokenError;
/* (4) On retire 'warehouse', 'admin' et 'sats' de @expected /* (4) On retire 'warehouse', 'admin' et 'sats' de @expected

96
build/api/core/Loader.php Normal file
View File

@ -0,0 +1,96 @@
<?php
namespace api\core;
use \error\core\Error;
use \error\core\Err;
use \http\core\HttpRequest;
use \api\core\Request;
class Loader{
/* (1) Build an API Request from the HTTP Request
*
* @uri<String> URI
*
* @return outName<outType> outDesc
*
---------------------------------------------------------*/
public static function remote($uri){
/* (1) Fetch HttpRequest correct data
---------------------------------------------------------*/
/* (1) Parse HttpRequest data because php doesn't parse it for non-POST HTTP method */
$httprequest = new HttpRequest();
/* (2) For later use -> replace default @_POST global */
$_POST = $httprequest->POST();
/* (3) Get @data from @_POST values */
$data = $_POST;
/* (2) Check if @path var is set
---------------------------------------------------------*/
/* (1) If is in @uri */
$pathInUrl = is_string($uri) && preg_match('#^/?([\w_-]+/[\w_-]+)(?:/?|/((?:\w+/)*(?:\w+/?)))$#', $uri, $uriMatches);
/* (2) Get @path from @uri + @uri arguments if there is */
if( $pathInUrl ){
// {1} Add @path as data //
$data['path'] = $uriMatches[1];
// {2} Add $uri arguments as data 'URL_@i' (@i is the order beginnint at 0) //
if( count($uriMatches) > 2 ){
$uriParams = explode('/', trim($uriMatches[2], '/'));
foreach($uriParams as $k=>$v)
$data["URL_$k"] = $v;
}
}
/* (3) If @path haven't been found -> error */
if( !isset($data['path']) )
return new Request();
/* (3) Parse arguments from JSON
---------------------------------------------------------*/
/* (1) Init. arguments */
$params = [];
/* (2) Parse each arg (except @path) */
foreach($data as $name=>$value){
if( $name === 'path' )
continue;
// {1} Json parse //
$json = json_decode( $value, true );
// {2} if valid -> set the parsed value //
if( !is_null($json) )
$params[$name] = $json;
// {3} else -> leave it like it was //
else
$params[$name] = $value;
}
/* (4) Build an API Request object
---------------------------------------------------------*/
return new Request($data['path'], $params);
}
}

View File

@ -6,7 +6,6 @@
use \api\core\ModuleFactory; use \api\core\ModuleFactory;
use \error\core\Error; use \error\core\Error;
use \error\core\Err; use \error\core\Err;
use \http\core\HttpRequest;
class Request{ class Request{
@ -335,88 +334,6 @@
} }
/* DESERIALISATION A PARTIR DE L'URL ET DES DONNEES POST (OPT)
*
* @url<String> Contenu de l'url formatté (commence à "/module/methode")
*
* @return instance<Request> Retourne un objet de type <Request>
*
* @note
* 1. `path` peut être dans l'url : /method/module
* `path` peut être dans les données $_POST
* 2. les données peuvent être dans l'url : /module/method/data1/data2/...
* les données peuvent être dans les données $_POST
*
*/
public static function remote($url){
/* [1] Fetch HttpRequest correct data
=========================================================*/
/* (1) Parse HttpRequest data because php doesn't parse it for non-POST HTTP method */
$httprequest = new HttpRequest();
$_POST = $httprequest->POST();
$data = $_POST;
/* [2] On verifie que le @path est renseigne
=========================================================*/
/* (1) Si le path est dans @url */
$pathInUrl = is_string($url) && preg_match('#^/?([\w_-]+/[\w_-]+)(?:/?|/((?:\w+/)*(?:\w+/?)))$#', $url, $urlMatches);
/* (2) On récupère le @path + les arguments dans l'URL */
if( $pathInUrl ){
// {1} On ajoute le @path aux données //
$data['path'] = $urlMatches[1];
// {2} On ajoute les arguments d'URL aux données //
if( count($urlMatches) > 2 ){
$urlParams = explode('/', trim($urlMatches[2], '/'));
foreach($urlParams as $k=>$v)
$data["URL_$k"] = $v;
}
}
/* (2) On vérifie dans tous les cas si le path existe */
if( !isset($data['path']) )
return new Request();
/* [3] On met les paramètres en JSON
=========================================================*/
/* (1) On initialise les paramètres*/
$params = [];
/* (2) On met tous les paramètres en json (sauf @path) */
foreach($data as $name=>$value){
if( $name === 'path' )
continue;
// {1} On met en JSON //
$json = json_decode( $value, true );
// {2} Si ok -> on remplace //
if( !is_null($json) )
$params[$name] = $json;
// {3} Sinon, on laisse tel quel //
else
$params[$name] = $value;
}
/* [4] On retourne une instance de <Request>
=========================================================*/
return new Request($data['path'], $params);
}
/* VERIFICATION DU FORMAT ET DE LA COHERENCE DU CHEMIN SPECIFIE /* VERIFICATION DU FORMAT ET DE LA COHERENCE DU CHEMIN SPECIFIE
* *
* @path<String> String correspondant au chemin de delegation ("module/methode") * @path<String> String correspondant au chemin de delegation ("module/methode")
@ -432,7 +349,7 @@
// On recupere les données de la regex // On recupere les données de la regex
$module = $matches[1]; $module = $matches[1];
$method = $this->http_method.'::'.$matches[2]; $method = $matches[2];
/* [2] Verification de l'existence du module (conf) /* [2] Verification de l'existence du module (conf)

View File

@ -0,0 +1,211 @@
<?php
namespace api\module;
use \database\core\Repo;
use \error\core\Error;
use \error\core\Err;
class adminDefault{
public function __construct(){
// Routine to execute before each call to authenticationDefault's method
}
public function __destruct(){
// Routine to execute after each call to authenticationDefault's method
}
/* RETOURNE LA LISTE DSE ADMINISTRATEURS DE L'ENTREPOT
*
* @return admins<array> Liste des administrateurs de l'entrepôt
*
*/
public function getAll($params){
/* (1) Fetch admin list
---------------------------------------------------------*/
/* (1) Prepare request */
$listRq = new Repo('admin/getByIdWarehouse', [ $_SESSION['WAREHOUSE']['id'] ]);
/* (2) Get response */
$listRs = $listRq->answer();
/* (3) Manage error */
if( !is_array($listRs) )
return ['error' => new Error(Err::RepoError)];
/* (2) Setup data (remove self)
---------------------------------------------------------*/
return ['admins' => $listRs];
}
/* MODIFICATION MOT DE PASSE ADMINISTRATEUR
*
* @old<String> Ancien mot de passe (actuel)
* @new<String> Nouveau mot de passe
* @confirm<String> Confirmation mot de passe
*
* @return status<Boolean> TRUE si les crédits sont bons, sinon FALSE
*
*/
public function update($params){
extract($params);
/* [1] On vérifie la confirmation de mot de passe
=========================================================*/
if( $new !== $confirm )
return [ 'error' => new Error(Err::WrongParam, 'confirm') ];
/* [2] On vérifie le mot de passe actuel
=========================================================*/
/* (1) On hash le mot de passe actuel */
$hash_old = secure_hash($old, $_SESSION['ADMIN']['username']);
/* (2) On vérifie que le mot de passe est correct */
$checkPassword = new Repo('admin/getById', [
$_SESSION['WAREHOUSE']['id'],
$_SESSION['ADMIN']['id']
]);
$adminFetched = $checkPassword->answer();
// Si aucun résultat -> erreur
if( $adminFetched === false )
return [ 'error' => new Error(Err::NoMatchFound) ];
/* [3] On vérifie le mot de passe actuel
=========================================================*/
// Si mot de passe faux, on retourne une erreur
if( $adminFetched['password'] != $hash_old )
return [ 'error' => new Error(Err::WrongParam, 'old') ];
/* [3] On met à jour le mot de passe
=========================================================*/
/* (1) On hash le nouveau mot de passe */
$hash_new = secure_hash($new, $adminFetched['username']);
/* (w) Requête */
$update = new Repo('admin/edit', [
$adminFetched['id_admin'],
$adminFetched['username'],
$adminFetched['mail'],
$hash_new
]);
/* (3) Gestion erreur */
if( !$update->answer() )
return [ 'error' => new Error(Err::RepoError) ];
/* (4) Succès si tout ok */
return [ 'error' => new Error(Err::Success) ];
}
/* CREATION D'UN NOUVEAL ADMINISTRATEUR
*
* @username<String> Identifiant du nouvel administrateur
*
* @return password<String> Mot de passe généré
*
*/
public function create($params){
extract($params);
/* [1] On génère un mot de passe
=========================================================*/
$password = secure_hash(uniqid(), uniqid());
/* [2] On vérifie l'unicité de l'identifiant
=========================================================*/
/* (1) On vérifie que l'identifiant n'existe pas */
$checkPassword = new Repo('admin/getByUsername', [
$_SESSION['WAREHOUSE']['id'],
$username
]);
$adminFetched = $checkPassword->answer();
// Si un résultat -> erreur
if( $adminFetched !== false )
return [ 'error' => new Error(Err::AlreadyExists, 'username') ];
/* [3] On crée l'administrateur
=========================================================*/
/* (1) Requête */
$create = new Repo('admin/create', [
$_SESSION['WAREHOUSE']['id'],
$username,
$mail,
$password
]);
/* (3) Gestion erreur */
if( !$create->answer() )
return [ 'error' => new Error(Err::RepoError) ];
/* (4) Succès si tout ok */
return [ 'password' => $password ];
}
/* SUPPRESSION D'UN ADMINISTRATEUR DU MEME ENTREPOT
*
* @id_admin<int> UID de l'administrateur
*
*/
public function delete($params){
extract($params);
/* [1] On vérifie que ce n'est pas nous-même
=========================================================*/
if( $id_admin == $_SESSION['ADMIN']['id'] )
return ['error' => new Error(Err::NoMatchFound) ];
/* [2] On essaie de supprimer
=========================================================*/
/* (1) On vérifie que l'identifiant n'existe pas */
$del_req = new Repo('admin/delete', [
$_SESSION['WAREHOUSE']['id'],
$id_admin
]);
/* (2) Gestion erreur */
if( !$del_req->answer() )
return [ 'error' => new Error(Err::RepoError) ];
/* (4) Succès si tout ok */
return [];
}
}
?>

View File

@ -5,15 +5,17 @@
use \api\core\Authentification; use \api\core\Authentification;
use \database\core\Repo; use \database\core\Repo;
use \manager\repo\cluster as clusterRepo; use \manager\repo\cluster as clusterRepo;
use \error\core\Error;
use \error\core\Err;
class authentificationDefault{ class authenticationDefault{
public function __construct(){ public function __construct(){
// Routine to execute before each call to authentificationDefault's method // Routine to execute before each call to authenticationDefault's method
} }
public function __destruct(){ public function __destruct(){
// Routine to execute after each call to authentificationDefault's method // Routine to execute after each call to authenticationDefault's method
} }
/* CONNEXION A UN ENTREPOT /* CONNEXION A UN ENTREPOT
@ -116,6 +118,74 @@
return [ 'status' => true ]; return [ 'status' => true ];
} }
/* MODIFICATION CODE D'ACCES ENTREPOT
*
* @old<String> Ancien code d'accès (actuel)
* @new<String> Nouveau code d'accès
* @confirm<String> Confirmation code d'accès
*
* @return status<Boolean> TRUE si les crédits sont bons, sinon FALSE
*
*/
public function update_warehouse($params){
extract($params);
/* [1] On vérifie la confirmation de code d'accès
=========================================================*/
if( $new !== $confirm )
return [ 'error' => new Error(Err::WrongParam, 'confirm') ];
/* [2] On vérifie le code d'accès actuel
=========================================================*/
/* (1) On hash le code d'accès actuel */
$hash_old = secure_hash($old, $_SESSION['WAREHOUSE']['name']);
/* (2) On vérifie que le code d'accès est correct */
$checkPassword = new Repo('warehouse/getById', [
$_SESSION['WAREHOUSE']['id']
]);
$warehouseFetched = $checkPassword->answer();
// Si aucun résultat -> erreur
if( $warehouseFetched === false )
return [ 'error' => new Error(Err::NoMatchFound) ];
/* [3] On vérifie le code d'accès actuel
=========================================================*/
// Si code d'accès faux, on retourne une erreur
if( $warehouseFetched['password'] != $hash_old )
return [ 'error' => new Error(Err::WrongParam, 'old') ];
/* [3] On met à jour le code d'accès
=========================================================*/
/* (1) On hash le nouveau code d'accès */
$hash_new = secure_hash($new, $warehouseFetched['name']);
/* (w) Requête */
$update = new Repo('warehouse/edit', [
$warehouseFetched['id_warehouse'],
$warehouseFetched['name'],
$hash_new
]);
/* (3) Gestion erreur */
if( !$update->answer() )
return [ 'error' => new Error(Err::RepoError) ];
/* (4) Succès si tout ok */
return [ 'error' => new Error(Err::Success) ];
}
} }

View File

@ -5,6 +5,7 @@
use \database\core\DatabaseDriver; use \database\core\DatabaseDriver;
use \manager\sessionManager; use \manager\sessionManager;
use \error\core\Error; use \error\core\Error;
use \error\core\Err;
use \database\core\Repo; use \database\core\Repo;
use \manager\repo\cluster as clusterRepo; use \manager\repo\cluster as clusterRepo;
@ -419,6 +420,82 @@
/* RETOURNE LA LISTE DES MODULE D'UN GROUPE DE MACHINES
*
* @id_machine_cluster<int> UID du groupe de machine
*
* @return modules<Array> Liste des modules autorisés pour le groupe de machines
*
*/
public static function getModules($params){
extract($params);
/* [1] On récupère les modules
=========================================================*/
/* (1) Récupération */
$mod_req = new Repo('module/getForMachineCluster', [
$_SESSION['WAREHOUSE']['id'],
$id_machine_cluster
]);
$answer = $mod_req->answer();
/* (2) Gestion erreur */
if( $answer === false )
return ['error' => new Error(Err::NoMatchFound)]; // no error
/* [3] On retourne la liste
=========================================================*/
return [ 'modules' => $answer ];
}
/* RETOURNE LES E-TREES D'UN GROUPE DE MACHINES
*
* @id_machine_cluster<int> UID du groupe de machine
*
* @return etrees<Array> E-trees du groupe de machines
*
*/
public static function getEtrees($params){
extract($params);
/* [1] On récupère les modules
=========================================================*/
/* (1) Récupération */
$mod_req = new Repo('etree/getForMachineCluster', [
$_SESSION['WAREHOUSE']['id'],
$id_machine_cluster
]);
$answer = $mod_req->answer();
/* (2) Gestion erreur */
if( $answer === false )
return ['error' => new Error(Err::NoMatchFound)]; // no error
/* [3] On retourne la liste
=========================================================*/
return [ 'etrees' => $answer ];
}
} }

View File

@ -0,0 +1,138 @@
<?php
namespace api\module;
use \database\core\DatabaseDriver;
use \manager\sessionManager;
use \error\core\Error;
use \error\core\Err;
use \database\core\Repo;
use \api\core\Request;
class deployDefault{
public function __construct(){}
public function __destruct(){}
/* [0] Dispatch pour envoyer les données d'une feature d'une machine
*
* @etree<String> Nom (complet) de l'e-tree
*
* @return data<mixed> Données à synchroniser à la machine
*
=========================================================*/
public function dispatch($params){
extract($params);
/* (1) On parse le nom complet
---------------------------------------------------------*/
$method_name = str_replace('-', '_', $etree);
/* (2) Gestion du dispatch
---------------------------------------------------------*/
/* (1) Formulation requête */
$request = new Request("deployDefault/$method_name", []);
/* (2) Gestion erreur */
if( $request->error->get() != Err::Success )
return ['error' => $request->error];
/* (3) Exécution */
$response = $request->dispatch();
/* (4) Gestion erreur */
if( $response->error->get() != Err::Success )
return ['error' => $response->error];
/* (5) Remontée du résultat */
return [
'data' => $response->get('data')
];
}
/* [1] Génération des données de fonctionnement de l'etree READ du module RFID
*
* @data<mixed> Données à traiter
*
* @return data<mixed> Données à synchroniser (permissions, etc)
*
=========================================================*/
public function rfid_read($params){
extract($params);
/* [1] On récupére la liste des actions
=========================================================*/
/* (1) On récupère les actions */
$actionsReq = new Repo('action/getAll');
$actions = ($actionsReq->error->get()==Err::Success) ? $actionsReq->answer() : [];
/* (2) On regroupe les actions par TIMEOUT */
$sorted_actions = [];
foreach($actions as $a=>$action){
/* (3) Si aucune valeur pour ce TIMEOUT, on crée un tableau vide */
if( !isset($sorted_actions[$action['timeout']]) )
$sorted_actions[$action['timeout']] = [];
/* (4) On ajoute l'action au TIMEOUT */
$sorted_actions[$action['timeout']][] = [
'id_action' => intval($action['id_action']),
'name' => strtolower($action['name']),
'required' => $action['required'],
'action' => $action['action']
];
}
/* [2] On récupère les utilisateurs + accès sur la machine
=========================================================*/
/* (1) On récupère les utilisateurs et leurs permissions */
$permissionsReq = new Repo('action_merge/getAccess', [
$_SESSION['WAREHOUSE']['id'],
$_SESSION['SATS']['id']
]);
$permissions = ($permissionsReq->error->get()==Err::Success) ? $permissionsReq->answer() : [];
/* (2) Pour formatte et indexe les permissions par CODE RFID */
$indexed_permissions = [];
foreach($permissions as $p=>$permission){
$actionList = explode(',', $permission['id_action']);
foreach($actionList as $a=>$action)
$actionList[$a] = intval($action);
sort($actionList);
$indexed_permissions[$permission['code']] = [
'id_user' => intval($permission['id_user']),
'actions' => $actionList
];
}
/* (3) Retourne les données récupérées */
return [ 'data' => [
'actions' => $sorted_actions,
'permissions' => $indexed_permissions
] ];
}
}
?>

View File

@ -5,7 +5,7 @@
use \error\core\Err; use \error\core\Err;
use \manager\ResourceDispatcher; use \manager\ResourceDispatcher;
class module{ class documentationDefault{
public function __construct(){} public function __construct(){}
public function __destruct(){} public function __destruct(){}
@ -87,7 +87,7 @@
/* [0] Récupération de la configuration /* [0] Récupération de la configuration
=========================================================*/ =========================================================*/
// On récupère le fichier et on le parse // On récupère le fichier et on le parse
$modules = json_decode( file_get_contents(__ROOT__/'/config/modules.json'), true ); $modules = json_decode( file_get_contents(__CONFIG__.'/modules.json'), true );
// Gestion de l'erreur de parsage // Gestion de l'erreur de parsage
if( $modules == null ) if( $modules == null )
@ -185,8 +185,9 @@
/* (1) Description */ /* (1) Description */
$content .= "### $methName [POST /$module/$methName]\n\n"; $content .= "### $methName [POST /$module/$methName]\n\n";
$content .= $method['description']."\n"; $content .= $method['description']."\n";
if( count($method['permissions']) > 0) if( count($method['permissions']) > 0 )
$content .= '> Permissions `'.implode('``', $method['permissions'])."`\n\n"; foreach($method['permissions'] as $perm_set)
$content .= '> Permissions `'.implode('``', $perm_set)."`\n\n";
// Liste des paramètres // Liste des paramètres
if( isset($method['parameters']) && count($method['parameters']) > 0 ){ if( isset($method['parameters']) && count($method['parameters']) > 0 ){
@ -194,7 +195,7 @@
$content .= "+ Parameters\n\n"; $content .= "+ Parameters\n\n";
foreach($method['parameters'] as $argName=>$argument){ foreach($method['parameters'] as $argName=>$argument){
$optional = isset($argument['optional']) && $argument['optional'] === true; $optional = isset($argument['optional']) && $argument['optional'] === true;
$content .= " + $argName (${argument['type']}, ".( $optional ? 'optional' : 'required' ).") - ${argument['description']}\n"; $content .= " + $argName (".$argument['type'].", ".( $optional ? 'optional' : 'required' ).") - ".(isset($argument['description']) ? $argument['description'] : 'none')."\n";
} }
$content .= "\n"; $content .= "\n";
} }
@ -252,7 +253,7 @@
// On explicite tous les paramètres // On explicite tous les paramètres
$content .= " + Attributes (object)\n\n"; $content .= " + Attributes (object)\n\n";
foreach($method['output'] as $outName=>$outData) foreach($method['output'] as $outName=>$outData)
$content .= " + $outName (${outData['type']}) - ${outData['description']}\n"; $content .= " + $outName (".$outData['type'].") - ".(isset($outData['description']) ? $outData['description'] : 'none')."\n";
} }
$content .= "\n\n"; $content .= "\n\n";

View File

@ -0,0 +1,172 @@
<?php
namespace api\module;
use \database\core\DatabaseDriver;
use \manager\sessionManager;
use \error\core\Error;
use \error\core\Err;
use \database\core\Repo;
use \api\core\Request;
class fetchDefault{
public function __construct(){}
public function __destruct(){}
/* [0] Dispatch des données d'une feature d'une machine
*
* @etree<String> Nom (complet) de l'e-tree
* @data<mixed> Données à traiter
*
* @return saved<numeric> Code de réception (nombre d'entrées ou autre)
*
=========================================================*/
public function dispatch($params){
extract($params);
/* (1) On parse le nom complet
---------------------------------------------------------*/
/* (1) Requête */
$etree_parse_req = new Repo('etree/parse', [$etree]);
/* (2) On récupère la réponse */
$etree_data = $etree_parse_req->answer();
/* (3) Gestion erreur */
if( $etree_data === false )
return ['error' => new Error(Err::FormatError)];
/* (4) On calcule le nom de la méthode */
$method_name = $etree_data['module_name'].'_'.$etree_data['etree_name'];
/* (2) Gestion du dispatch
---------------------------------------------------------*/
/* (1) Formulation requête */
$request = new Request("fetchDefault/$method_name", [
'data' => $data
]);
/* (2) Gestion erreur */
if( $request->error->get() != Err::Success )
return ['saved' => -$request->error->get()];
/* (3) Exécution */
$response = $request->dispatch();
/* (4) Gestion erreur */
if( $response->error->get() != Err::Success )
return [ 'saved' => -$response->error->get() ];
/* (5) Remontée du résultat */
return [
'saved' => $response->get('saved')
];
}
/* [1] Gestion des données historiques de l'etree READ du module RFID
*
* @data<mixed> Données à traiter
*
* @return saved<numeric> Nombre de lignes ajoutées
*
=========================================================*/
public function rfid_read($params){
extract($params);
/* (1) Initialisation du compteur de lignes enregistrées */
$count = 0;
/* (2) Create history entry in db */
foreach($data as $entry){
// {1} Build request to store each entry //
$log_req = new Request('historyDefault/create', [
'timestamp' => $entry[0],
'id_user' => $entry[1],
'id_action' => $entry[2],
'id_machine' => $_SESSION['SATS']['id']
]);
// {2} Process + get response //
$log_res = $log_req->dispatch();
// {3} Ignore failure //
// if( $log_res->error->get() != Err::Success )
// continue;
// {4} Register count if success //
$count++;
}
/* (3) Retourne le nombre d'entrées enregistrées */
return [ 'saved' => $count ];
}
/* [2] Gestion des données historiques de l'etree SIMPLE du module MOTHEURE
*
* @data<mixed> Données à traiter
*
* @return saved<numeric> Nombre de lignes ajoutées
*
=========================================================*/
public function motheure_simple($params){
extract($params);
/* (1) Initialize data
---------------------------------------------------------*/
/* (1) Initialisation du compteur de lignes enregistrées */
$count = 0;
/* (2) Calcl the total to add */
$total = 0;
foreach($data as $entry){
// Only if positive numeric
if( isset($entry[0]) && is_numeric($entry[0]) && $entry[0] > 0 )
$total += intval($entry[0]);
$count++;
}
/* (2) Update the table in the database
---------------------------------------------------------*/
/* (1) Build request to store each entry */
$upd_req = new Request('motheure/increment', [
'count' => $total
]);
/* (2) Process + get response */
$upd_res = $upd_req->dispatch();
/* (3) Manage error */
if( $upd_res->error->get() != Err::Success )
return ['error' => $upd_res->error];
/* (4) Retourne le nombre d'entrées enregistrées */
return [ 'saved' => $count ];
}
}
?>

View File

@ -150,6 +150,88 @@
]; ];
} }
/* (x) Return the machine history for an history entry
*
* @id_entry<id> UID of the history entry
*
* @return timeline<array> Machine timeline data
*
---------------------------------------------------------*/
public function get_timeline($params){
extract($params);
/* (1) Get history entry data
---------------------------------------------------------*/
/* (1) Request */
$entry = new Repo('history/getById', [$id_entry]);
/* (2) Get response */
$entry = $entry->answer();
/* (3) Manage error */
if( !is_array($entry) )
return ['error' => new Error(Err::RepoError)];
/* (2) Get history for machine
---------------------------------------------------------*/
/* (1) Request */
$timeline = new Repo('history/getByIdMachine', [
$_SESSION['WAREHOUSE']['id'],
$entry['id_machine']
]);
/* (2) Get response */
$timeline = $timeline->answer();
/* (3) Manage error */
if( $timeline === false )
return ['error' => new Error(Err::RepoError)];
/* (3) Return data
---------------------------------------------------------*/
return [ 'timeline' => $timeline ];
}
/* (x) Return the entry data for an history id
*
* @id_entry<id> UID of the history entry
*
* @return data<array> Entry data
*
---------------------------------------------------------*/
public function getById($params){
extract($params);
/* (1) Get history entry data
---------------------------------------------------------*/
/* (1) Request */
$entry = new Repo('history/getById', [$id_entry]);
/* (2) Get response */
$entry = $entry->answer();
/* (3) Manage error */
if( !is_array($entry) )
return ['error' => new Error(Err::RepoError)];
/* (2) Return data
---------------------------------------------------------*/
return [ 'entry' => $entry ];
}
} }

View File

@ -383,7 +383,7 @@
/* [3] Get history for the machine /* [3] Get history for the machine
=========================================================*/ =========================================================*/
/* (1) Write request */ /* (1) Write request */
$history_req = new Repo('history/getByIdMachine', [$id_machine]); $history_req = new Repo('history/getByIdMachine', [$_SESSION['WAREHOUSE']['id'], $id_machine]);
/* (2) Manage error */ /* (2) Manage error */
if( $history_req->error->get() != Err::Success ) if( $history_req->error->get() != Err::Success )
@ -461,109 +461,140 @@
*/ */
private static function getMachineWorkingInformation($id_machine){ private static function getMachineWorkingInformation($id_machine){
/* [1] On récupére la liste des actions
=========================================================*/ /* [1] On envoie les e-tree de la machine
$actionsReq = new Repo('action/getAll'); =========================================================*/ {
$actions = ($actionsReq->error->get()==Err::Success) ? $actionsReq->answer() : [];
// var_dump($actionsReq->answer()); $etrees = [];
/* (1) On essaie de récupérer les etree de la machine*/
$mc_req = new Request('machineDefault/getClusters', ['id_machine' => $id_machine]);
$mc_res = $mc_req->dispatch();
/* (2) Si on arrive à récupérer les clusters */
if( $mc_res->error->get() == Err::Success ){
/* (3) Pour chaque cluster, on récupère les e-trees */
foreach($mc_res->get('clusters') as $cluster){
/* (4) On les e-trees du cluster */
$etree_req = new Request('clusterDefault/getEtrees', [
'id_machine_cluster' => $cluster['id_machine_cluster']
]);
$etree_res = $etree_req->dispatch();
/* (5) Si erreur, on passe */
if( $etree_res->error->get() != Err::Success )
continue;
/* (6) Sinon -> On entregistre les e-trees */
foreach($etree_res->get('etrees') as $etree){
$etree_name = $etree['name'].'-'.$etree['daemon'];
/* (7) Si pas déja entregistré -> on l'ajoute */
if( !in_array($etree_name, $etrees) )
$etrees[] = $etree_name;
}
/* [2] On regroupe les actions par TIMEOUT }
=========================================================*/
$sorted_actions = [];
foreach($actions as $a=>$action){
/* (1) Si aucune valeur pour ce TIMEOUT, on crée un tableau vide */
if( !isset($sorted_actions[$action['timeout']]) )
$sorted_actions[$action['timeout']] = [];
/* (2) On ajoute l'action au TIMEOUT */
$sorted_actions[$action['timeout']][] = [
'id_action' => intval($action['id_action']),
'name' => strtolower($action['name']),
'previous' => $action['previous'],
'action' => $action['action']
];
}
/* [3] On récupère la liste des états
=========================================================*/
$globalStatesReq = new Repo('global_state/getAll');
$globalStates = ($globalStatesReq->error->get()==Err::Success) ? $globalStatesReq->answer() : [];
/* [4] On récupère la liste des MODULES (puces)
=========================================================*/
$chipsReq = new Repo('chip/getAll', [$_SESSION['WAREHOUSE']['id']]);
$chips = ($chipsReq->error->get()==Err::Success) ? $chipsReq->answer() : [];
foreach($chips as $c=>$chip){
/* [5] On récupére la liste des PINS de chaque PUCE
=========================================================*/
$pinsReq = new Repo('pin_merge/getByIdChip', [$chip['id_chip']]);
$pins = ($pinsReq->error->get()==Err::Success) ? $pinsReq->answer() : [];
$chips[$c]['pins'] = [];
foreach($pins as $p=>$pin)
$chips[$c]['pins'][$p] = intval($pin['pin']);
/* [6] On récupère valeurs pour chaque état de chaque PUCE
=========================================================*/
$chips[$c]['states'] = [];
$statesReq = new Repo('state/getForChip', [$chip['id_chip']]);
$states = ($statesReq->error->get()==Err::Success) ? $statesReq->answer() : [];
// On met en forme les données : "val1,val2,val3" -> [val1, val2, val3]
foreach($states as $s=>$state){
$chips[$c]['states'][$state['state']] = explode(',', $state['pin_values']);
foreach($chips[$c]['states'][$state['state']] as $s2=>$state2)
$chips[$c]['states'][$state['state']][$s2] = intval($state2);
} }
} }
/* [5] On récupère les utilisateurs + accès sur la machine
=========================================================*/
/* (1) On récupère les utilisateurs et leurs permissions */
$permissionsReq = new Repo('action_merge/getAccess', [
$_SESSION['WAREHOUSE']['id'],
$id_machine
]);
$permissions = ($permissionsReq->error->get()==Err::Success) ? $permissionsReq->answer() : [];
/* (2) Pour formatte et indexe les permissions par CODE RFID */
$indexed_permissions = [];
foreach($permissions as $p=>$permission){ /* [2] On récupère les données globales
$actionList = explode(',', $permission['id_action']); =========================================================*/ {
foreach($actionList as $a=>$action) /* (1) On récupère la liste des états
$actionList[$a] = intval($action); ---------------------------------------------------------*/ {
sort($actionList); $globalStatesReq = new Repo('global_state/getAll');
$globalStates = ($globalStatesReq->error->get()==Err::Success) ? $globalStatesReq->answer() : [];
}
/* (2) On récupère la liste des composants (chip)
---------------------------------------------------------*/ {
/* (1) On récupère les composants disponibles */
$chipsReq = new Repo('chip/getForMachine', [$_SESSION['WAREHOUSE']['id'], $id_machine]);
$chips = ($chipsReq->error->get()==Err::Success) ? $chipsReq->answer() : [];
foreach($chips as &$chip){
/* (2) On récupére la liste des PINS de chaque COMPOSANT */
$chip['pins'] = explode(',', $chip['pins']);
if( !is_array($chip['pins']) )
$chip['pins'] = [];
/* (3) On récupère valeurs pour chaque état de chaque COMPOSANT */
$chip['states'] = [];
$statesReq = new Repo('state/getForChip', [$chip['id_chip']]);
$states = ($statesReq->error->get()==Err::Success) ? $statesReq->answer() : [];
/* (4) On met en forme les données : "val1,val2,val3" -> [val1, val2, val3] */
foreach($states as $s=>$state){
$chip['states'][$state['state']] = explode(',', $state['value']);
foreach($chip['states'][$state['state']] as $s2=>$state2)
$chip['states'][$state['state']][$s2] = intval($state2);
}
}
}
$indexed_permissions[$permission['code']] = [
'id_user' => intval($permission['id_user']),
'actions' => $actionList
];
} }
/* [3] On récupère les données de chaque feature
=========================================================*/
$features = [];
/* (1) Pour chaque etree/feature */
foreach($etrees as $etree_name){
$features[$etree_name] = [];
/* (2) On lance le dispatch */
$dispatch_feat_req = new Request('deployDefault/dispatch', [
'etree' => $etree_name
]);
/* (3) Exécution + récupération réponse */
$dispatch_feat_res = $dispatch_feat_req->dispatch();
/* (4) Gestion erreur */
if( $dispatch_feat_res->error->get() != Err::Success )
$features[$etree_name]['err'] = $dispatch_feat_res->error->get();
/* (5) Enregistrement des données */
$features[$etree_name] = $dispatch_feat_res->get('data');
}
/* [N] Retourne les données /* [N] Retourne les données
=========================================================*/ =========================================================*/
return [ return [
'actions' => $sorted_actions, 'etrees' => $etrees,
'states' => $globalStates, 'feature' => $features,
'chips' => $chips, 'chips' => $chips,
'permissions' => $indexed_permissions 'states' => $globalStates
]; ];
} }
@ -639,57 +670,46 @@
/* [1] Initialisation des variables /* [1] Initialisation des variables
=========================================================*/ =========================================================*/
$fetched = [ $fetched = []; // count of registered logs for each feature
'history' => 0, // count of registered logs
'feature' => [], // count of registered logs for each feature
'identity' => [ // network identity
'ap' => isset($data['identity']) && is_array($data['identity']) && isset($data['identity']['ap']) ? $data['identity']['ap'] : null,
'ip' => isset($data['identity']) && is_array($data['identity']) && isset($data['identity']['ip']) ? $data['identity']['ip'] : null
]
];
/* [2] Gestion des données reçues /* [2] Gestion des données reçues
=========================================================*/ =========================================================*/
/* (1) For each history entry */ /* (1) For each feature data */
if( isset($data['default']) && is_array($data['default']) ){ if( isset($data['feature']) && is_array($data['feature']) ){
/* (2) Create history entry in db */ /* (2) Create history entry in db */
foreach($data['default'] as $entry){ foreach($data['feature'] as $etree_name=>$feat_data){
// {1} Build request // // {1} Use fetchDefault to dispatch the request //
$log_req = new Request('historyDefault/create', [ $dispatch_feat_req = new Request('fetchDefault/dispatch', [
'timestamp' => $entry[0], 'etree' => $etree_name,
'id_user' => $entry[1], 'data' => $feat_data
'id_action' => $entry[2],
'id_machine' => $_SESSION['SATS']['id']
]); ]);
// {2} Process + get response // // {2} Process + get response //
$log_res = $log_req->dispatch(); $dispatch_feat_res = $dispatch_feat_req->dispatch();
// {3} Exit on failure // // {3} Exit on failure //
if( $log_res->error->get() != Err::Success ) if( $dispatch_feat_res->error->get() != Err::Success )
break; continue;
// {4} Register count if success // // {4} Register saved code (returned from dispatcher) //
$fetched['history']++; $fetched[$etree_name] = $dispatch_feat_res->get('saved');
} }
} }
/* (2) For each feature's entry */ /* (2) Mise à jour de l'identité de la machine (ap-ip) */
// TODO: Manage feature's entries
/* (3) Mise à jour de l'identité de la machine (ap-ip) */
$updateNetId = new Repo('machine/updateNetworkIdentity', [ $updateNetId = new Repo('machine/updateNetworkIdentity', [
$_SESSION['WAREHOUSE']['id'], $_SESSION['WAREHOUSE']['id'],
$_SESSION['SATS']['id'], $_SESSION['SATS']['id'],
$fetched['identity']['ap'], isset($data['identity']) && is_array($data['identity']) && isset($data['identity']['ap']) ? $data['identity']['ap'] : null,
$fetched['identity']['ip'] isset($data['identity']) && is_array($data['identity']) && isset($data['identity']['ip']) ? $data['identity']['ip'] : null,
]); ]);
/* (2) On gère l'erreur */ /* (3) Gestion erreur */
if( $updateNetId->error->get() != Err::Success || !$updateNetId->answer() ) if( $updateNetId->error->get() != Err::Success || !$updateNetId->answer() )
return [ 'error' => new Error(Err::RepoError) ]; return [ 'error' => new Error(Err::RepoError) ];
@ -704,7 +724,7 @@
/* [4] Envoi des données /* [4] Envoi des données
=========================================================*/ =========================================================*/
return array_merge($basis_update, ['saved' => $fetched, 'id' => $fetched['identity']]); return array_merge($basis_update, ['saved' => $fetched]);
} }

View File

@ -0,0 +1,142 @@
<?php
namespace api\module;
use \database\core\DatabaseDriver;
use \manager\sessionManager;
use \error\core\Error;
use \error\core\Err;
use \database\core\Repo;
use \api\core\Request;
use \orm\core\Rows;
use \orm\core\Table;
class motheure{
public function __construct(){}
public function __destruct(){}
/* (1) RETURNS THE TOTAL COUNT FOR A MACHINE
*
* @id_machine<id> Identifiant de la machine
*
* @return count<int> Retourne le compte horaire
*
---------------------------------------------------------*/
public function getCount($params){
extract($params);
/* (1) Check if machine have motheure etree activated
---------------------------------------------------------*/
$mod = Table::get('module')
->whereName('motheure');
$etree = Table::get('etree')
->whereDaemon('simple')
->join('id_module', $mod);
$mc = Table::get('module_merge')
->join('id_etree', $etree);
$m = Table::get('machine')
->select('id_machine')
->whereId($id_machine);
$mc_m = Table::get('machine_cluster_merge')
->join('id_machine', $m)
->join('id_machine_cluster', $mc);
/* (1) If not the etree -> exit */
if( count($mc_m->fetch()) == 0 )
return ['error' => new Error(Err::NoMatchFound)];
/* (2) Get the motor count
---------------------------------------------------------*/
/* (1) Fetch count */
$count = Table::get('motheure')
->unique()
->select('count')
->whereIdMachine($id_machine)
->fetch();
/* (2) If no result -> return 0 */
if( !is_array($count) || !isset($count['count']) )
return ['count' => 0];
/* (3) Else -> return the count */
return [ 'count' => $count['count'] ];
}
/* (2) Increment the motor count
*
* @count<int> Count to add to motor count of the machine
*
---------------------------------------------------------*/
public function increment($params){
extract($params);
/* (1) Check if entry exists
---------------------------------------------------------*/
/* (1) Check if there is an entry for the current machine */
$fetched = Table::get('motheure')
->unique()
->select('id_motheure')
->select('id_machine')
->select('count')
->whereIdMachine($_SESSION['SATS']['id'])
->fetch();
/* (2) Set variable to ease process */
$already_exists = is_array($fetched);
/* (2) If does not exist, create entry
---------------------------------------------------------*/
if( !$already_exists ){
/* (1) Insert new entry */
$inserted = Table::get('motheure')
->insert([
'id_motheure' => Rows::INSERT_DEFAULT,
'id_machine' => $_SESSION['SATS']['id'],
'count' => $count
]);
/* (2) Propagate error */
return [ 'error' => ($inserted) ? new Error(Err::Success) : new Error(Err::RepoError) ];
/* (3) If already exists, update entry
---------------------------------------------------------*/
}else{
/* (1) Update entry */
$updated = Table::get('motheure')
->whereIdMachine($_SESSION['SATS']['id'])
->edit([ 'count' => $count + $fetched['count'] ]);
/* (2) Propagate error */
return [ 'error' => ($updated) ? new Error(Err::Success) : new Error(Err::RepoError) ];
}
/* (x) Default error */
return [ 'error' => new Error(Err::Success) ];
}
}
?>

View File

@ -12,6 +12,7 @@
/* CREATION D'UN ADMINISTRATEUR /* CREATION D'UN ADMINISTRATEUR
* *
* @id_warehouse<int> UID de l'entrepôt
* @username<String> Identifiant de l'administrateur * @username<String> Identifiant de l'administrateur
* @mail<String> Adresse mail de l'administrateur * @mail<String> Adresse mail de l'administrateur
* @password<String> Mot de passe de l'administrateur * @password<String> Mot de passe de l'administrateur
@ -20,16 +21,17 @@
* Renvoie FALSE si une erreur occure * Renvoie FALSE si une erreur occure
* *
*/ */
public static function create($username, $mail, $password){ public static function create($id_warehouse, $username, $mail, $password){
/* [1] Création de l'administrateur /* [1] Création de l'administrateur
=========================================================*/ =========================================================*/
$inserted = Table::get('admin') $inserted = Table::get('admin')
->insert([ ->insert([
'id_admin' => Rows::INSERT_DEFAULT, 'id_admin' => Rows::INSERT_DEFAULT,
'username' => $username, 'id_warehouse' => $id_warehouse,
'mail' => $mail, 'username' => $username,
'password' => sessionManager::secure_hash( $password ), 'mail' => $mail,
'token' => sessionManager::secure_hash( uniqid() ) 'password' => \secure_hash( $password, $username ),
'token' => \secure_hash( uniqid(), $username.'-*-'.$mail )
]); ]);
// Si username ou mail déja pris // Si username ou mail déja pris
@ -39,7 +41,7 @@
/* [2] On retourne l'id_admin ou FALSE si erreur /* [2] On retourne l'id_admin ou FALSE si erreur
=========================================================*/ =========================================================*/
$check_admin = self::getByUsername($username); $check_admin = self::getByUsername($id_warehouse, $username);
// Si n'existe pas on retourne FALSE // Si n'existe pas on retourne FALSE
if( $check_admin === false ) if( $check_admin === false )
@ -49,8 +51,6 @@
return $check_admin['id_admin']; return $check_admin['id_admin'];
} }
@ -131,15 +131,17 @@
/* SUPPRIME UN ENTREPOT DONNE /* SUPPRIME UN ENTREPOT DONNE
* *
* @id_admin<int> UID de l'administrateur en question * @id_warehouse<int> UID de l'entrepôt en question
* @id_admin<int> UID de l'administrateur en question
* *
* @return status<Boolean> Retourne si oui ou non l'administrateur a bien ete supprime * @return status<Boolean> Retourne si oui ou non l'administrateur a bien ete supprime
* *
*/ */
public static function delete($id_admin){ public static function delete($id_warehouse, $id_admin){
/* [1] On redige/execute la requete /* [1] On redige/execute la requete
=========================================================*/ =========================================================*/
$deleted = Table::get('admin') $deleted = Table::get('admin')
->whereIdWarehouse($id_warehouse)
->whereId($id_admin) ->whereId($id_admin)
->delete(); ->delete();

View File

@ -11,27 +11,68 @@
protected static function table_name(){ static $table_name = 'chip'; return $table_name; } protected static function table_name(){ static $table_name = 'chip'; return $table_name; }
/* RENVOIE LA LISTE DES CARTES/PUCES DISPONIBLES EN FONCTION DES MODULES DE L'ENTREPOT /* RENVOIE LA LISTE DES CARTES/PUCES DISPONIBLES EN FONCTION DES MODULES DU GROUPE DE MACHINE
*
* @id_warehouse<int> UID de l'entrepot
* @id_machine<int> UID de la machine
* *
* @return chips<Array> Liste des puces/cartes disponibles * @return chips<Array> Liste des puces/cartes disponibles
* *
*/ */
public static function getAll($id_warehouse){ public static function getForMachine($id_warehouse, $id_machine){
/* [1] On récupère les modules de l'entrepot courant
=========================================================*/ /* (1) On récupère les groupes de la machine
$module_merge = Table::get('module_merge') ---------------------------------------------------------*/
->whereIdWarehouse(7); $get_clus = new Repo('machine/getClusters', [$id_warehouse, $id_machine]);
$clusters = $get_clus->answer();
if( $clusters === false )
return [];
$chip = Table::get('chip') /* (2) On récupère les modules associés aux clusters
->join('id_module', $module_merge) ---------------------------------------------------------*/
->select('*'); $module_ids = [];
foreach($clusters as $cluster){
$get_mods = new Repo('module/getForMachineCluster', [$id_warehouse, $cluster['id_machine_cluster']]);
$mods = $get_mods->answer();
foreach($mods as $module){
// si pas déja -> on ajoute l'id module à la liste
if( !in_array($module['id_module'], $module_ids) )
$module_ids[] = $module['id_module'];
}
}
/* (3) On récupère la liste des CHIPS (associés aux modules)
---------------------------------------------------------*/
$chips = [];
foreach($module_ids as $module_id){
$chip_req = Table::get('chip')
->select('*')
->whereIdModule($module_id);
$chip_fetched = $chip_req->fetch();
foreach($chip_fetched as $chip)
$chips[] = $chip;
}
/* [2] On retourne le résultat /* [2] On retourne le résultat
=========================================================*/ =========================================================*/
return $chip->fetch(); return $chips;
} }
} }

View File

@ -0,0 +1,110 @@
<?php
namespace database\repo;
use \database\core\DatabaseDriver;
use \error\core\Err;
use \database\core\Repo;
use \orm\core\Table;
use \orm\core\Rows;
class etree extends parentRepo{
protected static function table_name(){ static $table_name = 'etree'; return $table_name; }
/* [1] Fetch all etrees for the given machine_cluster
*
* @id_warehouse<int> UID of the given warehouse
* @id_machine_cluster<int> UID of the given machine_cluster
*
* @return etrees<Array> The list of etrees
* FALSE on error
*
=========================================================*/
public static function getForMachineCluster($id_warehouse, $id_machine_cluster){
/* (1) On récupère le ETREE de la machine
---------------------------------------------------------*/
$module = Table::get('module')
->select('id_module')
->select('name');
$etree = Table::get('etree')
->select('id_etree')
->select('daemon')
->join('id_module', $module);
$merge = Table::get('module_merge')
->join('id_etree', $etree)
->whereIdWarehouse($id_warehouse)
->whereIdMachineCluster($id_machine_cluster);
return $merge->fetch();
}
/* [2] Parses an e-tree full name (mod_name-etree_name)
*
* @full_name<String> Full name to parse
*
* @return info<Array> The useful data (id_module, id_etree)
* FALSE on error
*
=========================================================*/
public static function parse($full_name){
/* (1) On vérifie le format (permet l'extraction des données) */
if( !preg_match('@^(.+)-(.+)$@', $full_name, $matches) )
return false;
/* (2) On recherche le module */
$module = Table::get('module')
->select('id_module')
->select('name')
->unique()
->whereName($matches[1])
->fetch();
/* (3) Si on ne trouve pas de module -> error */
if( !is_array($module) || !isset($module['id_module']) )
return false;
/* (5) On cherche l'e-tree */
$etree = Table::get('etree')
->select('id_etree')
->select('daemon')
->whereIdModule($module['id_module'])
->whereDaemon($matches[2])
->unique()
->fetch();
/* (6) Si erreur */
if( !is_array($etree) || !isset($etree['id_etree']) )
return false;
/* (7) Si tout ok, on retourne les données */
return [
'id_module' => $module['id_module'],
'module_name' => $module['name'],
'id_etree' => $etree['id_etree'],
'etree_name' => $etree['daemon']
];
}
}
?>

View File

@ -88,15 +88,37 @@
* FALSE si aucun résultat * FALSE si aucun résultat
* *
*/ */
public static function getByIdMachine($id_machine){ public static function getByIdMachine($id_warehouse, $id_machine){
/* [1] On rédige/execute la requête /* [1] On rédige/execute la requête
=========================================================*/ =========================================================*/
$machine = Table::get('history') $users = Table::get('user')
->whereIdMachine($id_machine) ->whereIdWarehouse($id_warehouse)
->orderby('timestamp', Rows::ORDER_DESC) ->select('id_user')
->select('*'); ->select('username', null, null, 'user_name')
->select('firstname', null, null, 'user_firstname')
->select('lastname', null, null, 'user_lastname');
return $machine->fetch(); $machines = Table::get('machine')
->whereIdWarehouse($id_warehouse)
->whereId($id_machine)
->select('id_machine')
->select('name', null, null, 'machine_name');
$actions = Table::get('action')
->select('id_action')
->select('name', null, null, 'action_name');
$history = Table::get('history')
->join('id_user', $users)
->join('id_machine', $machines)
->join('id_action', $actions)
->select('id_history')
->select('timestamp')
->orderby('timestamp', Rows::ORDER_DESC);
return $history->fetch();
} }
@ -134,21 +156,23 @@
/* RETOURNE UNE ENTREE SPECIFIQUE /* RETOURNE UNE ENTREE SPECIFIQUE
* *
* @id_history<int> UID de l'entree * @id_entry<int> UID de l'entrée historique
* *
* @return entry<Array> Données de l'entree * @return entry<Array> Données de l'entree
* FALSE si aucun résultat * FALSE si erreur | aucun résultat
* *
*/ */
public static function getById($id_history){ public static function getById($id_entry){
/* [1] On rédige/execute la requête /* [1] On rédige/execute la requête
=========================================================*/ =========================================================*/
$user = Table::get('user') $entry = Table::get('history')
->whereId($id_history) ->whereId($id_entry)
->orderby('timestamp', Rows::ORDER_DESC) ->orderby('timestamp', Rows::ORDER_DESC)
->select('*'); ->select('*')
->unique();
return $entry->fetch();
return $user->fetch();
} }
@ -211,34 +235,60 @@
/* [1] Recherche dans les relations 'machines' /* [1] Recherche dans les relations 'machines'
=========================================================*/ =========================================================*/
/* (1) On exécute la requête */ /* (1) On exécute la requête */
$machines_r = new Repo('machine/search', [$id_warehouse, $keyword]); $machines_rq = new Repo('machine/search', [$id_warehouse, $keyword]);
$machines_rs = $machines_rq->answer();
/* (2) Gestion succès */ /* (2) Gestion succès */
if( $machines_r->error->get() == Err::Success ) if( is_array($machines_rs) )
foreach($machines_r->answer() as $row) foreach($machines_rs as $row)
$machine_ids[] = $row['id_machine']; $machine_ids[] = $row['id_machine'];
/* [2] Recherche dans les relations 'users' /* [2] Recherche dans les relations 'users'
=========================================================*/ =========================================================*/
/* (1) On cherche dans les utilisateurs */ /* (1) On cherche dans les utilisateurs */
$users_r = new Repo('user/search', [$id_warehouse, $keyword]); $users_rq = new Repo('user/search', [$id_warehouse, $keyword]);
$users_rs = $users_rq->answer();
/* (2) Gestion succès */ /* (2) Gestion succès */
if( $users_r->error->get() == Err::Success ) if( is_array($users_rs) )
foreach($users_r->answer() as $row) foreach($users_rs as $row)
$user_ids[] = $row['id_user']; $user_ids[] = $row['id_user'];
/* [3] On rédige/execute la requête /* [3] On rédige/execute la requête
=========================================================*/ =========================================================*/
$history_r = DatabaseDriver::getPDO()->prepare("SELECT id_history FROM history /* (1) Recherche par utilisateur */
WHERE id_user IN (SELECT id_user FROM user WHERE username LIKE '%$keyword%') $history_r_user = Table::get('history')
or id_machine IN (SELECT id_machine FROM machine WHERE name LIKE '%$keyword%') ->select('id_history')
ORDER BY timestamp DESC;"); ->whereIdUser([ $user_ids, Rows::COND_IN ]);
$history_r->execute(); /* (2) Recherche par utilisateur */
$history_r_machine = Table::get('history')
->select('id_history')
->whereIdMachine([ $machine_ids, Rows::COND_IN ]);
return DatabaseDriver::delNumeric( $history_r->fetchAll() ); /* (3) On enregistre les entrées par utilisateur */
$already_id = [];
$ids = $history_r_user->fetch();
foreach($ids as $user_result)
$already_id[ $user_result['id_history'] ] = null;
/* (4) On ajoute les entrées par machines (si pas déja) */
foreach($history_r_machine->fetch() as $machine_result)
if( !isset($already_id[$machine_result['id_history']]) ){
$ids[] = $machine_result;
$already_id[ $machine_result['id_history'] ] = null;
}
/* (5) On retourne le total */
return $ids;
} }

View File

@ -30,7 +30,9 @@
'id_warehouse' => $id_warehouse, 'id_warehouse' => $id_warehouse,
'name' => $name, 'name' => $name,
'token' => null, 'token' => null,
'unlock_code' => null 'unlock_code' => null,
'ap' => Rows::INSERT_DEFAULT,
'ip' => Rows::INSERT_DEFAULT
]); ]);
// Si erreur (car name doit être unique) // Si erreur (car name doit être unique)
@ -63,15 +65,75 @@
* *
*/ */
public static function search($id_warehouse, $keyword){ public static function search($id_warehouse, $keyword){
// On recupere les donnees
$search = Table::get('machine') /* (1) Format keyword
->whereIdWarehouse($id_warehouse) ---------------------------------------------------------*/ {
->whereName(["%$keyword%", Rows::COND_LIKE])
/* (1) Make all lowercase */
$keyword = strtolower($keyword);
/* (2) Create a keyword set (separator: space) */
$keywords = [];
$keywords_tmp = explode(' ', $keyword);
/* (4) Trim each keyword + ignore empty ones (2 consecutive spaces) */
foreach($keywords_tmp as $kw){
// ignore empty keywords
if( strlen(trim($kw)) == 0 )
continue;
// store others
$keywords[] = trim($kw);
}
}
/* (2) Search for each keyword
---------------------------------------------------------*/ {
/* (1) Initialise id list that will contain each matching user ids */
$mac_id_list = [];
/* (2) Request for each keyword */
foreach($keywords as $kw){
// {2.1} Request //
$searchmac = Table::get('machine')
->select('id_machine')
->whereIdWarehouse($id_warehouse)
->whereName(["%$kw%", Rows::COND_LIKE] );
// {2.2} Fetch result //
$matches = $searchmac->fetch();
// {2.3} Only add non-already added ids //
foreach($matches as $match){
// {2.4.1} If not already -> add it //
if( !isset($mac_id_list[ $match['id_machine'] ]) )
$mac_id_list[ $match['id_machine'] ] = null;
}
}
}
/* (3) Join results
---------------------------------------------------------*/
/* (1) Join request */
$join_rq = Table::get('machine')
->select('id_machine') ->select('id_machine')
->select('name') ->select('name')
->orderby('name', Rows::ORDER_ASC); ->whereId([array_keys($mac_id_list), Rows::COND_IN]);
/* (2) Return result */
return $join_rq->fetch();
return $search->fetch();
} }

View File

@ -0,0 +1,89 @@
<?php
namespace database\repo;
use \database\core\DatabaseDriver;
use \error\core\Err;
use \database\core\Repo;
use \orm\core\Table;
use \orm\core\Rows;
class module extends parentRepo{
protected static function table_name(){ static $table_name = 'module'; return $table_name; }
/* [1] Fetch all modules
*
* @return modules<Array> The list of modules
* FALSE on error
*
=========================================================*/
public static function getAll(){
return Table::get('module')->select('*')->fetch();
}
/* [2] Fetch all modules for the given warehouse
*
* @id_warehouse<int> UID of the given warehouse
*
* @return modules<Array> The list of modules
* FALSE on error
*
=========================================================*/
public static function getForWarehouse($id_warehouse){
/* (1) Build request */
$modules = Table::get('module')->select('*');
$merge = Table::get('module_availability')->whereIdWarehouse($id_warehouse);
$merge->join('id_module', $modules);
return $merge->fetch();
}
/* [3] Fetch all modules for the given machine_cluster
*
* @id_warehouse<int> UID of the given warehouse
* @id_machine_cluster<int> UID of the given machine_cluster
*
* @return modules<Array> The list of modules
* FALSE on error
*
=========================================================*/
public static function getForMachineCluster($id_warehouse, $id_machine_cluster){
/* (1) On récupère le ETREE de la machine
---------------------------------------------------------*/
$module = Table::get('module')
->select('id_module')
->select('name');
$etree = Table::get('etree')
->join('id_module', $module);
$merge = Table::get('module_merge')
->join('id_etree', $etree)
->whereIdWarehouse($id_warehouse)
->whereIdMachineCluster($id_machine_cluster);
return $merge->fetch();
}
}
?>

View File

@ -1,16 +0,0 @@
<?php
namespace database\repo;
use \database\core\DatabaseDriver;
use \database\core\Repo;
use \manager\repo\cluster as clusterRepo;
class pin_merge extends parentRepo{
protected static function table_name(){ static $table_name = 'pin_merge'; return $table_name; }
}
?>

View File

@ -4,6 +4,7 @@
use \database\core\DatabaseDriver; use \database\core\DatabaseDriver;
use \database\core\Repo; use \database\core\Repo;
use \manager\repo\cluster as clusterRepo; use \manager\repo\cluster as clusterRepo;
use \orm\core\Table;
class state extends parentRepo{ class state extends parentRepo{
@ -14,22 +15,21 @@
* *
* @id_chip<int> UID de la puce * @id_chip<int> UID de la puce
* *
* @return states<Array> Retourne les données sous forme de tableau de la forme (state, chip, pin, value) * @return states<Array> Retourne les données sous forme de tableau de la forme (state, chip, pin, value)
* *
*/ */
public static function getForChip($id_chip){ public static function getForChip($id_chip){
$req = DatabaseDriver::getPDO()->prepare("SELECT s.state, pm.id_chip, GROUP_CONCAT(s.value ORDER BY pm.pin ASC) as pin_values $chip = Table::get('chip')
FROM state as s, pin_merge as pm ->select('id_chip')
WHERE s.id_pin_merge = pm.id_pin_merge ->whereId($id_chip);
AND pm.id_chip = :id_chip
GROUP BY s.state, pm.id_chip");
$req->execute([
':id_chip' => $id_chip
]);
$req = Table::get('state')
->select('state')
->select('value')
->join('id_chip', $chip);
return $req->fetchAll(); return $req->fetch();
} }
} }

View File

@ -66,22 +66,82 @@
* *
*/ */
public static function search($id_warehouse, $keyword){ public static function search($id_warehouse, $keyword){
// On recupere les donnees
$searchusers = DatabaseDriver::getPDO()->prepare("SELECT * FROM user
WHERE id_warehouse = :id_warehouse
AND ( code LIKE '%".$keyword."%'
OR username LIKE '%".$keyword."%'
OR firstname LIKE '%".$keyword."%'
OR lastname LIKE '%".$keyword."%'
OR mail LIKE '%".$keyword."%'
)
");
$searchusers->execute([ /* (1) Format keyword
':id_warehouse' => $id_warehouse ---------------------------------------------------------*/ {
]);
return DatabaseDriver::delNumeric( $searchusers->fetchAll() ); /* (1) Make all lowercase */
$keyword = strtolower($keyword);
/* (2) Create a keyword set (separator: space) */
$keywords = [];
$keywords_tmp = explode(' ', $keyword);
/* (4) Trim each keyword + ignore empty ones (2 consecutive spaces) */
foreach($keywords_tmp as $kw){
// ignore empty keywords
if( strlen(trim($kw)) == 0 )
continue;
// store others
$keywords[] = trim($kw);
}
}
/* (2) Search for each keyword
---------------------------------------------------------*/ {
/* (1) Initialise id list that will contain each matching user ids */
$user_id_list = [];
/* (2) Request for each keyword */
foreach($keywords as $kw){
// {2.1} Request //
$searchusers = DatabaseDriver::getPDO()->prepare("SELECT id_user FROM user
WHERE id_warehouse = :id_warehouse
AND ( LOWER(code) LIKE '%".$kw."%'
OR LOWER(username) LIKE '%".$kw."%'
OR LOWER(firstname) LIKE '%".$kw."%'
OR LOWER(lastname) LIKE '%".$kw."%'
OR LOWER(mail) LIKE '%".$kw."%'
)
");
// {2.2} Inject params //
$searchusers->execute([ ':id_warehouse' => $id_warehouse ]);
// {2.3} Fetch result //
$matches = DatabaseDriver::delNumeric( $searchusers->fetchAll() );
// {2.4} Only add non-already added ids //
foreach($matches as $match){
// {2.4.1} If not already -> add it //
if( !isset($user_id_list[ $match['id_user'] ]) )
$user_id_list[ $match['id_user'] ] = null;
}
}
}
/* (3) Join results
---------------------------------------------------------*/
/* (1) Join request */
$join_rq = Table::get('user')
->select('*')
->whereId([array_keys($user_id_list), Rows::COND_IN]);
/* (2) Return result */
return $join_rq->fetch();
} }

View File

@ -2,6 +2,7 @@
namespace database\repo; namespace database\repo;
use \database\core\DatabaseDriver; use \database\core\DatabaseDriver;
use \database\core\Repo;
use \manager\sessionManager; use \manager\sessionManager;
use \orm\core\Table; use \orm\core\Table;
use \orm\core\Rows; use \orm\core\Rows;
@ -26,8 +27,8 @@
->insert([ ->insert([
'id_warehouse' => Rows::INSERT_DEFAULT, 'id_warehouse' => Rows::INSERT_DEFAULT,
'name' => $name, 'name' => $name,
'password' => sessionManager::secure_hash( $password ), 'password' => \secure_hash( $password, $name ),
'token' => sessionManager::secure_hash( uniqid() ) 'token' => \secure_hash( uniqid(), $name.'-*-'.$name )
]); ]);
// Si name déja pris, erreur // Si name déja pris, erreur
@ -97,20 +98,22 @@
public static function getModules($id_warehouse){ public static function getModules($id_warehouse){
/* [1] On récupère les modules /* [1] On récupère les modules
=========================================================*/ =========================================================*/
$module = Table::get('module') /* (1) Récupération */
->select('id_module') $mod_req = new Repo('module/getForWarehouse', [$id_warehouse]);
->select('name');
$merge = Table::get('module_merge') $answer = $mod_req->answer();
->whereIdWarehouse($id_warehouse)
->join('id_module', $module); /* (2) Gestion erreur */
if( $answer === false )
return []; // no error
$modules = $merge->fetch();
/* [2] On formatte les données pour avoir 1 niveau de tableau /* [2] On formatte les données pour avoir 1 niveau de tableau
=========================================================*/ =========================================================*/
foreach($modules as $m=>$module) $modules = []; // id => name
$modules[$m] = $module['name'];
foreach($answer as $module)
$modules[$module['id_module']] = $module['name'];
/* [3] On retourne la liste /* [3] On retourne la liste
@ -141,7 +144,7 @@
->whereId($id_warehouse) ->whereId($id_warehouse)
->edit([ ->edit([
'name' => $name, 'name' => $name,
'password' => sessionManager::secure_hash( $password ) 'password' => $password
]); ]);

117
build/generic/core/View.php Normal file
View File

@ -0,0 +1,117 @@
<?php
namespace generic\core;
class View{
/* (1) Attributes
---------------------------------------------------------*/
private $core_class;
private $patch_class = [];
private $arguments;
public static $html_error = "<span class='error'>Une erreur est survenue, veuilez contacter le webmaster si cette erreur persiste.</span>";
/* (2) Instance constructor (add patches)
*
* @core_class<String> The target view class
*
---------------------------------------------------------*/
private function __construct(String $core_class){
/* (1) Get class directory & namespace */
$root_ns = str_replace('/', '\\', dirname( str_replace('\\', '/', $core_class) ) ).'\\';
$root_dir = __BUILD__.'/generic/'.dirname( str_replace('\\', '/', $core_class) );
/* (2) Get patches */
foreach( glob($root_dir.'/*.php') as $class ){
// {1} Extract basename (without '.php') //
$basename = basename($class);
$basename = substr($basename, 0, strlen($basename)-strlen('.php'));
$class_ns = $root_ns.$basename;
// {2} Ignore main (core class) //
if( $basename == 'main' )
continue;
// {3} Check if class exists //
if( !class_exists($class_ns) )
continue;
// {4} Check if instance of 'i_patch' //
if( !(new $class_ns() instanceof i_patch) )
continue;
// {5} Check if it corresponds to a warehouse's module //
if( !in_array($basename, $_SESSION['WAREHOUSE']['modules']) )
continue;
// {6} Store each patch instance //
$this->patch_class[$basename] = new $class_ns();
}
/* (3) Store core class */
$this->core_class = $core_class;
}
/* (3) Renders a view with injected data
*
* @injected_data<Array> Data to inject
*
* @return render<String> Rendered view
*
---------------------------------------------------------*/
public function render(array $injected_data=[]){
/* (1) Create core instance with data */
$view = new $this->core_class(...$injected_data);
/* (2) Patch it every @patch_class */
foreach($this->patch_class as $patch_name=>$patch_inst)
$view->patch($patch_name, $patch_inst);
/* (3) Dispatch rendering */
return $view->render();
}
/* (4) Loads a view from its path (builder)
*
* @view_path<String> View path
*
* @return view<View> View instance
* NULL on error
*
---------------------------------------------------------*/
public static function load(String $view_path){
/* (1) Check arguments
---------------------------------------------------------*/
/* (1) Check path format */
if( !preg_match('@^[\w+\.]+$@', $view_path) )
return null;
/* (2) Extract class */
$core_class = '\\view\\'.str_replace('.', '\\', $view_path).'\\main';
/* (3) Check if class exists */
if( !class_exists($core_class) )
return null;
/* (2) Return View instance
---------------------------------------------------------*/
return new self($core_class);
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace generic\core;
abstract class i_patch{
/* (1) Attributes
---------------------------------------------------------*/
/* (1) Patch index */
public $patch = [];
}

View File

@ -0,0 +1,90 @@
<?php
namespace generic\core;
abstract class i_view{
/* (1) Attributes
---------------------------------------------------------*/
/* (1) Will contain patches according to warehouse's modules */
public $patch = [];
/* (2) Add a patch to the core view
*
* @patch_name<String> Patch name
* @patch_inst<i_patch> Patch instance
*
---------------------------------------------------------*/
public function patch(String $patch_name, i_patch $patch_inst){
$this->patch[$patch_name] = $patch_inst;
}
/* (3) Returns the auto patch code
*
*
---------------------------------------------------------*/
private function autopatch(){
/* (1) Pre-code */
$code = "{% extends 'main.twig' %}\n\n";
/* (2) For each module patch */
foreach($this->patch as $name=>$inst)
/* (3) For each block patch */
foreach($inst->patch as $block=>$temp)
$code .= "{% block $block %}{% include '$temp' %}{% endblock %}\n";
/* (4) Return code */
return $code;
}
/* (4) Renders the view
*
---------------------------------------------------------*/
public function render(){
/* (1) Get path information (core class)
---------------------------------------------------------*/
/* (1) Get core class */
$core_class = str_replace('\\', '/', get_class($this));
/* (2) Extract root DIR */
$root_path = __BUILD__.'/generic/'.dirname($core_class);
/* (3) Extract file name */
$model_path = basename($core_class).'.twig';
/* (2) Get patches
---------------------------------------------------------*/
$auto_patch = [ 'render.twig' => $this->autopatch() ];
/* (2) Setup
---------------------------------------------------------*/
/* (1) Initialize twig */
$loader = new \Twig_Loader_Chain([
new \Twig_Loader_Filesystem($root_path), // default directory templates
new \Twig_Loader_Array($auto_patch) // custom auto-patch system
]);
$twig = new \Twig_Environment($loader, [
'debug' => true,
'cache' => false,
'auto_reload' => true
]);
/* (3) Build the view and return it back
---------------------------------------------------------*/
/* (1) Render and return the view */
return $twig->render('render.twig', [ 'core' => $this, 'patch' => $this->patch ]);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace view\group\form\create;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,24 @@
{% block form_tag %} <form class='valid'> {% endblock %}
{% block input %}
<input id='create_name' type='text' placeholder='Nom'><br>
<span class='error-msg create_name'></span><br>
<select id='create_class'>
<option value='-' selected disabled>Type de groupe</option>
<option value='0'>utilisateurs</option>
<option value='1'>machines</option>
</select>
<span class='error-msg create_class'></span><br>
{% endblock %}
{% block submit %}
<button id='create_submit'>Créer</button>
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\group\form\edit;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,44 @@
{% block form_tag %} <form class='neutral'> {% endblock %}
<!-- Recherche de groupe -->
{% block search %}
{% block search_input %}
<input id='edit_search_keyword' type='text' class='search' placeholder='Recherche...'><br>
<input id='edit_search_id' type='hidden' value=''>
{% endblock %}
<!-- Indice du resultat -->
{% block search_submit %}
<span class='edit_search_view'>groupe <span class='edit_search_num'>0</span> sur <span class='edit_search_sum'>0</span></span><br><br>
<button id='edit_search_submit' class='search'>Trouver/Suivant</button><br>
{% endblock %}
{% endblock %}
<br><br><hr class='OR' data-label='PUIS' /><br><br>
<!-- Modification de groupe -->
{% block edit %}
{% block edit_input %}
<input id='edit_name' type='text' placeholder='Nom'><br>
<span class='error-msg edit_name'></span><br>
{% endblock %}
{% block edit_submit %}
<input id='edit_class' type='text' placeholder='Type de groupe' disabled><br>
<button id='edit_submit' disabled>Modifier</button>
{% endblock %}
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\group\form\remove;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,43 @@
{% block form_tag %} <form class='invalid'> {% endblock %}
<!-- Recherche de groupe -->
{% block search %}
{% block search_input %}
<input id='remove_search_keyword' type='text' class='search' placeholder='Recherche...'><br>
<input id='remove_search_id' type='hidden' value=''>
{% endblock %}
<!-- Indice du resultat -->
{% block search_submit %}
<span class='remove_search_view'>groupe <span class='remove_search_num'>0</span> sur <span class='remove_search_sum'>0</span></span><br><br>
<button id='remove_search_submit' class='search'>Trouver/Suivant</button><br>
{% endblock %}
{% endblock %}
<br><br><hr class='OR' data-label='PUIS' /><br><br>
<!-- Suppression de groupe -->
{% block remove %}
{% block remove_input %}
<input id='remove_name' type='text' placeholder='Nom' disabled><br>
<input id='remove_class' type='text' placeholder='Type de groupe' disabled><br>
{% endblock %}
{% block remove_submit %}
<button id='remove_submit' disabled>Supprimer</button>
{% endblock %}
{% endblock %}
</form>

View File

@ -0,0 +1,127 @@
<?php
namespace view\group\member\choice;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
use \generic\core\View;
class main extends i_view{
public $class;
public $name;
public $id_cluster;
public function __construct(String $id_cluster, int $class){
/* (1) On vérifie le type de groupe (user/machine)
---------------------------------------------------------*/ {
/* (1) On vérifie les paramètres */
if( !isset($id_cluster) || !is_numeric($id_cluster) || !isset($class) || !is_numeric($class) )
return View::$html_error;
/* (2) On récupère le groupe */
$checktypeRequest = new Request('clusterDefault/getById', [
'id_cluster' => $id_cluster,
'class' => $class
]);
$checktypeResponse = $checktypeRequest->dispatch();
/* (3) Si on ne le trouve pas, on retourne une erreur */
if( $checktypeResponse->error->get() != Err::Success )
return View::$html_error;
/* (4) On récupère les données du groupe */
$currentCluster = $checktypeResponse->get('cluster');
}
/* (2) Fill attributes
---------------------------------------------------------*/
$this->id_cluster = $id_cluster;
$this->class = $class;
$this->name = $currentCluster['name'];
}
public function get_members($id_cluster, $class){
/* (1) On récupère les membres
---------------------------------------------------------*/ {
/* (1) On exécute la requête */
$getmembersRequest = new Request('clusterDefault/getMembers', [
'id_cluster' => $id_cluster,
'class' => $class
]);
$getmembersResponse = $getmembersRequest->dispatch();
/* (2) Si erreur, on retourne rien par défaut */
if( $getmembersResponse->error->get() != Err::Success )
return [];
/* (3) On récupère la liste des UID uniquement */
$members_ids = [];
foreach($getmembersResponse->get('members') as $member)
$members_ids[] = ($class==0) ? $member['id_user'] : $member['id_machine'];
}
/* (2) On récupère les utilisateurs non membres
---------------------------------------------------------*/
/* (1) On récupère les utilisateurs */
if( $class == 0 ){
/* (2) On exécute la requête */
$getusersRequest = new Request('userDefault/getAll');
// On recupere la reponse
$getusersResponse = $getusersRequest->dispatch();
/* (3) si erreur, on affiche l'explicitation */
if( $getusersResponse->error->get() != Err::Success )
return [];
/* (4) On récupère la liste des utilisateurs */
$users = $getusersResponse->get('users');
/* (5) On ajoute s'ils sont dans le groupe ou non */
foreach($users as $u=>$user)
$users[$u]['already'] = in_array($user['id_user'], $members_ids);
return $users;
/* (3) On récupère les machines non membres
---------------------------------------------------------*/
/* (1) On récupère les machines */
}else{
/* (2) On exécute la requête */
$getmachinesRequest = new Request('machineDefault/getAll');
// On recupere la reponse
$getmachinesResponse = $getmachinesRequest->dispatch();
/* (3) si erreur, on affiche l'explicitation */
if( $getmachinesResponse->error->get() != Err::Success )
return [];
/* (4) On récupère la liste des machines */
$machines = $getmachinesResponse->get('machines');
/* (5) On ajoute s'ils sont dans le groupe ou non */
foreach($machines as $u=>$machine)
$machines[$u]['already'] = in_array($machine['id_machine'], $members_ids);
return $machines;
}
}
}

View File

@ -0,0 +1,87 @@
{% block back %}
<span style='text-align:center; color: #666; text-decoration: underline; cursor: pointer;' id='members-change-group'>Modifier un autre groupe</span>
<p></p>
{% endblock %}
{% block container %}
<article class='check-table'>
{% block hidden %}
<input type='hidden' id='members-member-idcluster' value='{{ core.id_cluster }}'>
<input type='hidden' id='members-member-class' value='{{ core.class }}'>
{% endblock %}
{% block header %}
<div>
{# USER HEADER #}
{% if core.class == 0 %}
<span><strong>Identifiant</strong></span>
<span><strong>Nom</strong></span>
<span><strong>Code RFID</strong></span>
{# MACHINE HEADER #}
{% else %}
<span><strong>Nom</strong></span>
{% endif %}
<span><strong>Membre de <u>{{ core.name }}</u></strong></span>
</div>
{% endblock %}
{% block member_list %}
{% for member in core.get_members(core.id_cluster, core.class) %}
{% block member_entry %}
{# USER ENTRIES #}
{% if core.class == 0 %}
{% block user_entry %}
<div>
<span>{{ member.username }}</span>
<span>{{ member.firstname }} {{ member.lastname }}</span>
<span>{{ member.code }}</span>
<span>
<input type='checkbox' value='{{ member.id_user }}' data-name='members' id='checkbox_{{ member.id_user }}' {% if member.already %}checked{% endif %}>
<label for='checkbox_{{ member.id_user }}'></label>
</span>
</div>
{% endblock %}
{# MACHINE ENTRIES #}
{% else %}
{% block machine_entry %}
<div>
<span>{{ member.name }}</span>
<span>
<input type='checkbox' value='{{ member.id_machine }}' data-name='members' id='checkbox_{{ member.id_machine }}' {% if member.already %}checked{% endif %}>
<label for='checkbox_{{ member.id_machine }}'></label>
</span>
</div>
{% endblock %}
{% endif %}
{% endblock %}
{% endfor %}
{% endblock %}
</article>
{% endblock %}

View File

@ -0,0 +1,32 @@
<?php
namespace view\group\member\group;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
public function __construct(){
}
public function get_clusters($class){
/* (1) On récupère les groupes */
$getClustersReq = new Request('clusterDefault/getAll', ['class' => $class]);
$getClusters = $getClustersReq->dispatch();
/* (2) si erreur, on retourne rien par défaut */
if( $getClusters->error->get() != Err::Success )
return [];
/* (3) On enregistre le résultat */
return $getClusters->get('clusters');
}
}

View File

@ -0,0 +1,26 @@
{% block form_tag %} <form class='neutral' action='' method='POST' id='choose-cluster'> {% endblock %}
{% block input %}
<select data-name='cluster'>
<option value='.' selected disabled>Groupe à modifier</option>
{% for user_cluster in core.get_clusters(0) %}
<option value='u{{ user_cluster.id_user_cluster }}'>{{ user_cluster.name }} (utilisateur)</option>
{% endfor %}
{% for machine_cluster in core.get_clusters(1) %}
<option value='m{{ machine_cluster.id_machine_cluster }}'>{{ machine_cluster.name }} (machine)</option>
{% endfor %}
</select>
{% endblock %}
{% block submit %}
<button id='choose-cluster'>Modifier la composition</button>
{% endblock %}
</form>

View File

@ -0,0 +1,113 @@
<?php
namespace view\group\permission;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
use \generic\core\View;
class main extends i_view{
public function __construct(){
/* (1) Setup attributes
---------------------------------------------------------*/
/* (1) Fill attributes */
$this->icon = [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'device' => file_get_contents( __PUBLIC__.'/src/static/menu-side/device.svg' ),
'permission' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/permission.svg')
];
$this->theme = $_SESSION['WAREHOUSE']['theme'];
}
public function get_clusters(){
$request = new Request('clusterDefault/getAll', [
'class' => 1
]);
$answer = $request->dispatch();
// si erreur, on affiche rien par défaut
if( $answer->error->get() != Err::Success )
return [];
return $answer->get('clusters');
}
public function get_nb_machines($id_cluster){
$machineReq = new Request('clusterDefault/getMembers', [
'id_cluster' => (int) $id_cluster,
'class' => 1
]);
$machineRes = $machineReq->dispatch();
// si erreur, on affiche rien par défaut
if( $machineRes->error->get() != Err::Success )
return [];
return count($machineRes->get('members'));
}
public function get_permissions(){
$permReq = new Request('clusterDefault/getPermissions', []);
$permRes = $permReq->dispatch();
// si erreur, on affiche rien par défaut
if( $permRes->error->get() != Err::Success )
return [];
return $permRes->get('permissions');
}
public function get_authed_user_clusters($id_cluster, $id_permission){
$ucReq = new Request('clusterDefault/getAuthenticatedClusters', [
'id_target' => $id_cluster,
'id_action' => $id_permission
]);
$ucRes = $ucReq->dispatch();
// si erreur, on affiche rien par défaut
if( $ucRes->error->get() != Err::Success )
return [];
return $ucRes->get('clusters');
}
public function permission_translate($word, $lang){
$word = strtolower($word);
if( $lang === 'fr' ){
switch($word){
case 'start': return 'démarrer'; break;
case 'stop': return 'arrêter'; break;
case 'signal': return 'signaler'; break;
case 'lock': return 'bloquer'; break;
case 'unlock': return 'débloquer'; break;
case 'unsignal': return 'désignaler'; break;
default: return 'inconnu'; break;
}
}else
return $word;
}
}

View File

@ -0,0 +1,86 @@
{% block search_bar %} <input type='text' class='searchbar' placeholder='Recherche'> {% endblock %}
{% for machine_cluster in core.get_clusters() %}
{% block machine_cluster_card %}
{% block card_tag %} <article class='inline-box' id='{{ machine_cluster.id_machine_cluster }}'> {% endblock %}
{% set nb_machines = core.get_nb_machines(machine_cluster.id_machine_cluster) %}
{% block card_title %} <span class='title' style='color: {{ core.theme }}'>{{ machine_cluster.name }}</span> {% endblock %}
{% block card_remove %} <span class='link_remove' data-cluster='{{ machine_cluster.id_machine_cluster }}'>{{ core.icon.remove | raw }}</span> {% endblock %}
{% block card_edit %} <span class='link_edit' data-cluster='{{ machine_cluster.id_machine_cluster }}'>{{ core.icon.edit | raw }}</span> {% endblock %}
{% block card_count %}
<span class='code'>
{{ core.icon.device | raw }}
<span>{{ nb_machines }} machines</span>
</span>
{% endblock %}
{% block card_permission_list %}
{% for permission in core.get_permissions() %}
{% block card_permission %}
<span class='groups'>
{% block card_permission_name %}
<span style='border-color: #ddd; background-color: #eee;'>
{{ core.permission_translate(permission.name, 'fr') }}
<span class='icon-permission'></span>
</span>
{% endblock %}
{% block auth_user_cluster_list %}
<span class='ignore'>
{% for user_cluster in core.get_authed_user_clusters(machine_cluster.id_machine_cluster, permission.id_permission) %}
{% block auth_user_cluster %}
<span>
{% block auth_user_cluster_name %} {{ user_cluster.name }} {% endblock %}
<span class='rem-permission' data-permission='{{ permission.id_permission }}' data-source='{{ user_cluster.id_user_cluster }}' data-target='{{ machine_cluster.id_machine_cluster }}'></span>
</span>
{% endblock %}
{% endfor %}
</span>
{% endblock %}
<span class='add-permission' data-target='{{ machine_cluster.id_machine_cluster }}' data-permission='{{ permission.id_permission }}'>+</span>
</span>
{% endblock %}
{% endfor %}
{% endblock %}
</article>
{% endblock %}
{# if no result #}
{% else %}
{% block no_result %}
<article class='inline-box'>
<span>Aucun groupe trouvé.</span>
</article>
{% endblock %}
{% endfor %}

View File

@ -0,0 +1,79 @@
<?php
namespace view\group\view;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
use \generic\core\View;
class main extends i_view{
public function __construct(){
/* (1) Setup attributes
---------------------------------------------------------*/
/* (1) Fill attributes */
$this->icon = [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'device' => file_get_contents( __PUBLIC__.'/src/static/menu-side/device.svg' ),
'user' => file_get_contents( __PUBLIC__.'/src/static/menu-side/users.svg' ),
'group' => file_get_contents( __PUBLIC__.'/src/static/container/group.svg' ),
'option' => file_get_contents( __PUBLIC__.'/src/static/container/option.svg' )
];
$this->theme = $_SESSION['WAREHOUSE']['theme'];
}
public function get_clusters($class){
/* (1) On récupère les groupes */
$getClustersReq = new Request('clusterDefault/getAll', ['class' => $class]);
$getClusters = $getClustersReq->dispatch();
/* (2) si erreur, on retourne rien par défaut */
if( $getClusters->error->get() != Err::Success )
return [];
/* (3) On enregistre le résultat */
return $getClusters->get('clusters');
}
public function get_members($id_cluster, $class){
$membersReq = new Request('clusterDefault/getMembers', [
'id_cluster' => (int) $id_cluster,
'class' => $class
]);
$membersRes = $membersReq->dispatch();
//
// si erreur, on affiche rien par défaut
if( $membersRes->error->get() != Err::Success )
return [];
return $membersRes->get('members');
}
public function get_options($id_cluster){
$modReq = new Request('clusterDefault/getEtrees', [
'id_machine_cluster' => (int) $id_cluster
]);
$modRes = $modReq->dispatch();
// si erreur, on affiche rien par défaut
if( $modRes->error->get() != Err::Success )
return [];
return $modRes->get('etrees');
}
}

View File

@ -0,0 +1,150 @@
{% block search_bar %} <input type='text' class='searchbar' placeholder='Recherche'> {% endblock %}
{% set count = 0 %}
{# {% block user_cluster_list %} #}
{% for user_cluster in core.get_clusters(0) %}
{% set count = count + 1 %}
{% set id_user_cluster = 'u' ~ user_cluster.id_user_cluster %}
{% set memlen = core.get_members(user_cluster.id_user_cluster,0) | length %}
{% block uc_card %}
{% block uc_card_tag %} <article class='inline-box' id='{{ id_user_cluster }}'> {% endblock %}
{% block uc_card_title %} <span class='title' style='color: {{ core.theme }}'>{{ user_cluster.name }}</span> {% endblock %}
{% block uc_card_remove %} <span class='link_remove' data-cluster='{{ id_user_cluster }}'>{{ core.icon.remove | raw }}</span> {% endblock %}
{% block uc_card_edit %} <span class='link_edit' data-cluster='{{ id_user_cluster }}'>{{ core.icon.edit | raw }}</span> {% endblock %}
{% block uc_card_count %}
<span class='code'>
{{ core.icon.user | raw }}
<span>{{ memlen }} utilisateur{% if memlen > 1 %}s{% endif %}</span>
</span>
{% endblock %}
{% block uc_card_member_list %}
<span class='groups'>
{{ core.icon.group | raw }}
{% block uc_card_member %}
<span class='ignore'>
{% for user in core.get_members(user_cluster.id_user_cluster, 0) %}
<span>
{% block uc_card_member_name %} {{ user.username }} {% endblock %}
<span class='rem-member' data-member='{{ user.id_user }}' data-cluster='{{ id_user_cluster }}'></span>
</span>
{% endfor %}
</span>
{% endblock %}
<span class='add-member' data-cluster='{{ id_user_cluster }}'>+</span>
</span>
{% endblock %}
</article>
{% endblock %}
{% endfor %}
{# {% endblock %} #}
{# {% block machines_cluster_list %} #}
{% for machine_cluster in core.get_clusters(1) %}
{% set count = count + 1 %}
{% set id_machine_cluster = 'm' ~ machine_cluster.id_machine_cluster %}
{% set memlen = core.get_members(machine_cluster.id_machine_cluster,1) | length %}
{% block mc_card %}
{% block mc_card_tag %} <article class='inline-box' id='{{ id_machine_cluster }}'> {% endblock %}
{% block mc_card_title %} <span class='title' style='color: {{ core.theme }}'>{{ machine_cluster.name }}</span> {% endblock %}
{% block mc_card_remove %} <span class='link_remove' data-cluster='{{ id_machine_cluster }}'>{{ core.icon.remove | raw }}</span> {% endblock %}
{% block mc_card_edit %} <span class='link_edit' data-cluster='{{ id_machine_cluster }}'>{{ core.icon.edit | raw }}</span> {% endblock %}
{% block mc_card_count %}
<span class='code'>
{{ core.icon.device | raw }}
<span>{{ memlen }} machine{% if memlen > 1 %}s{% endif %}</span>
</span>
{% endblock %}
{% block mc_card_options %}
<span class='option'>
{{ core.icon.option | raw }}
{% for option in core.get_options(machine_cluster.id_machine_cluster) %}
<span class='ignore'>
<span>{{ option.name }}:{{ option.daemon }}</span>
</span>
{% else %}
<span class='ignore'>Aucune option</span>
{% endfor %}
</span>
{% endblock %}
{% block mc_card_member_list %}
<span class='groups'>
{{ core.icon.group | raw }}
{% block mc_card_member %}
<span class='ignore'>
{% for machine in core.get_members(machine_cluster.id_machine_cluster,1) %}
<span>
{% block mc_card_member_name %} {{ machine.name }} {% endblock %}
<span class='rem-member' data-member='{{ machine.id_machine }}' data-cluster='{{ id_machine_cluster }}'></span>
</span>
{% endfor %}
</span>
{% endblock %}
<span class='add-member' data-cluster='{{ id_machine_cluster }}'>+</span>
</span>
{% endblock %}
</article>
{% endblock %}
{% endfor %}
{# {% endblock %} #}
{# if no result #}
{% if count <= 0 %}
{% block no_result %}
<article class='inline-box'>
<span>Aucun résultat {{ count }}</span>
</article>
{% endblock %}
{% endif %}

View File

@ -0,0 +1,13 @@
<?php
namespace view\history\archive;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){
}
}

View File

@ -0,0 +1,7 @@
<form class='search'>
Le téléchargement de l'archive supprimera toutes les entrées de l'historique.
<br>
<center>Etes-vous sur de vouloir procéder ?</center>
<br>
<button id='archive_clean'>Archiver l'historique</button>
</form>

View File

@ -0,0 +1,256 @@
<?php
namespace view\history\details;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
public $id_history;
public $timeline = [];
public $entry = [];
/* (1) Constructor
*
* @id_history<id> UID of the history entry
*
---------------------------------------------------------*/
public function __construct($id_history){
/* (1) Set attributes
---------------------------------------------------------*/
$this->id_history = $id_history;
/* (3) Get entry data
---------------------------------------------------------*/
/* (1) Request */
$entry_req = new Request('historyDefault/getById', [ 'id_entry' => $this->id_history ]);
/* (2) Get response */
$entry_res = $entry_req->dispatch();
/* (3) On success, store entry data */
if( $entry_res->error->get() == Err::Success )
$this->entry = $entry_res->get('entry');
/* (3) Get machine timeline
---------------------------------------------------------*/
/* (1) Request */
$mac_req = new Request('historyDefault/get_timeline', [ 'id_entry' => $this->id_history ]);
/* (2) Get response */
$mac_res = $mac_req->dispatch();
/* (3) On success, store timeline data */
if( $mac_res->error->get() == Err::Success ){
$this->timeline = $mac_res->get('timeline');
// add date nodes to the timeline
$this->add_date_nodes();
}
}
/* (2) Format timeline data to svg render
*
* @return svg<String> SVG raw render
*
---------------------------------------------------------*/
public function svg(){
/* (1) Initialize variables
---------------------------------------------------------*/
/* (1) Set date() timezone */
date_default_timezone_set('Europe/Paris');
debug();
/* (2) Init. result raw svg */
$RAW = '';
/* (3) Set global range */
$c = 0;
$cl = count($this->timeline);
// if no entry -> abort
if( $cl == 0 )
return '';
/* (4) Useful variables */
$y_pad = 50; // padding between each node
$line_pad = 50; // padding on each LINE end
$line_height = ( $cl + 1 ) * $y_pad; // line height (each node * @y_pad + @y_pad)
$height = $line_height + 2*$line_pad; // svg height
$width = 200; // svg width
$x = 50; // center width
/* (5) Svg tag */
$RAW .= "<svg width='$width' height='$height' viewBox='0 0 $width $height' class='timeline'>";
/* (6) Start CIRCLE */ {
// {6.1} Date node //
$y = $line_pad;
$RAW .= "<circle cx='$x' cy='$y' r='7' fill='#edf0f5' class='tstart'/>";
$RAW .= "<circle cx='$x' cy='$y' r='4' fill='#555' class='tstart'/>";
// {6.2} Date line to text //
$line_end_x = $x + (30-8);
$RAW .= "<path d='m".($x+8)." $y L$line_end_x $y' style='stroke-dasharray: 3px;' s stroke='#444'/>";
// {6.3} Date text //
$x_decal = $x + 30;
$y_decal = $y + 5;
$RAW .= "<text x='$x_decal' y='$y_decal' class='bold'>".date('d / m / Y', $this->timeline[0]['timestamp'])."</text>";
}
/* (2) Build barebone
---------------------------------------------------------*/
/* (1) Default TIMELINE */
$line_end_y = $line_height + $line_pad;
$RAW .= "<path d='m$x $line_pad L$x $line_end_y' style='stroke-dasharray: 3px;' stroke='#444' class='timeline line'/>";
/* (3) Build each action
---------------------------------------------------------*/
for( $c = 0 ; $c < $cl ; $c++ ){
/* (1) Calculate X */
$y = $line_pad + $y_pad + $c*$y_pad;
/* (2) Get entry data */
$entry = $this->timeline[$c];
/* (2.1) If DATE NODE -> add it */
if( isset($entry['date_node']) ){
// {2.1.1} Date node //
$RAW .= "<circle cx='$x' cy='$y' r='7' fill='#edf0f5' class='tstart'/>";
$RAW .= "<circle cx='$x' cy='$y' r='4' fill='#555' class='tstart'/>";
// {2.1.2} Date line to text //
$line_end_x = $x + (30-8);
$RAW .= "<path d='m".($x+8)." $y L$line_end_x $y' style='stroke-dasharray: 3px;' stroke='#555'/>";
// {2.1.3} Date text //
$x_decal = $x + 30;
$y_decal = $y + 5;
$RAW .= "<text x='$x_decal' y='$y_decal' class='bold'>".$entry['date_node']."</text>";
continue;
}
/* (3) Get useful data */
$action_class = strtolower($entry['action_name']);
$icon_uri = '/src/static/timeline/'.$action_class.'@ffffff.svg';
$data_entry = "data-entry='".$entry['id_history']."'";
$data_user = " data-user='".$entry['user_name']."'";
$data_machine = " data-machine='".$entry['machine_name']."'";
$data_action = " data-action='".$entry['action_name']."'";
$data_time = " data-time='".date('H:i:s d/m/Y', $entry['timestamp'])."'";
$data_tags = $data_entry.$data_user.$data_machine.$data_action.$data_time;
$y_img = $y - 5.5;
/* (4) Draw entry circles */
$RAW .= "<circle cx='$x' cy='$y' r='15' class='timeline around $action_class' $data_tags id='e".$entry['id_history']."' data-y='$y' />";
$RAW .= "<circle cx='$x' cy='$y' r='12' class='timeline center $action_class' />";
/* (5) Draw entry icon (action) */
$x_decal = $x - 5.5;
$RAW .= "\t<image x='$x_decal' y='$y_img' width='12' height='12' xlink:href='$icon_uri' class='icon' />";
/* (6) Draw circle below if current user */
if( $this->entry['id_user'] == $entry['id_user'] ){
$x_decal = $x - 25;
// {6.1} If current ENTRY -> draw big circle //
if( $this->entry['id_history'] == $entry['id_history'] )
$RAW .= "<circle cx='$x_decal' cy='$y' r='4' class='timeline below $action_class' />";
// {6.2} Else -> draw little circle //
else
$RAW .= "<circle cx='$x_decal' cy='$y' r='2' class='timeline below $action_class' />";
}
/* (6) Hour */
$x_decal = $x + 25;
$y_decal = $y + 5;
$RAW .= "<text x='$x_decal' y='$y_decal' class='$action_class'>".date('H:i:s', $entry['timestamp'])." - ".$entry['user_name']."</text>";
}
/* (4) Close SVG
---------------------------------------------------------*/
/* (1) Stop CIRCLE */
$y = $line_height + $line_pad;
$RAW .= "<circle cx='$x' cy='$y' r='6' fill='#edf0f5' class='tstop' />";
$RAW .= "<circle cx='$x' cy='$y' r='4' fill='#555' class='tstop' />";
/* (2) Close SVG tag */
$RAW .= "</svg>";
/* (5) Create invisible infobox (for now)
---------------------------------------------------------*/
$RAW .= "<div class='timeline infobox'></div>";
return $RAW;
}
/* (3) Add events for new day in @this->timeline
*
---------------------------------------------------------*/
private function add_date_nodes(){
/* (1) Initialization
---------------------------------------------------------*/
/* (1) Initialize variables */
$last_day = null;
$new_timeline = []; // will contain the new @timeline data
/* (2) Browse each entry
---------------------------------------------------------*/
foreach($this->timeline as $entry){
/* (1) If different day (not null) -> add a node + update last_day */
if( !is_null($last_day) && $last_day != date('d / m / Y', $entry['timestamp']) )
$new_timeline[] = [ 'date_node' => $last_day ];
/* (2) In all cases -> copy the event */
$new_timeline[] = $entry;
/* (3) Update the day */
$last_day = date('d / m / Y', $entry['timestamp']);
}
/* (3) Update the result
---------------------------------------------------------*/
$this->timeline = $new_timeline;
}
}

View File

@ -0,0 +1,6 @@
<!-- <span class='in-dev'>In development.. This feature will soon be available.</span> -->
<article class='timeline container' data-length='{{ core.timeline | length }}'>
{{ core.svg() | raw }}
</article>

View File

@ -0,0 +1,110 @@
<?php
namespace view\history\view;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
public function __construct(){}
public function get_history(){
$req = new Request('historyDefault/getAll', []);
$res = $req->dispatch();
// si erreur, on retourne rien par défaut
if( $res->error->get() != Err::Success )
return [];
return $res->get('history');
}
public function ts_format($ts){
date_default_timezone_set('Europe/Paris');
return date('d/m/Y H:i:s', $ts);
}
public function ts_relative($ts){
$r = self::relativetime($ts);
// if only one
$o = $r[0] <= 1;
switch($r[1]){
case 'Y': return $r[0].' an'.($o?'':'s'); break;
case 'm': return $r[0].' mois'; break;
case 'd': return $r[0].' jour'.($o?'':'s'); break;
case 'H': return $r[0].' heure'.($o?'':'s'); break;
case 'i': return $r[0].' minute'.($o?'':'s'); break;
case 's': return $r[0].' seconde'.($o?'':'s'); break;
default: return 'peu de temps'; break;
}
}
private static function relativetime($ts){
/* [1] Explode time into human-readable time units
=========================================================*/
$units = [];
/* (1) Date units */
$units['year'] = (int) date('Y', $ts);
$units['month'] = (int) date('m', $ts);
$units['day'] = (int) date('d', $ts);
/* (2) Time units */
$units['hour'] = (int) date('H', $ts);
$units['minute'] = (int) date('i', $ts);
$units['second'] = (int) date('s', $ts);
/* [2] Calculate relative time for each unit
=========================================================*/
/* (1) Date units */
$units['year'] = intval(date('Y')) - $units['year'];
$units['month'] = intval(date('m')) - $units['month'];
$units['day'] = intval(date('d')) - $units['day'];
/* (2) Time units */
$units['hour'] = intval(date('H')) - $units['hour'];
$units['minute'] = intval(date('i')) - $units['minute'];
$units['second'] = intval(date('s')) - $units['second'];
/* [3] Return significative relative time
=========================================================*/
/* (1) Date units */
if( $units['year'] > 0 ) return [ $units['year'], 'Y' ];
if( $units['month'] > 0 ) return [ $units['month'], 'm' ];
if( $units['day'] > 0 ) return [ $units['day'], 'd' ];
/* (2) Time units */
if( $units['hour'] > 0 ) return [ $units['hour'], 'H' ];
if( $units['minute'] > 0 ) return [ $units['minute'], 'i' ];
if( $units['second'] > 0 ) return [ $units['second'], 's' ];
/* (3) Default value */
return [0, '.'];
}
}

View File

@ -0,0 +1,70 @@
{% block search_bar %} <input type='text' class='searchbar' placeholder='Recherche'> {% endblock %}
{% block history_list %}
{% for entry in core.get_history() %}
{% block header %}
{% if loop.index == 1 %}
<article class='inline-row' style='border: 0; box-shadow: none;background: transparent;'>
<span>Machine</span>
<span>Dernière utilisation</span>
<span>Utilisateur</span>
<span>Action</span>
<span>Historique détaillé</span>
</article>
{% endif %}
{% endblock %}
{% block entry %}
{% block entry_tag %} <article class='inline-row' id='{{ entry.id_history }}'> {% endblock %}
{% block entry_machine %} <span data-machine='{{ entry.id_machine }}' class='title'><span>#{{ entry.machine_name }}</span></span> {% endblock %}
{% block entry_time %}
<span>
<span>{{ core.ts_format(entry.timestamp) }}</span>
<span style='color:#aaa;'>Il y a {{ core.ts_relative(entry.timestamp) }}</span>
</span>
{% endblock %}
{% block entry_user %}
<span data-user='{{ entry.id_user }}'>
<span>{{ entry.user_name }}</span>
<span style='color:#aaa;'>{{ entry.user_firstname }} {{ entry.user_lastname }}</span>
</span>
{% endblock %}
{% block entry_action %}
<span>
<span>{{ entry.action_name }}</span>
</span>
{% endblock %}
{% block entry_details %}
<span>
<button class='search' data-details='{{ entry.id_history }}'>Détails</button>
</span>
{% endblock %}
</article>
{% endblock %}
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,12 @@
<?php
namespace view\machine\form\create;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,17 @@
{% block form_tag %} <form class='valid'> {% endblock %}
{% block input %}
<input id='create_name' type='text' placeholder='Name'><br>
<span class='error-msg create_name'></span><br>
{% endblock %}
{% block submit %}
<button id='create_submit'>Créer</button>
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\machine\form\edit;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,43 @@
{% block form_tag %} <form class='neutral'> {% endblock %}
<!-- Recherche de machine -->
{% block search %}
{% block search_input %}
<input id='edit_search_keyword' type='text' class='search' placeholder='Recherche...'><br>
<input id='edit_search_id' type='hidden' value=''>
{% endblock %}
<!-- Indice du resultat -->
{% block search_submit %}
<span class='edit_search_view'>machine <span class='edit_search_num'>0</span> sur <span class='edit_search_sum'>0</span></span><br><br>
<button id='edit_search_submit' class='search'>Trouver/Suivant</button><br>
{% endblock %}
{% endblock %}
<br><br><hr class='OR' data-label='PUIS' /><br><br>
<!-- Modification de machine -->
{% block edit %}
{% block edit_input %}
<input id='edit_name' type='text' placeholder='Name'><br>
<span class='error-msg edit_name'></span><br>
{% endblock %}
{% block edit_submit %}
<button id='edit_submit' disabled>Modifier</button>
{% endblock %}
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\machine\form\remove;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,41 @@
{% block form_tag %} <form class='invalid'> {% endblock %}
<!-- Recherche de machine -->
{% block search %}
{% block search_input %}
<input id='remove_search_keyword' type='text' class='search' placeholder='Recherche...'><br>
<input id='remove_search_id' type='hidden' value=''>
{% endblock %}
<!-- Indice du resultat -->
{% block search_submit %}
<span class='remove_search_view'>machine <span class='remove_search_num'>0</span> sur <span class='remove_search_sum'>0</span></span><br><br>
<button id='remove_search_submit' class='search'>Trouver/Suivant</button><br>
{% endblock %}
{% endblock %}
<br><br><hr class='OR' data-label='PUIS' /><br><br>
<!-- Suppression de machine -->
{% block edit %}
{% block edit_input %}
<input id='remove_name' type='text' placeholder='Name'><br>
{% endblock %}
{% block edit_submit %}
<button id='remove_submit' disabled>Supprimer</button>
{% endblock %}
{% endblock %}
</form>

View File

@ -0,0 +1,87 @@
<?php
namespace view\machine\group;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
/* (1) Attributes
---------------------------------------------------------*/
public $icon;
public $theme;
public function __construct(){
/* (1) Setup attributes
---------------------------------------------------------*/
/* (1) Fill attributes */
$this->icon = [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'device' => file_get_contents( __PUBLIC__.'/src/static/menu-side/device.svg' ),
'group' => file_get_contents( __PUBLIC__.'/src/static/container/group.svg' ),
'option' => file_get_contents( __PUBLIC__.'/src/static/container/option.svg' )
];
$this->theme = $_SESSION['WAREHOUSE']['theme'];
}
public function get_clusters(){
$request = new Request('clusterDefault/getAll', [
'class' => 1
]);
$answer = $request->dispatch();
// si erreur, on affiche rien par défaut
if( $answer->error->get() != Err::Success )
return [];
return $answer->get('clusters');
}
public function get_members($id_cluster){
$usersReq = new Request('clusterDefault/getMembers', [
'id_cluster' => (int) $id_cluster,
'class' => 1
]);
$usersRes = $usersReq->dispatch();
// si erreur, on affiche rien par défaut
if( $usersRes->error->get() != Err::Success )
return [];
return $usersRes->get('members');
}
public function get_options($id_cluster){
$modReq = new Request('clusterDefault/getEtrees', [
'id_machine_cluster' => (int) $id_cluster
]);
$modRes = $modReq->dispatch();
// si erreur, on affiche rien par défaut
if( $modRes->error->get() != Err::Success )
return [];
return $modRes->get('etrees');
}
}

View File

@ -0,0 +1,82 @@
{% block search_bar %} <input type='text' class='searchbar' placeholder='Recherche'> {% endblock %}
{% block group_list %}
{% for cluster in core.get_clusters() %}
{% block group_card %}
{% block card_tag %} <article class='inline-box' id='{{ cluster.id_machine_cluster }}'> {% endblock %}
{% set machinelist = core.get_members(cluster.id_machine_cluster) %}
{% block card_title %} <span class='title' style='color: {{ core.theme }}'>{{ cluster.name }}</span> {% endblock %}
{% block card_remove %} <span class='link_remove' data-cluster='{{ cluster.id_machine_cluster }}'>{{ core.icon.remove | raw }}</span> {% endblock %}
{% block card_edit %} <span class='link_edit' data-cluster='{{ cluster.id_machine_cluster }}'>{{ core.icon.edit | raw }}</span> {% endblock %}
{# To be patched #}
{% block card_patch %}{% endblock %}
{% block card_count %}
<span class='code'>
{{ core.icon.device | raw }}
<span>{{ machinelist | length }} machines</span>
</span>
{% endblock %}
{% block card_option %}
<span class='option'>
{{ core.icon.option | raw }}
{% for option in core.get_options(cluster.id_machine_cluster) %}
<span class='ignore'>
<span>{{ option.name }}:{{ option.daemon }}</span>
</span>
{% else %}
<span class='ignore'>Aucune option</span>
{% endfor %}
</span>
{% endblock %}
{% block card_members %}
<span class='groups'>
{{ core.icon.group | raw }}
<span class='ignore'>
{% for machine in machinelist %}
<span>
{{ machine.name }}
<span class='rem-member' data-member='{{ machine.id_machine }}' data-cluster='{{ cluster.id_machine_cluster }}'></span>
</span>
{% endfor %}
</span>
<span class='add-member' data-cluster='{{ cluster.id_machine_cluster }}'>+</span>
</span>
{% endblock %}
</article>
{% endblock %}
{# if no result #}
{% else %}
{% block no_result %}
<article class='inline-box'>
<span>Aucun groupe machine trouvé.</span>
</article>
{% endblock %}
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,82 @@
<?php
namespace view\machine\view;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
/* (1) Attributes
---------------------------------------------------------*/
public $icon;
public $theme;
public function __construct(){
/* (1) Setup attributes
---------------------------------------------------------*/
/* (1) Fill attributes */
$this->icon = [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'group' => file_get_contents( __PUBLIC__.'/src/static/container/group.svg' ),
'motor' => file_get_contents( __PUBLIC__.'/src/static/container/motor.svg' )
];
$this->theme = $_SESSION['WAREHOUSE']['theme'];
}
public function get_machines(){
$request = new Request('machineDefault/getAll'); // On utilise la methode 'getAll' du module 'machineDefault'
$answer = $request->dispatch(); // On recupere la reponse
// si erreur, on affiche rien par défaut
if( $answer->error->get() != Err::Success )
return [];
return $answer->get('machines');
}
public function get_state($id_machine){
/* (1) Write / Execute request */
$req = new Request('machineDefault/getState', [
'id_machine' => $id_machine
]);
$res = $req->dispatch();
/* (2) Manage error */
if( $res->error->get() != Err::Success )
return 'detached';
return $res->get('state');
}
public function get_clusters($id_machine){
$request = new Request('machineDefault/getClusters', [
'id_machine' => (int) $id_machine
]);
$answer = $request->dispatch();
// si erreur, on affiche rien par défaut
if( $answer->error->get() != Err::Success )
return [];
return $answer->get('clusters');
}
}

View File

@ -0,0 +1,60 @@
{% block search_bar %} <input type='text' class='searchbar' placeholder='Recherche'> {% endblock %}
{% block machine_list %}
{% for machine in core.get_machines() %}
{% block machine_card %}
{% block card_tag %} <article class='inline-box' id='{{ machine.id_machine }}'> {% endblock %}
{% block card_state %} <span class='state' data-state='{{ core.get_state(machine.id_machine) }}'></span> {% endblock %}
{% block card_title %} <span class='title' style='color: {{ core.theme }}' title='{{ machine.ap | default('?') }} ({{ machine.ip | default('?') }})'>{{ machine.name }} <span>#{{ machine.name }}</span></span> {% endblock %}
{% block card_remove %} <span class='link_remove' data-machine='{{ machine.id_machine }}'>{{ core.icon.remove | raw }}</span> {% endblock %}
{% block card_edit %} <span class='link_edit' data-machine='{{ machine.id_machine }}'>{{ core.icon.edit | raw }}</span> {% endblock %}
{# To be patched #}
{% block card_motheure_patch %}{% endblock %}
{% block card_group %}
<span class='groups'>
{{ core.icon.group | raw }}
{% block group_list %}
<span class='ignore'>
{% for cluster in core.get_clusters(machine.id_machine) %}
<span>
{% block group_name %} {{ cluster.name }} {% endblock %}
<span class='rem-group' data-group='{{ cluster.id_machine_cluster }}' data-machine='{{ machine.id_machine }}'></span>
</span>
{% endfor %}
</span>
{% endblock %}
<span class='add-group' data-machine='{{ machine.id_machine }}'>+</span>
</span>
{% endblock %}
</article>
{% endblock %}
{# if no result #}
{% else %}
{% block no_result %}
<article class='inline-box'>
<span>Aucune machine trouvée</span>
</article>
{% endblock %}
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,36 @@
<?php
namespace view\machine\view;
use \generic\core\i_patch;
use \api\core\Request;
use \error\core\Err;
class motheure extends i_patch{
/* (1) Attributes
---------------------------------------------------------*/
public $patch = [
'card_motheure_patch' => 'motheure_count.twig'
];
public function get_motheure($id_machine){
/* (1) Get its machine_clusters
---------------------------------------------------------*/
/* (1) Create request */
$motheureReq = new Request('motheure/getCount', ['id_machine' => $id_machine]);
/* (2) Execute */
$motheureRes = $motheureReq->dispatch();
/* (3) Manage error */
if( $motheureRes->error->get() != Err::Success )
return null;
return $motheureRes->get('count');
}
}

View File

@ -0,0 +1,10 @@
{% set motheure = patch.motheure.get_motheure(machine.id_machine) %}
{% if motheure %}
<span class='motheure'>
{{ core.icon.motor | raw }}
<span>{{ motheure }}</span>ms
</span>
{% endif %}

View File

@ -0,0 +1,12 @@
<?php
namespace view\profile\password;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,22 @@
{% block form_tag %} <form class='search'> {% endblock %}
{% block input %}
<input id='old_pwd' type='password' placeholder='Mot de passe actuel'><br>
<span class='error-msg old_pwd'></span><br>
<input id='new_pwd' type='password' placeholder='Nouveau mot de passe'><br>
<span class='error-msg new_pwd'></span><br>
<input id='confirm_pwd' type='password' placeholder='Confirmation'><br>
<span class='error-msg confirm_pwd'></span><br>
{% endblock %}
{% block submit %}
<button id='update_pwd'>Mettre à jour</button>
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\profile\view;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1 @@
<span class='in-dev'>In development.. This feature will soon be available.</span>

View File

@ -0,0 +1,12 @@
<?php
namespace view\settings\admin\create;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,25 @@
{% block form_tag %} <form class='valid'> {% endblock %}
{% block input %}
<input id='admin_username' type='text' placeholder='Identifiant'><br>
<span class='error-msg admin_username'></span><br>
<input id='admin_mail' type='text' placeholder='Adresse mail'><br>
<span class='error-msg admin_mail'></span><br>
{% endblock %}
{% block generated %}
<input id='admin_password' type='text' placeholder='Mot de passe généré...'><br>
{% endblock %}
{% block submit %}
<button id='admin_submit'>Créer l'administrateur</button>
{% endblock %}
</form>

View File

@ -0,0 +1,49 @@
<?php
namespace view\settings\admin\view;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
/* (1) Attributes
---------------------------------------------------------*/
public $icon;
public $theme;
public $self_id;
public function __construct(){
/* (1) Setup attributes
---------------------------------------------------------*/
/* (1) Fill attributes */
$this->icon = [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' )
];
$this->theme = $_SESSION['WAREHOUSE']['theme'];
$this->self_id = $_SESSION['ADMIN']['id'];
}
public function get_admins(){
/* (1) On exécute la requête */
$adminListRq = new Request('adminDefault/getAll');
/* (2) On recupere la reponse */
$adminListRs = $adminListRq->dispatch();
/* (3) si erreur vide */
if( $adminListRs->error->get() != Err::Success )
return [];
/* (4) On récupère la liste des utilisateurs */
return $adminListRs->get('admins');
}
}

View File

@ -0,0 +1,29 @@
{% for admin in core.get_admins() %}
{% block entry %}
{% block entry_tag %} <article class='inline-row' id='{{ admin.id_admin }}'> {% endblock %}
{% block entry_name %} <span data-admin='{{ admin.id_admin }}' class='title'><span style='color: {{ core.theme }};'>{{ admin.username }}</span></span> {% endblock %}
{% block entry_mail %}
<span>
<span>{{ admin.mail }}</span>
</span>
{% endblock %}
{% block link_remove %}
<span>
<span class='link_remove list' data-admin='{{ admin.id_admin }}'>{{ core.icon.remove | raw }}</span>
</span>
{% endblock %}
</article>
{% endblock %}
{% endfor %}

View File

@ -0,0 +1,12 @@
<?php
namespace view\settings\password;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,22 @@
{% block form_tag %} <form class='search'> {% endblock %}
{% block input %}
<input id='old_pwd' type='password' placeholder="Code d'accès actuel"><br>
<span class='error-msg old_pwd'></span><br>
<input id='new_pwd' type='password' placeholder="Nouveau code d'accès"><br>
<span class='error-msg new_pwd'></span><br>
<input id='confirm_pwd' type='password' placeholder='Confirmation'><br>
<span class='error-msg confirm_pwd'></span><br>
{% endblock %}
{% block submit %}
<button id='update_pwd'>Mettre à jour</button>
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\settings\view;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1 @@
<span class='in-dev'>In development.. This feature will soon be available.</span>

View File

@ -0,0 +1,12 @@
<?php
namespace view\user\form\create;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,28 @@
{% block form_tag %} <form class='valid'> {% endblock %}
{% block input %}
<input id='create_code' type='text' placeholder='CO-DE-RF-ID'><br>
<span class='error-msg create_code'></span><br>
<input id='create_username' type='text' placeholder='Username'><br>
<span class='error-msg create_username'></span><br>
<input id='create_firstname' type='text' placeholder='Firstname'><br>
<span class='error-msg create_firstname'></span><br>
<input id='create_lastname' type='text' placeholder='Lastname'><br>
<span class='error-msg create_lastname'></span><br>
<input id='create_mail' type='text' placeholder='Mail'><br>
<span class='error-msg create_mail'></span><br>
{% endblock %}
{% block submit %}
<button id='create_submit'>Créer</button>
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\user\form\edit;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,55 @@
{% block form_tag %} <form class='neutral'> {% endblock %}
<!-- Recherche d'utilisateur -->
{% block search %}
{% block search_input %}
<input id='edit_search_keyword' type='text' class='search' placeholder='Recherche...'><br>
<input id='edit_search_id' type='hidden' value=''>
{% endblock %}
<!-- Indice du resultat -->
{% block search_submit %}
<span class='edit_search_view'>utilisateur <span class='edit_search_num'>0</span> sur <span class='edit_search_sum'>0</span></span><br><br>
<button id='edit_search_submit' class='search'>Trouver/Suivant</button><br>
{% endblock %}
{% endblock %}
<br><br><hr class='OR' data-label='PUIS' /><br><br>
<!-- Modification d'utilisateur -->
{% block edit %}
{% block edit_input %}
<input id='edit_code' type='text' placeholder='CO-DE-RF-ID'><br>
<span class='error-msg edit_code'></span><br>
<input id='edit_username' type='text' placeholder='Username'><br>
<span class='error-msg edit_username'></span><br>
<input id='edit_firstname' type='text' placeholder='Firstname'><br>
<span class='error-msg edit_firstname'></span><br>
<input id='edit_lastname' type='text' placeholder='Lastname'><br>
<span class='error-msg edit_lastname'></span><br>
<input id='edit_mail' type='text' placeholder='Mail'><br>
<span class='error-msg edit_mail'></span><br>
{% endblock %}
{% block edit_submit %}
<button id='edit_submit' disabled>Modifier</button>
{% endblock %}
{% endblock %}
</form>

View File

@ -0,0 +1,12 @@
<?php
namespace view\user\form\remove;
use \generic\core\i_view;
class main extends i_view{
public function __construct(){}
}

View File

@ -0,0 +1,46 @@
{% block form_tag %} <form class='invalid'> {% endblock %}
<!-- Recherche d'utilisateur -->
{% block search %}
{% block search_input %}
<input id='remove_search_keyword' type='text' class='search' placeholder='Recherche...'><br>
<input id='remove_search_id' type='hidden' value=''>
{% endblock %}
<!-- Indice du resultat -->
{% block search_submit %}
<span class='remove_search_view'>utilisateur <span class='remove_search_num'>0</span> sur <span class='remove_search_sum'>0</span></span><br><br>
<button id='remove_search_submit' class='search'>Trouver/Suivant</button><br>
{% endblock %}
{% endblock %}
<br><br><hr class='OR' data-label='PUIS' /><br><br>
<!-- Suppression d'utilisateur -->
{% block remove %}
{% block remove_input %}
<input id='remove_code' type='text' placeholder='Code'><br>
<span class='error-msg remove_code'></span><br>
<input id='remove_username' type='text' placeholder='Username'><br>
<span class='error-msg remove_username'></span><br>
{% endblock %}
{% block remove_submit %}
<button id='remove_submit' disabled>Supprimer</button>
{% endblock %}
{% endblock %}
</form>

View File

@ -0,0 +1,68 @@
<?php
namespace view\user\group;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
/* (1) Attributes
---------------------------------------------------------*/
public $icon;
public $theme;
public function __construct(){
/* (1) Setup attributes
---------------------------------------------------------*/
/* (1) Fill attributes */
$this->icon = [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'type' => file_get_contents( __PUBLIC__.'/src/static/container/type.svg' ),
'group' => file_get_contents( __PUBLIC__.'/src/static/container/group.svg' )
];
$this->theme = $_SESSION['WAREHOUSE']['theme'];
}
public function get_clusters(){
$request = new Request('clusterDefault/getAll', [
'class' => 0
]);
$answer = $request->dispatch();
// si erreur, on affiche rien par défaut
if( $answer->error->get() != Err::Success )
return [];
return $answer->get('clusters');
}
public function get_members($id_cluster){
$usersReq = new Request('clusterDefault/getMembers', [
'id_cluster' => (int) $id_cluster,
'class' => 0
]);
$usersRes = $usersReq->dispatch();
// si erreur, on affiche rien par défaut
if( $usersRes->error->get() != Err::Success )
return [];
return $usersRes->get('members');
}
}

View File

@ -0,0 +1,65 @@
{% block search_bar %} <input type='text' class='searchbar' placeholder='Recherche'> {% endblock %}
{% block group_list %}
{% for cluster in core.get_clusters() %}
{% block group_card %}
{% block card_tag %} <article class='inline-box' id='{{ cluster.id_user_cluster }}'> {% endblock %}
{% set userlist = core.get_members(cluster.id_user_cluster) %}
{% block card_title %} <span class='title' style='color: {{ core.theme }}'>{{ cluster.name }}</span> {% endblock %}
{% block card_remove %} <span class='link_remove' data-cluster='{{ cluster.id_user_cluster }}'>{{ core.icon.remove | raw }}</span> {% endblock %}
{% block card_edit %} <span class='link_edit' data-cluster='{{ cluster.id_user_cluster }}'>{{ core.icon.edit | raw }}</span> {% endblock %}
{% block card_count %}
<span class='code'>
{{ core.icon.type | raw }}
<span>{{ userlist | length }} utilisateurs</span>
</span>
{% endblock %}
{% block card_members %}
<span class='groups'>
{{ core.icon.group | raw }}
<span class='ignore'>
{% for user in userlist %}
<span>
{{ user.username }}
<span class='rem-member' data-member='{{ user.id_user }}' data-cluster='{{ cluster.id_user_cluster }}'></span>
</span>
{% endfor %}
</span>
<span class='add-member' data-cluster='{{ cluster.id_user_cluster }}'>+</span>
</span>
{% endblock %}
</article>
{% endblock %}
{# if no result #}
{% else %}
{% block no_result %}
<article class='inline-box'>
<span>Aucun groupe utilisateur trouvé.</span>
</article>
{% endblock %}
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,63 @@
<?php
namespace view\user\view;
use \generic\core\i_view;
use \api\core\Request;
use \error\core\Err;
class main extends i_view{
/* (1) Attributes
---------------------------------------------------------*/
public $icon;
public $theme;
public function __construct(){
/* (1) Setup attributes
---------------------------------------------------------*/
/* (1) Fill attributes */
$this->icon = [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'card' => file_get_contents( __PUBLIC__.'/src/static/container/card.svg' ),
'mail' => file_get_contents( __PUBLIC__.'/src/static/container/mail.svg' ),
'group' => file_get_contents( __PUBLIC__.'/src/static/container/group.svg' )
];
$this->theme = $_SESSION['WAREHOUSE']['theme'];
}
public function get_users(){
$request = new Request('userDefault/getAll'); // On utilise la methode 'getAll' du module 'userDefault'
$answer = $request->dispatch(); // On recupere la reponse
// si erreur, on affiche rien
if( $answer->error->get() != Err::Success )
return [];
return $answer->get('users');
}
public function get_clusters($id_user){
$clustersReq = new Request('userDefault/getClusters', [ 'id_user' => $id_user ]);
$clustersRes = $clustersReq->dispatch();
/* (2) Gestion si erreur */
if( $clustersRes->error->get() != Err::Success )
return [];
return $clustersRes->get('clusters');
}
}

View File

@ -0,0 +1,80 @@
{% block search_bar %} <input type='text' class='searchbar' placeholder='Recherche'> {% endblock %}
{% block user_list %}
{% for user in core.get_users() %}
{% block user_card %}
{% block card_tag %} <article class='inline-box' id='{{ user.id_user }}'> {% endblock %}
{% block card_title %} <span class='title' style='color: {{ core.theme }}'>{{ user.firstname }} {{ user.lastname }} <span>#{{ user.username }}</span></span> {% endblock %}
{% block card_remove %} <span class='link_remove' data-user='{{ user.id_user }}'>{{ core.icon.remove | raw }}</span> {% endblock %}
{% block card_edit %} <span class='link_edit' data-user='{{ user.id_user }}'>{{ core.icon.edit | raw }}</span> {% endblock %}
{% block card_code %}
<span class='code'>
{{ core.icon.card | raw }}
<span>{{ user.code }}</span>
</span>
{% endblock %}
{% block card_mail %}
<span class='mail'>
{{ core.icon.mail | raw }}
<a href='mailto:{{ user.mail }}'>
<span>{{ user.mail }}</span>
</a>
</span>
{% endblock %}
{% block card_groups %}
<span class='groups'>
{{ core.icon.group | raw }}
{% block group_list %}
<span class='ignore'>
{% for cluster in core.get_clusters(user.id_user) %}
<span>
{% block group_name %} {{ cluster.name }} {% endblock %}
<span class='rem-group' data-group='{{ cluster.id_user_cluster }}' data-user='{{ user.id_user }}'></span>
</span>
{% endfor %}
</span>
{% endblock %}
<span class='add-group' data-user='{{ user.id_user }}'>+</span>
</span>
{% endblock %}
</article>
{% endblock %}
{# if no result #}
{% else %}
{% block no_result %}
<article class='inline-box'>
<span>Aucun utilisateur trouvé</span>
</article>
{% endblock %}
{% endfor %}
{% endblock %}

View File

@ -42,7 +42,7 @@
/* [2] Define headers /* [2] Define headers
=========================================================*/ =========================================================*/
$this->headers = \getallheaders(); $this->headers = self::getallheaders_adapter();
/* [3] Define default datasets (GET, POST) /* [3] Define default datasets (GET, POST)
@ -201,4 +201,30 @@
public function HEADERS(){ return $this->headers; } public function HEADERS(){ return $this->headers; }
public function METHOD(){ return $this->method; } public function METHOD(){ return $this->method; }
public function URI(){ return $this->uri; } public function URI(){ return $this->uri; }
private static function getallheaders_adapter(){
/* (1) If exists -> use it
---------------------------------------------------------*/
if( function_exists('getallheaders') )
return getallheaders();
/* (2) If does not (php-fpm)
---------------------------------------------------------*/
/* (1) init. variables */
$fetched_headers = [];
/* (2) Get all headers from $_SERVER */
foreach($_SERVER as $hname=>$hvalue ){
// {1} Store only if begins with 'HTTP_' //
if( substr($hname,0,5) == 'HTTP_' )
$fetched_headers[ str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($hname,5)))))] = $hvalue;
}
/* (3) Return created headers */
return $fetched_headers;
}
} }

134
build/log/core/FileDriver.php Executable file
View File

@ -0,0 +1,134 @@
<?php
namespace log\core;
class FileDriver{
/* CREATES A FILE WITH ITS NEEDED DIRECTORIES
*
* @path<String> Path of the needed file
*
* @return created<Boolean> If the file has been created successfully
*
*/
public static function create($file){
/* (0) Checks arguments */
if( !is_string($file) || is_dir($file) )
return false;
/* (1) Creates file */
try{
return fclose( fopen($file, 'w') );
}catch(\Exception $e){ return false; }
}
/* READS FILE'S CONTENT
*
* @file<String> File to read
*
*/
public static function read($file){
/* (0) Checks arguments */
if( !is_string($file) )
throw new \Exception('Wrong argument for read(<String>).');
/* (1) Initializing driver on file (read-flag) */
$driver = new \SplFileObject($file, 'r');
/* (2) Read lines */
$read = '';
$line = 0;
while( $driver->current() ){
$read .= $driver->current();
$driver->next();
}
/* (3) Returns result */
return $read;
}
/* READS A FILE'S SPECIFIC LINE
*
* @file<String> File to read
* @line<int> Line to read
*
*/
public static function readline($file, $line){
/* (0) Checks arguments */
if( !is_string($file) || intval($line) !== $line )
throw new \Exception('Wrong argument for readline(<String>, <int>).');
/* (1) Initializing driver on file (read-flag) */
$driver = new \SplFileObject($file, 'r');
/* (2) Goto specific line */
$driver->seek($line);
/* (3) Return line's content */
if( $driver->key() == $line )
return $driver->current();
else
return null;
}
/* WRITES CONTENT TO A FILE
*
* @file<String> File to write to
* @content<String> Content to write
*
* @return written<Boolean> Returns if the content have been written successfully
*
* @note: Creates file if it is possible with `fopen()`
*
*/
public static function write($file, $content){
/* (0) Checks arguments */
if( !is_string($file) || !is_string($content) )
return false;
/* (1) Erase file */
try{
fclose( fopen($file, 'w') );
}catch(\Exception $e){ return false; }
/* (2) Get driver (write-flag) */
$driver = new \SplFileObject($file, 'r+');
/* (3) Writes content */
return !is_null( $driver->fwrite($content) );
}
/* APPENDS CONTENT TO A FILE
*
* @file<String> File to append content to
* @content<String> Content to append
*
* @return append<Boolean> Returns if the content have been append successfully
*
* @note: If file doesn't exists, returns false
*
*/
public static function append($file, $content){
/* (0) Checks arguments */
if( !is_file($file) || !is_string($content) )
return false;
/* (1) Get driver (append-flag) */
$driver = new \SplFileObject($file, 'a');
/* (2) append content */
return !is_null( $driver->fwrite($content.PHP_EOL) );
}
}
?>

83
build/log/core/Log.php Executable file
View File

@ -0,0 +1,83 @@
<?php
namespace log\core;
class Log{
private static $maxlen = 50;
/* [1] Attributes
=========================================================*/
private $label; // label of the log system
private $file; // absolute path to logfile
/* [2] Constructor
*
* @label<String> Label of the logger
*
=========================================================*/
private function __construct($label){
/* (1) Set logfile and label */
$this->label = $label;
$this->file = __BUILD__."/log/log/$label.log";
/* (2) Create file if doesn't exist already */
if( !is_file($this->file) )
FileDriver::create($this->file);
}
/* [3] Writes a new log to the file
*
* @content<String> Content to log
* @tag<String> [OPT] Tag of the log (category)
*
* @return outputname<outputtype> outputdesc
*
=========================================================*/
public function log($content="...", $tag="default"){
/* (1) Get time data */
$timestamp = time();
$date = date('Y-m-s H:i:s', $timestamp);
/* (2) Create beginning string */
$body = "$timestamp | $date | [$tag] ";
$headerl = strlen($body);
/* (3) Split content by length */
$body .= substr($content, 0, self::$maxlen);
for( $i = self::$maxlen, $l = strlen($content) ; $i < $l ; $i += self::$maxlen )
$body .= "\n".str_repeat(" ", $headerl).substr($content, $i, self::$maxlen);
/* (4) Append to log file */
FileDriver::append($this->file, $body);
}
/* [4] Multiton attributes
=========================================================*/
private static $instance = []; // instances
/* [5] Multiton Manager
*
* @label<String> Label of the logger you want
*
* @return instance<Log> instance of the wanted logger
*
=========================================================*/
public static function get($label="default"){
/* (1) Create if doesn't exist */
if( !isset(self::$instance[$label]) )
self::$instance[$label] = new Log($label);
/* (2) Return instance for all cases */
return self::$instance[$label];
}
}

View File

@ -237,7 +237,7 @@
/* [3] If `IN` condition /* [3] If `IN` condition
=========================================================*/ =========================================================*/
$defaultWhere = $this->where; $defaultWhere = $this->where;
$inCond = count($args[0]) > 1 && is_array($args[0][0]) && $args[0][1] == self::COND_IN; $inCond = is_array($args[0]) && count($args[0]) > 1 && is_array($args[0][0]) && $args[0][1] == self::COND_IN;
// erreur // erreur
if( is_array($args[0][0]) && !$inCond ) if( is_array($args[0][0]) && !$inCond )

View File

@ -132,7 +132,10 @@
/* [1] On construit la requête /* [1] On construit la requête
=========================================================*/ =========================================================*/
/* (1) Chamo */ /* (1) Chamo */
$sql .= $field[0].'.'.$field[1].' '; if( $value[1] == Rows::COND_LIKE ) // make LIKE lowercase
$sql .= 'LOWER('.$field[0].'.'.$field[1].') ';
else
$sql .= $field[0].'.'.$field[1].' ';
/* (2) Opérateur */ /* (2) Opérateur */
$sql .= substr($value[1], 2, -2).' '; $sql .= substr($value[1], 2, -2).' ';

View File

@ -18,6 +18,10 @@ class Router{
* *
*/ */
public function __construct($url){ public function __construct($url){
// Format URI (ne doit pas avoir le premier '/')
if( preg_match("@^/@", $url) )
$url = substr($url, 1);
$this->url = $url; $this->url = $url;
// On initialise les routes // On initialise les routes

View File

@ -0,0 +1,302 @@
<?php
namespace token\core;
class TreeToken{
private static $DEBUG = false;
private $secret = null;
private $step = 0;
private $max_step = 0;
private static $salt = '_9284 we;\'sa';
private static $pepper = 'dasklj3948\'3=2';
private $sync = null;
/* (1) Constructs a new TreeToken
*
* @max_step<int> Max. number of children tokens
*
---------------------------------------------------------*/
public function __construct($max_step=100){
/* (1) Check argument */
if( abs(intval($max_step)) !== $max_step || $max_step < 0 )
throw new \Exception('Invalid argument type.');
/* (2) Manage session */
if( session_status() != PHP_SESSION_ACTIVE )
\session_start();
/* (3) Set attributes */
$this->max_step = $max_step+1;
}
/* (2) Gets the existing parent
*
* @return status<bool> TRUE: right parent + token
* FALSE: Invalid token
* NULL: No parent found
*
---------------------------------------------------------*/
private function check_parent(){
/* (1) Check system state
---------------------------------------------------------*/
$has_token = isset($_COOKIE['_PUBLIC_']) && preg_match( '/^[a-z0-9]{128}$/i', $_COOKIE['_PUBLIC_'] );
$has_parent = isset($_SESSION['_PRIVATE_']) && preg_match( '/^([a-z0-9]{128})\.(\d+)$/i', $_SESSION['_PRIVATE_'], $p_match );
/* (1) If no parent -> NULL */
if( !$has_parent )
return null;
/* (2) But if no token -> FALSE */
if( !$has_token )
return false;
if( self::$DEBUG ){
echo "* PARENT RECEIVED *\n";
echo 'sess_id: '.session_id()."\n";
echo 'pub: '.$_COOKIE['_PUBLIC_']."\n";
echo 'priv: '.$_SESSION['_PRIVATE_']."\n";
}
/* (2) Check parent token
---------------------------------------------------------*/
/* (1) Check public token */
if( self::tgen($p_match[1], $this->max_step) !== $_COOKIE['_PUBLIC_'] ){
if( self::$DEBUG )
echo "<b>/!\ invalid parent pub (token)</b>\n";
return false;
}
/* (2) Inherit parent properties */
$this->secret = $p_match[1];
$this->step = $p_match[2];
/* (3) If valid token */
if( self::$DEBUG )
echo "[ <b>Valid parent pub (token)</b> ]\n";
return true;
}
/* (3) Create or regenerate a parent
*
* @inName<inType> inDesc
*
* @return outName<outType> outDesc
*
---------------------------------------------------------*/
public function init_parent(){
/* (1) Check parent
---------------------------------------------------------*/
/* (1) Process check */
$valid_parent = $this->check_parent();
/* (2) If invalid parent -> destroy session */
if( $valid_parent === false ){
if( self::$DEBUG )
echo "-> new session <-\n";
\session_regenerate_id(true); // true: delete old session
\session_unset();
\session_destroy();
\session_start();
}
/* (2) Init new parent
---------------------------------------------------------*/
/* (1) Choose new secret */
$this->secret = self::tgen(uniqid());
/* (2) Set step = max */
$this->step = $this->max_step;
/* (3) Generate PRIVATE */
$_SESSION['_PRIVATE_'] = $this->secret.'.'.$this->max_step;
/* (4) Generate PUBLIC */
$_COOKIE['_PUBLIC_'] = self::tgen($this->secret, $this->max_step);
setcookie('_PUBLIC_', $_COOKIE['_PUBLIC_'], time()+30*60, '/');
if( self::$DEBUG ){
echo "\n* PARENT UPDATED *\n";
echo 'sess_id: '.session_id()."\n";
echo 'pub: '.$_COOKIE['_PUBLIC_']."\n";
echo 'priv: '.$_SESSION['_PRIVATE_']."\n";
}
/* (5) Granted */
return $valid_parent !== false;
}
/* (4) Checks a child
*
* @return status<bool> TRUE: Valid child
* FALSE: Invalid token
*
---------------------------------------------------------*/
private function check_child(){
/* (1) Check the parent
---------------------------------------------------------*/
/* (1) Process parent check */
$valid_parent = $this->check_parent();
/* (2) Manage missing OR invalid parent */
if( $valid_parent !== true )
return false;
/* (2) Check system state
---------------------------------------------------------*/
$has_token = !is_null(self::getTreeToken()) && preg_match( '/^[a-z0-9]{128}$/i', self::getTreeToken() );
/* (1) If no token -> false */
if( !$has_token )
return false;
/* (3) Check child token
---------------------------------------------------------*/
/* (1) If no more steps -> false */
if( $this->step <= 1 ){
if( self::$DEBUG )
echo "<b>/!\ no more token available</b>\n";
return false;
}
if( self::$DEBUG ){
echo "* CHILD RECEIVED *\n";
echo 'sess_id: '.session_id()."\n";
echo 'token: '.self::getTreeToken()."\n";
echo 'priv: '.$this->secret.'.'.$this->step."\n";
}
/* (2) Check child token */
if( self::tgen($this->secret, $this->step) !== self::getTreeToken() ){
if( self::$DEBUG )
echo "<b>/!\ invalid child token</b>\n";
return false;
}
/* (3) If valid token */
if( self::$DEBUG )
echo "[ <b>Valid child token</b> ]\n";
return true;
}
/* (5) Updates a child
*
* @inName<inType> inDesc
*
* @return outName<outType> outDesc
*
---------------------------------------------------------*/
public function init_child(){
/* (1) Check child
---------------------------------------------------------*/
/* (1) Process check */
$valid_child = $this->check_child();
/* (2) If invalid child -> destroy session */
if( $valid_child !== true )
return false;
/* (2) Update parent for other children
---------------------------------------------------------*/
/* (1) Decrement step */
$this->step--;
if( $this->step > 1 ){ // only if it is not the last step
/* (2) Update step in session */
$_SESSION['_PRIVATE_'] = $this->secret.'.'.$this->step;
/* (3) Generate child-specific PUBLIC */
header('X-Tree-Token: '.self::tgen($this->secret, $this->step));
if( self::$DEBUG ){
echo "\n* CHILD UPDATED *\n";
echo 'sess_id: '.session_id()."\n";
echo 'token: '.self::getTreeToken()."\n";
echo 'priv: '.$_SESSION['_PRIVATE_']."\n";
}
}
/* (2) Granted */
return true;
}
/* (6) Get custom TreeToken header
*
* @return token<String> TreeToken fetched from header list
* NULL on error
*
---------------------------------------------------------*/
private static function getTreeToken(){
/* (1) Check if exsits */
if( !isset($_SERVER['HTTP_X_TREE_TOKEN']))
return null;
/* (2) Return result */
return $_SERVER['HTTP_X_TREE_TOKEN'];
}
/* (x) Generates a pseudo-rdm token
*
* @data<String> Seed to use
* @depth<int> Token depth
*
* @return token<String> @data hashed @depth times
*
---------------------------------------------------------*/
private static function tgen($data, $depth=1){
/* (0) If depth < 1 -> depth=1 */
$depth = ( $depth < 1 ) ? 1 : $depth;
/* (1) Apply salt */
$hash = self::$salt.$data;
/* (2) Hash @depth times */
for( $d = 0 ; $d < $depth ; $d++ )
$hash = ( $d == $depth-1 ) ? hash('sha512', $hash.self::$pepper) : hash('sha512', $hash);
/* (3) Return hash */
return $hash;
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace token\core;
class TreeTokenNull{
public function __construct(){}
public function init_parent(){ return true; }
public function init_child(){ return true; }
}

View File

@ -1,146 +0,0 @@
<?php
namespace viewer\core;
use \error\core\Error;
use \error\core\Err;
class Viewer{
public $error;
private $template;
private $args;
private $view;
public static $htmlError = "<span class='error'>Une erreur est survenue, veuilez contacter le webmaster si cette erreur persiste.</span>";
/* INITIALISATION DE LA VUE VUE
*
* @template<String> Nom du modèle de la vue à utiliser
* @args<Array> Données pour construire la vue à partir du modèle
*
*/
public function __construct($template, $args){
$this->error = new Error(Err::Success);
// Si pas parametre manquant, on quitte
if( $template == null ){
$this->error = new Error(Err::MissingPath);
return false;
}
/* [1] On vérifie que le template existe
=========================================================*/
$templatePath = $this->checkPath($template);
if( $templatePath === false )
return false;
/* [2] On récupère le chemin du template et on l'enregistre
=========================================================*/
$this->template = $templatePath;
/* [3] On enregistre les paramètres
=========================================================*/
$this->args = $args;
/* [4] On process la vue
=========================================================*/
$this->view = call_user_func(
$this->template,
$this->args
);
}
/* AFFICHE LA VUE CALCULEE
*
*/
public function view(){
echo $this->view;
}
/* RETOURNE LA VUE CALCULEE
*
*/
public function getView(){
return $this->view;
}
/* VERIFICATION DE L'EXISTENCE D'UN MODELE
*
* @template<String> Chemin du modèle
*
* @return status<Boolean> TRUE si le modèle existe, sinon FALSE
*
*/
private function checkPath($template){
/* [1] On vérifie le format
=========================================================*/
if( !preg_match('/^(\w+)\.(\w+)$/i', $template, $match) ){
$this->error = new Error(Err::ParamError);
return false;
}
/* [2] On vérifie que le template existe
=========================================================*/
$class = '\\viewer\\view\\'.$match[1].'\\'.$match[2];
$method = 'render';
/* (1) On vérifie que la classe existe */
if( !class_exists($class) ){
$this->error = new Error(Err::UnknownTemplate);
return false;
}
/* (2) On vérifie que la méthode existe */
if( !method_exists($class, $method) ){
$this->error = new Error(Err::UnknownTemplate);
return false;
}
/* [3] Si tout est bon, on renvoie les données
=========================================================*/
return [ $class, $method ];
}
}
// USE case
//
// $myView = new Viewer('templateParent.templateModel', [
// 'myVar' => 1,
// 'helloMsg' => 'Hello',
// ]);
//
// $myView->view();
//
?>

View File

@ -1,52 +0,0 @@
<?php
namespace viewer\view\group;
use \api\core\Request;
use \error\core\Error;
use \error\core\Err;
use \api\core\Authentification;
class group_choice{
public static function render(){
/* [1] Init Twig
=========================================================*/
$loader = new \Twig_Loader_Filesystem(__BUILD__.'/viewer/view');
$twig = new \Twig_Environment($loader, []);
/* [2] Store variables
=========================================================*/
$variables = [
'p_theme' => $_SESSION['WAREHOUSE']['theme']
];
/* [3] Store functions
=========================================================*/
$twig->addFunction(new \Twig_Function('f_clusters', function($class){
/* (1) On récupère les groupes */
$getClustersReq = new Request('clusterDefault/getAll', ['class' => $class]);
$getClusters = $getClustersReq->dispatch();
/* (2) si erreur, on retourne rien par défaut */
if( $getClusters->error->get() != Err::Success )
return [];
/* (3) On enregistre le résultat */
return $getClusters->get('clusters');
}));
/* [4] Build the whole stuff
=========================================================*/
return $twig->render('group/group_choice.twig', [
'p_icon' => $variables['p_icon'],
'p_theme' => $variables['p_theme']
]);
}
}
?>

View File

@ -1,16 +0,0 @@
<form class='neutral' action='' method='POST' id='choose-cluster'>
<select data-name='cluster'>
<option value='.' selected disabled>Groupe à modifier</option>
{% for user_cluster in f_clusters(0) %}
<option value='u{{ user_cluster.id_user_cluster }}'>{{ user_cluster.name }} (utilisateur)</option>
{% endfor %}
{% for machine_cluster in f_clusters(1) %}
<option value='m{{ machine_cluster.id_machine_cluster }}'>{{ machine_cluster.name }} (machine)</option>
{% endfor %}
</select>
<button id='choose-cluster'>Modifier la composition</button>
</form>

View File

@ -1,138 +0,0 @@
<?php
namespace viewer\view\group;
use \viewer\core\Viewer;
use \api\core\Request;
use \error\core\Err;
use \error\core\Error;
use \api\core\Authentification;
class members_choice{
public static function render($params){
/* [1] On vérifie le type de groupe (user/machine)
=========================================================*/
/* (1) On vérifie les paramètres */
if( !isset($params['id_cluster']) || !is_numeric($params['id_cluster']) || !isset($params['class']) || !is_numeric($params['class']) )
return Viewer::$htmlError;
/* (2) On récupère le groupe */
$checktypeRequest = new Request('clusterDefault/getById', [
'id_cluster' => $params['id_cluster'],
'class' => $params['class']
]);
$checktypeResponse = $checktypeRequest->dispatch();
/* (3) Si on ne le trouve pas, on retourne une erreur */
if( $checktypeResponse->error->get() != Err::Success )
return Viewer::$htmlError;
/* (4) On récupère les données du groupe */
$currentCluster = $checktypeResponse->get('cluster');
/* [2] Init Twig
=========================================================*/
$loader = new \Twig_Loader_Filesystem(__BUILD__.'/viewer/view');
$twig = new \Twig_Environment($loader, []);
/* [3] Store variables
=========================================================*/
$variables = [
'p_id_cluster' => $params['id_cluster'],
'p_class' => $params['class'],
'p_name' => $currentCluster['name'],
'p_theme' => $_SESSION['WAREHOUSE']['theme']
];
/* [4] Store functions
=========================================================*/
$twig->addFunction(new \Twig_Function('f_members', function($id_cluster, $class){
/* [1] On récupère les membres
=========================================================*/
/* (1) On exécute la requête */
$getmembersRequest = new Request('clusterDefault/getMembers', [
'id_cluster' => $id_cluster,
'class' => $class
]);
$getmembersResponse = $getmembersRequest->dispatch();
/* (2) Si erreur, on retourne rien par défaut */
if( $getmembersResponse->error->get() != Err::Success )
return [];
/* (3) On récupère la liste des UID uniquement */
$members_ids = [];
foreach($getmembersResponse->get('members') as $member)
$members_ids[] = ($class==0) ? $member['id_user'] : $member['id_machine'];
/* [2] On récupère les utilisateurs non membres
=========================================================*/
/* (1) On récupère les utilisateurs */
if( $class == 0 ){
/* (2) On exécute la requête */
$getusersRequest = new Request('userDefault/getAll');
// On recupere la reponse
$getusersResponse = $getusersRequest->dispatch();
/* (3) si erreur, on affiche l'explicitation */
if( $getusersResponse->error->get() != Err::Success )
return [];
/* (4) On récupère la liste des utilisateurs */
$users = $getusersResponse->get('users');
/* (5) On ajoute s'ils sont dans le groupe ou non */
foreach($users as $u=>$user)
$users[$u]['already'] = in_array($user['id_user'], $members_ids);
return $users;
/* [3] On récupère les machines non membres
=========================================================*/
/* (1) On récupère les machines */
}else{
/* (2) On exécute la requête */
$getmachinesRequest = new Request('machineDefault/getAll');
// On recupere la reponse
$getmachinesResponse = $getmachinesRequest->dispatch();
/* (3) si erreur, on affiche l'explicitation */
if( $getmachinesResponse->error->get() != Err::Success )
return [];
/* (4) On récupère la liste des machines */
$machines = $getmachinesResponse->get('machines');
/* (5) On ajoute s'ils sont dans le groupe ou non */
foreach($machines as $u=>$machine)
$machines[$u]['already'] = in_array($machine['id_machine'], $members_ids);
return $machines;
}
}));
/* [5] Build the whole stuff
=========================================================*/
return $twig->render('group/members_choice.twig', [
'p_class' => $variables['p_class'],
'p_name' => $variables['p_name'],
'p_id_cluster' => $variables['p_id_cluster'],
'p_theme' => $variables['p_theme']
]);
}
}
?>

View File

@ -1,50 +0,0 @@
<span style='text-align:center; color: #666; text-decoration: underline; cursor: pointer;' id='members-change-group'>Modifier un autre groupe</span>
<p></p>
<article class='check-table'>
<input type='hidden' id='members-member-idcluster' value='{{ p_id_cluster }}'>
<input type='hidden' id='members-member-class' value='{{ p_class }}'>
<div>
{# USER HEADER #}
{% if p_class == 0 %}
<span><strong>Identifiant</strong></span>
<span><strong>Nom</strong></span>
<span><strong>Code RFID</strong></span>
{# MACHINE HEADER #}
{% else %}
<span><strong>Nom</strong></span>
{% endif %}
<span><strong>Membre de <u>{{ p_name }}</u></strong></span>
</div>
{% for member in f_members(p_id_cluster, p_class) %}
{# USER ENTRIES #}
{% if p_class == 0 %}
<div>
<span>{{ member.username }}</span>
<span>{{ member.firstname }} {{ member.lastname }}</span>
<span>{{ member.code }}</span>
<span>
<input type='checkbox' value='{{ member.id_user }}' data-name='members' id='checkbox_{{ member.id_user }}' {% if member.already %}checked{% endif %}>
<label for='checkbox_{{ member.id_user }}'></label>
</span>
</div>
{# MACHINE ENTRIES #}
{% else %}
<div>
<span>{{ member.name }}</span>
<span>
<input type='checkbox' value='{{ member.id_machine }}' data-name='members' id='checkbox_{{ member.id_machine }}' {% if member.already %}checked{% endif %}>
<label for='checkbox_{{ member.id_machine }}'></label>
</span>
</div>
{% endif %}
{% endfor %}
</article>

View File

@ -1,126 +0,0 @@
<?php
namespace viewer\view\group;
use \viewer\core\Viewer;
use \api\core\Request;
use \api\core\Authentification;
use \error\core\Err;
use \error\core\Error;
class permission{
public static function render(){
debug();
/* [1] Init Twig
=========================================================*/
$loader = new \Twig_Loader_Filesystem(__BUILD__.'/viewer/view');
$twig = new \Twig_Environment($loader, []);
/* [2] Store variables
=========================================================*/
$variables = [
'p_icon' => [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'device' => file_get_contents( __PUBLIC__.'/src/static/menu-side/device.svg' ),
'permission' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/permission.svg')
],
'p_theme' => $_SESSION['WAREHOUSE']['theme']
];
/* [3] Store functions
=========================================================*/
$twig->addFunction(new \Twig_Function('f_clusters', function(){
$request = new Request('clusterDefault/getAll', [
'class' => 1
]);
$answer = $request->dispatch();
// si erreur, on affiche rien par défaut
if( $answer->error->get() != Err::Success )
return [];
return $answer->get('clusters');
}));
$twig->addFunction(new \Twig_Function('f_nbmachines', function($id_cluster){
$machineReq = new Request('clusterDefault/getMembers', [
'id_cluster' => (int) $id_cluster,
'class' => 1
]);
$machineRes = $machineReq->dispatch();
// si erreur, on affiche rien par défaut
if( $machineRes->error->get() != Err::Success )
return [];
return count($machineRes->get('members'));
}));
$twig->addFunction(new \Twig_Function('f_permissions', function(){
$permReq = new Request('clusterDefault/getPermissions', []);
$permRes = $permReq->dispatch();
// si erreur, on affiche rien par défaut
if( $permRes->error->get() != Err::Success )
return [];
return $permRes->get('permissions');
}));
$twig->addFunction(new \Twig_Function('f_userclusters', function($id_cluster, $id_permission){
$ucReq = new Request('clusterDefault/getAuthenticatedClusters', [
'id_target' => $id_cluster,
'id_action' => $id_permission
]);
$ucRes = $ucReq->dispatch();
// si erreur, on affiche rien par défaut
if( $ucRes->error->get() != Err::Success )
return [];
return $ucRes->get('clusters');
}));
$twig->addFilter(new \Twig_Filter('translate', function($word, $lang){
$word = strtolower($word);
if( $lang === 'fr' ){
switch($word){
case 'start': return 'démarrer'; break;
case 'stop': return 'arrêter'; break;
case 'signal': return 'signaler'; break;
case 'lock': return 'bloquer'; break;
case 'unlock': return 'débloquer'; break;
case 'unsignal': return 'désignaler'; break;
default: return 'inconnu'; break;
}
}else
return $word;
}));
/* [4] Build the whole stuff
=========================================================*/
return $twig->render('group/permission.twig', [
'p_icon' => $variables['p_icon'],
'p_theme' => $variables['p_theme']
]);
}
}
?>

View File

@ -1,50 +0,0 @@
<input type='text' class='searchbar' placeholder='Recherche'>
{% for machine_cluster in f_clusters() %}
<article class='inline-box' id='{{ machine_cluster.id_machine_cluster }}'>
{% set nbmachines = f_nbmachines(machine_cluster.id_machine_cluster) %}
<span class='title' style='color: {{ p_theme }}'>{{ machine_cluster.name }}</span>
{# <span class='link_remove' data-cluster='{{ machine_cluster.id_machine_cluster }}'>{{ p_icon.remove | raw }}</span>
<span class='link_edit' data-cluster='{{ machine_cluster.id_machine_cluster }}'>{{ p_icon.edit | raw }}</span> #}
<span class='code'>
{{ p_icon.device | raw }}
<span>{{ nbmachines }} machines</span>
</span>
{% for permission in f_permissions() %}
<span class='groups'>
<span style='border-color: #ddd; background-color: #eee;'>
{{ permission.name | translate('fr') }}
<span class='icon-permission'></span>
</span>
<span class='ignore'>
{% for user_cluster in f_userclusters(machine_cluster.id_machine_cluster,permission.id_permission) %}
<span>
{{ user_cluster.name }}
<span class='rem-permission' data-permission='{{ permission.id_permission }}' data-source='{{ user_cluster.id_user_cluster }}' data-target='{{ machine_cluster.id_machine_cluster }}'></span>
</span>
{% endfor %}
</span>
<span class='add-permission' data-target='{{ machine_cluster.id_machine_cluster }}' data-permission='{{ permission.id_permission }}'>+</span>
</span>
{% endfor %}
</article>
{# if no result #}
{% else %}
<article class='inline-box'>
<span>Aucun groupe trouvé.</span>
</article>
{% endfor %}

View File

@ -1,74 +0,0 @@
<?php
namespace viewer\view\group;
use \api\core\Request;
use \api\core\Authentification;
use \error\core\Err;
use \error\core\Error;
class view{
public static function render(){
/* [1] Init Twig
=========================================================*/
$loader = new \Twig_Loader_Filesystem(__BUILD__.'/viewer/view');
$twig = new \Twig_Environment($loader, []);
/* [2] Store variables
=========================================================*/
$variables = [
'p_icon' => [
'remove' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/remove.svg' ),
'edit' => file_get_contents( __PUBLIC__.'/src/static/sub-menu-side/edit.svg' ),
'type' => file_get_contents( __PUBLIC__.'/src/static/menu-side/type.svg' ),
'group' => file_get_contents( __PUBLIC__.'/src/static/container/group.svg' )
],
'p_theme' => $_SESSION['WAREHOUSE']['theme']
];
/* [3] Store functions
=========================================================*/
$twig->addFunction(new \Twig_Function('f_clusters', function($class){
/* (1) On récupère les groupes */
$getClustersReq = new Request('clusterDefault/getAll', ['class' => $class]);
$getClusters = $getClustersReq->dispatch();
/* (2) si erreur, on retourne rien par défaut */
if( $getClusters->error->get() != Err::Success )
return [];
/* (3) On enregistre le résultat */
return $getClusters->get('clusters');
}));
$twig->addFunction(new \Twig_Function('f_members', function($id_cluster, $class){
$membersReq = new Request('clusterDefault/getMembers', [
'id_cluster' => (int) $id_cluster,
'class' => $class
]);
$membersRes = $membersReq->dispatch();
//
// si erreur, on affiche rien par défaut
if( $membersRes->error->get() != Err::Success )
return [];
return $membersRes->get('members');
}));
/* [4] Build the whole stuff
=========================================================*/
return $twig->render('group/view.twig', [
'p_icon' => $variables['p_icon'],
'p_theme' => $variables['p_theme']
]);
}
}
?>

View File

@ -1,89 +0,0 @@
<input type='text' class='searchbar' placeholder='Recherche'>
{% set noresult = true %}
{% for user_cluster in f_clusters(0) %}
{% set noresult = false %}
{% set id_user_cluster = 'u' ~ user_cluster.id_user_cluster %}
{% set memlen = f_members(user_cluster.id_user_cluster,0) | length %}
<article class='inline-box' id='{{ id_user_cluster }}'>
<span class='title' style='color: {{ p_theme }}'>{{ user_cluster.name }}</span>
<span class='link_remove' data-cluster='{{ id_user_cluster }}'>{{ p_icon.remove | raw }}</span>
<span class='link_edit' data-cluster='{{ id_user_cluster }}'>{{ p_icon.edit | raw }}</span>
<span class='code'>
{{ p_icon.type | raw }}
<span>{{ memlen }} utilisateur{% if memlen > 1 %}s{% endif %}</span>
</span>
<span class='groups'>
{{ p_icon.group | raw }}
<span class='ignore'>
{% for user in f_members(user_cluster.id_user_cluster, 0) %}
<span>
{{ user.username }}
<span class='rem-member' data-member='{{ user.id_user }}' data-cluster='{{ id_user_cluster }}'></span>
</span>
{% endfor %}
</span>
<span class='add-member' data-cluster='{{ id_user_cluster }}'>+</span>
</span>
</article>
{% endfor %}
{% for machine_cluster in f_clusters(1) %}
{% set noresult = false %}
{% set id_machine_cluster = 'm' ~ machine_cluster.id_machine_cluster %}
{% set memlen = f_members(machine_cluster.id_machine_cluster,1) | length %}
<article class='inline-box' id='{{ id_machine_cluster }}'>
<span class='title' style='color: {{ p_theme }}'>{{ machine_cluster.name }}</span>
<span class='link_remove' data-cluster='{{ id_machine_cluster }}'>{{ p_icon.remove | raw }}</span>
<span class='link_edit' data-cluster='{{ id_machine_cluster }}'>{{ p_icon.edit | raw }}</span>
<span class='code'>
{{ p_icon.type | raw }}
<span>{{ memlen }} machine{% if memlen > 1 %}s{% endif %}</span>
</span>
<span class='groups'>
{{ p_icon.group | raw }}
<span class='ignore'>
{% for machine in f_members(machine_cluster.id_machine_cluster,1) %}
<span>
{{ machine.name }}
<span class='rem-member' data-member='{{ machine.id_machine }}' data-cluster='{{ id_machine_cluster }}'></span>
</span>
{% endfor %}
</span>
<span class='add-member' data-cluster='{{ id_machine_cluster }}'>+</span>
</span>
</article>
{% endfor %}
{# if no result #}
{% if noresult %}
<article class='inline-box'>
<span>Aucun groupe trouvé</span>
</article>
{% endif %}

View File

@ -1,129 +0,0 @@
<?php
namespace viewer\view\history;
use \api\core\Request;
use \error\core\Error;
use \error\core\Err;
class view{
public static function render(){
/* [1] Init Twig
=========================================================*/
$loader = new \Twig_Loader_Filesystem(__BUILD__.'/viewer/view');
$twig = new \Twig_Environment($loader, []);
/* [2] Store variables
=========================================================*/
$variables = [
'p_theme' => $_SESSION['WAREHOUSE']['theme']
];
/* [3] Store functions
=========================================================*/
$twig->addFunction(new \Twig_Function('f_history', function(){
$req = new Request('historyDefault/getAll', []);
$res = $req->dispatch();
// si erreur, on retourne rien par défaut
if( $res->error->get() != Err::Success )
return [];
return $res->get('history');
}));
$twig->addFilter(new \Twig_Filter('f_tsformat', function($ts){
date_default_timezone_set('Europe/Paris');
return date('d/m/Y H:i:s', $ts);
}));
$twig->addFilter(new \Twig_Filter('f_tsrelative', function($ts){
$r = self::relativetime($ts);
// if only one
$o = $r[0] <= 1;
switch($r[1]){
case 'Y': return $r[0].' an'.($o?'':'s'); break;
case 'm': return $r[0].' mois'; break;
case 'd': return $r[0].' jour'.($o?'':'s'); break;
case 'H': return $r[0].' heure'.($o?'':'s'); break;
case 'i': return $r[0].' minute'.($o?'':'s'); break;
case 's': return $r[0].' seconde'.($o?'':'s'); break;
default: return 'peu de temps'; break;
}
}));
/* [4] Build the whole stuff
=========================================================*/
return $twig->render('history/view.twig', [
'p_theme' => $variables['p_theme']
]);
}
/* RETURNS A RELATIVE HUMAN-READABLE TIME
*
* @ts<int> Timestamp to process
*
* @return relative<Array> human-readable relative time [value, unit]
*
*/
private static function relativetime($ts){
/* [1] Explode time into human-readable time units
=========================================================*/
$units = [];
/* (1) Date units */
$units['year'] = (int) date('Y', $ts);
$units['month'] = (int) date('m', $ts);
$units['day'] = (int) date('d', $ts);
/* (2) Time units */
$units['hour'] = (int) date('H', $ts);
$units['minute'] = (int) date('i', $ts);
$units['second'] = (int) date('s', $ts);
/* [2] Calculate relative time for each unit
=========================================================*/
/* (1) Date units */
$units['year'] = intval(date('Y')) - $units['year'];
$units['month'] = intval(date('m')) - $units['month'];
$units['day'] = intval(date('d')) - $units['day'];
/* (2) Time units */
$units['hour'] = intval(date('H')) - $units['hour'];
$units['minute'] = intval(date('i')) - $units['minute'];
$units['second'] = intval(date('s')) - $units['second'];
/* [3] Return significative relative time
=========================================================*/
/* (1) Date units */
if( $units['year'] > 0 ) return [ $units['year'], 'Y' ];
if( $units['month'] > 0 ) return [ $units['month'], 'm' ];
if( $units['day'] > 0 ) return [ $units['day'], 'd' ];
/* (2) Time units */
if( $units['hour'] > 0 ) return [ $units['hour'], 'H' ];
if( $units['minute'] > 0 ) return [ $units['minute'], 'i' ];
if( $units['second'] > 0 ) return [ $units['second'], 's' ];
/* (3) Default value */
return [0, '.'];
}
}

View File

@ -1,44 +0,0 @@
<input type='text' class='searchbar' placeholder='Recherche'>
{% for entry in f_history() %}
{% if loop.index == 1 %}
<article class='inline-row' style='border: 0; box-shadow: none;background: transparent;'>
<span>Machine</span>
<span>Dernière utilisation</span>
<span>Utilisateur</span>
<span>Action</span>
<span>Historique détaillé</span>
</article>
{% endif %}
<article class='inline-row' id='{{ entry.id_history }}'>
<span data-machine='{{ entry.id_machine }}' class='title'><span>#{{ entry.machine_name }}</span></span>
<span>
<span>{{ entry.timestamp | f_tsformat }}</span>
<span style='color:#aaa;'>Il y a {{ entry.timestamp | f_tsrelative }}</span>
</span>
<span data-user='{{ entry.id_user }}'>
<span>{{ entry.user_name }}</span>
<span style='color:#aaa;'>{{ entry.user_firstname }} {{ entry.user_lastname }}</span>
</span>
<span>
<span>{{ entry.action_name }}</span>
</span>
<span>
<button class='search' data-details='{{ entry.id_history }}'>Détails</button>
</span>
</article>
{% endfor %}

Some files were not shown because too many files have changed in this diff Show More