Compare commits

...

350 Commits

Author SHA1 Message Date
Adrien Marquès 177752fdc4 npm packages update 2018-06-09 15:26:17 +02:00
Adrien Marquès 782d2084ca fix http vs. https for CAS service (redirection) 2018-06-09 15:08:46 +02:00
Adrien Marquès 047efa100c update package (vue-template-compiler) 2018-06-09 14:58:04 +02:00
Adrien Marquès 8bd98484aa make login HOST generic 2018-06-09 12:22:20 +02:00
Adrien Marquès 47c90d8737 add dedicated page 'fiche' for teachers only (not 'cas_admin') + router management + add logout btn 2018-05-17 15:16:30 +02:00
xdrm-brackets 1bfd97009e fix [modules.json] format + fix 'teacher/pdf' to return data even if no formation is found (+remove dumb data from pdf) 2018-05-14 12:03:11 +02:00
xdrm-brackets cfb9e0df23 remove page 'fiche' 2018-05-14 11:56:11 +02:00
Unknown 8f909821b6 add version delete/update restrictions 2018-05-14 01:03:18 +02:00
Unknown 24b0bb3798 Implement non-admin user pdf download 2018-05-14 00:57:57 +02:00
Unknown 9dea19b9b1 Fix version update 2018-05-13 23:41:32 +02:00
xdrm-brackets edbd2da4eb Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-05-12 16:48:13 +02:00
xdrm-brackets 799116d1a4 remove debug 2018-05-12 16:48:07 +02:00
xdrm-brackets f62674cb0b fix export extension 2018-05-12 16:46:23 +02:00
xdrm-brackets 50f99f6a44 fix export extension 2018-05-12 16:45:47 +02:00
xdrm-brackets c52893ffd6 added global department's version export 2018-05-12 16:42:49 +02:00
xdrm-brackets 56eb72ac55 department/export now uses the download system 2018-05-12 16:42:28 +02:00
xdrm-brackets 9093ce2d38 department.create/delete(unimplemented server-side)/switch 2018-05-12 16:17:27 +02:00
Unknown a745daa506 Add fiche download auth check 2018-05-10 15:43:02 +02:00
Unknown e9579c8956 Implemented Excel export of version 2018-05-10 15:09:40 +02:00
Unknown 6af33306af Merge branch 'verions-new' 2018-05-10 12:37:51 +02:00
Unknown b33f1a67cb Implemented Department creation 2018-05-10 12:37:27 +02:00
xdrm-brackets fa7d9ee6f2 Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-05-09 17:51:47 +02:00
xdrm-brackets dd52ed39bc fail on trying to rename a version with the empty string 2018-05-09 17:45:52 +02:00
xdrm-brackets 78c3d1c02d now better version management all-in-header 2018-05-09 17:43:34 +02:00
xdrm-brackets 1225f69d9d [api.cas] on login select version with 'default=1' first then if nothing, take the first element. Same for [api.version.DELETE] to update the list 2018-05-09 17:43:20 +02:00
xdrm-brackets 058eb5c275 Merge branch 'verions-new' of https://git.xdrm.io/ptut/vhost into verions-new 2018-05-09 15:57:54 +02:00
Unknown 79bdb1c33c Implemented Department creation 2018-05-09 17:44:40 +02:00
xdrm-brackets 35a6b2a931 extremely ugly edit mode for versions 2018-05-09 15:57:47 +02:00
xdrm-brackets 13e545e5f9 update version id + currentDatabase when switching department 2018-05-09 15:12:26 +02:00
xdrm-brackets 3dfa1cc525 minfix 2018-05-09 12:38:09 +02:00
xdrm-brackets 73bc584036 update version model + casController/switch version format in session 2018-05-09 12:36:12 +02:00
xdrm-brackets 63fdcc012d Merge branch 'master' into verions-new 2018-05-09 11:44:02 +02:00
Unknown d2dfd2e962 Implement Formation CRUD 2018-05-08 19:23:46 +02:00
xdrm-brackets d803925b2b add ordering in 'vue.ue.manage' by professor name OR volume count | formation list length 2018-05-08 15:58:11 +02:00
xdrm-brackets bc5d2fff19 alphabetical professor order 2018-05-08 15:48:45 +02:00
xdrm-brackets 6d57e0aa5b display default creation formations on UI for 'POST api.ue.*' 2018-05-08 14:50:39 +02:00
xdrm-brackets 465fde053b fix api.ue.cours + api.ue.tp to return 'formations' id list 2018-05-08 14:48:48 +02:00
xdrm-brackets 4e1ca634ff fixed [ue.manage] list style + added ordering basis (TODO: order algorithm) 2018-05-08 14:46:50 +02:00
xdrm-brackets ca9ca6e290 [POST cours|td|tp] adds the default formation if exists + given formations as arguments - also it returns as output the added formation id list 2018-05-08 14:45:26 +02:00
Unknown c6b46e1b88 New version managing API 2018-05-07 18:14:17 +02:00
xdrm-brackets 367d3c5988 [ue.manage][scss.container.list] fuckin' layout pseudo~fix~~~ 2018-04-17 18:13:57 +02:00
xdrm-brackets 9e96d7a84e Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-04-17 17:38:38 +02:00
xdrm-brackets f14b6d4bbf [scss.container.list] fixed layout + added togglable arrows for filtering (ordering actually) + [ue.manage] added back button 2018-04-17 17:38:32 +02:00
Guillaume FAUVET 21d67f3d2a {upd} statistiques are responsive 2018-04-07 12:40:40 +02:00
Unknown 32da5131b4 [repo.ue] Fixed request stacker + fixed UE request 2018-04-01 13:10:36 +02:00
Guillaume FAUVET f65513a241 Merge branch 'page-home' 2018-03-31 13:40:51 +02:00
Guillaume FAUVET 1c2de0b5df [page.home] {upd} ajout de commentaires 2018-03-31 13:36:32 +02:00
Guillaume FAUVET c40d45e7c9 [page.home] {correction} maj des noms des heures + ajout de légendes extra 2018-03-31 13:33:08 +02:00
Guillaume FAUVET 1e93e712c3 [master] {correction} affiche les messages d'erreur de connexion plus longtemps 2018-03-31 13:11:59 +02:00
Guillaume FAUVET 52f3a3ac60 Merge page-home to master 2018-03-31 13:06:02 +02:00
xdrm-brackets dc8420a70c [teacher.view] let EHTD in EDIT MODE 2018-03-30 19:18:43 +02:00
xdrm-brackets ad2e393e8c [data.ue] implemented 'formation' inclusive filter and vue template updated in [ue.view] + managed auto-unblur in template 'beforeMount' 2018-03-30 18:32:13 +02:00
xdrm-brackets 1ead035f0e [data.ue] added formation list to search bar + fixed proccess time (algo exit first) 2018-03-30 18:07:04 +02:00
xdrm-brackets 9bd58eb460 [teacher.view] create card with same design as others [data.teacher] created handler 'ic_reset' + added button 'CANCEL' to reset form & untoggle 2018-03-30 17:32:12 +02:00
xdrm-brackets 365e1eb567 [ue.view] create card with same design as others [data.ue] created handler 'ic_reset' + added button 'CANCEL' to reset form & untoggle 2018-03-30 17:29:39 +02:00
xdrm-brackets 7b8c01b38a renamed 'Cours' -> 'CM' [teacher.view] [ue.manage] 2018-03-30 17:19:50 +02:00
xdrm-brackets 7a1872a65a [ue.view] errors more explicit : missing teacher, wrong volume 2018-03-30 17:16:56 +02:00
xdrm-brackets 07ab742071 [scss.global] added tooltip arrow + transformed before-icons to raw icons [ue.view] replaced before-icons with raw icons 2018-03-30 17:03:35 +02:00
xdrm-brackets e8ed5ab97d [teacher.view] fixed 'sous-service'/'sur-service' float with N decimal numbers -> now only 2 2018-03-30 16:54:03 +02:00
xdrm-brackets 0f136299e9 [teacher.view] added 'sous-service'/'sur-service' + EHTD + EDIT MODE valid + info header 2018-03-29 22:01:40 +02:00
Unknown a79710f3fe [repo.ue]Fix additionnals data computation 2018-03-29 23:51:15 +02:00
xdrm-brackets 5ea9d901a9 [ue.view] fix for EDIT MODE 2018-03-29 21:36:57 +02:00
xdrm-brackets d8cc6b27ac [data.ue] fixed manage cannot find 'code' from URI when playing with history back/forth so now uses VueRouter 2018-03-29 21:29:29 +02:00
xdrm-brackets 2d270f5689 [ue.view] updated 'required' colors + 'CM', 'TD', 'TP' with group count + when errors in bold red + error incicators 2018-03-29 21:21:37 +02:00
xdrm-brackets 53e671457d Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-03-29 20:36:41 +02:00
Unknown 848a1b7970 [repo.ue] Added some data
+ number of CM TD TP
+ modulo of the number of hours of CM TD TP
+ number of prof assigned to CM TD TP
2018-03-29 22:24:37 +02:00
xdrm-brackets e64667a955 [scss.container.card] added 'info' (mini-header for little informations) + added icon to update 'required'/'optional' in right top corner + [vue.ue.view] moved 'required' with pin before name and 'enabled' with line-through [scss.global] 2018-03-29 19:30:37 +02:00
Guillaume FAUVET eaa2bc65e0 [page.home] {fix} affichage sur réponse de l'API 2018-03-28 11:32:59 +02:00
xdrm-brackets 1997af49f4 [scss.container.card] bigger '+' create toggle 2018-03-26 13:34:03 +02:00
xdrm-brackets 8b5a385252 merge conflict 2018-03-26 07:27:20 -04:00
xdrm-brackets f62af0693e [webpack.teacher] updated fields names + pdf download works [scss.container.card] added PDF download icon 2018-03-26 13:24:19 +02:00
xdrm-brackets 72e38d59b1 [webpack.teacher] updated fields names + pdf download works [scss.container.card] added PDF download icon 2018-03-26 13:23:32 +02:00
xdrm-brackets a4e56c8574 merge 2018-03-22 06:13:09 -04:00
Guillaume FAUVET 6e375a8e14 [home > graphique svg] 2018-03-22 10:54:46 +01:00
xdrm-brackets 20a4f86d5c [module.professor.pdf] Added extension '.pdf' 2018-03-21 15:24:26 +01:00
xdrm-brackets 8b33f401af [module.professor.pdf] Added extension '.pdf' 2018-03-21 15:07:50 +01:00
xdrm-brackets be1e5b0a4d [api.core.Request] if DOWNLOAD -> create TMP dir in PUBLIC 2018-03-21 15:02:12 +01:00
xdrm-brackets 6273a58046 [module.professor.pdf] Generate PDF link 2018-03-21 14:54:42 +01:00
xdrm-brackets 2c0681dd7c [module.professor.pdf] Generate PDF (not tested but working) ONLY WORKS WITH 'prof_id' not ALL 2018-03-21 14:43:47 +01:00
xdrm-brackets e153b7ecb4 [repo.cours] getForProfessor [repo.td] getForProfessor [repo.tp] getForProfessor 2018-03-21 14:42:52 +01:00
xdrm-brackets daddb8ebcf [config.modules] added 'cas' permissions for 'department.version' and 'professor' 2018-03-21 00:59:51 +01:00
xdrm-brackets ec6a89233f [module.cas] GET minmod 2018-03-21 00:50:19 +01:00
xdrm-brackets 81db5a02c8 [module.cas] GET works with URL0=0 with redirection | URL0=1 with pop-up management 2018-03-21 00:41:44 +01:00
xdrm-brackets 46ba44d042 [module.cas] PUT is so slow.. timeout (CAS server not responding in consistent time) 2018-03-20 23:51:39 +01:00
xdrm-brackets 100b09c695 [config.modules] added 'cas' permissions [module.cas] added PUT to really logout (from CAS server) but do not work (except from document.location) 2018-03-20 23:35:16 +01:00
xdrm-brackets 7db2a41027 [repo.meta] fixed 'create_prof' return type to 'bool' [repo.professor] removed getLinkedDepartments 2018-03-20 18:49:00 +01:00
xdrm-brackets 12b1a29ed0 [repo.meta] created meta database repo (create_prof, delete_prof, prof_exists, link_exists, link, unlink, get_prof_departments) [repo.professor] used [repo.meta] to synchronize meta database (fully tested, even if meta not already synchronized) [module.casController] now uses [repo.meta] [module.department] now uses [repo.meta] 2018-03-20 18:44:43 +01:00
xdrm-brackets e562bec77f [repo.professor] fixed 'CurrentDepartementId' to 'CurrentDepartmentId' 2018-03-20 17:26:23 +01:00
xdrm-brackets ad67e62680 [webpack.login] login successful redirects to URL page (allows direct access) 2018-03-20 12:09:26 +01:00
xdrm-brackets c8c1bf2ede [webpack.common] added gstore field 'HOST' that contains 'https://ptut.xdrm.io' or 'http://ptut.com:8080' 2018-03-20 12:08:53 +01:00
xdrm-brackets e32ce89837 [webpack.login] added custom error code (-5) 'popup_interrupted' 2018-03-20 11:51:20 +01:00
xdrm-brackets e301a7eb2e [api.department] added GET (id or ALL) 2018-03-20 11:47:54 +01:00
xdrm-brackets c5adb6d660 [api.core.auth-system-default] fixed 'CurrentDepartmentId' reset type check 2018-03-20 10:54:12 +01:00
xdrm-brackets b06b8666bc [renamed] 'AvailableDepartment' -> 'AvailableDepartments' [renamed] 'CurrentDepartementId' -> 'CurrentDepartmentId' 2018-03-20 10:49:53 +01:00
xdrm-brackets 35b0cb36fa [repo.professor] fix CREATE sync with meta database 2018-03-20 10:49:12 +01:00
xdrm-brackets 67e0f9eba2 [webpack.login] re-activate button after fail attempt + debug message as raw-html 2018-03-20 10:25:30 +01:00
xdrm-brackets 0486110f2b [webpack.login] minfix 2018-03-20 10:22:55 +01:00
xdrm-brackets 2dedde4fa6 [webpack.data.login] send custom error code '-2' not NULL anymore (from previous commit) 2018-03-20 10:20:40 +01:00
xdrm-brackets e67195871f [module.cas] dispatch custom error codes [webpack.login] display error codes 2018-03-20 10:19:32 +01:00
xdrm-brackets 14c71d88f1 [repo.ue] removed debug (PDO::ERRMODE_EXCEPTION) 2018-03-19 23:39:53 +01:00
xdrm-brackets 38600994c0 [repo.ue] UPDATE manage 'new_code' [module.ue] PUT manages optional argument 'new_code' [webpack.data.ue] display input for 'code' and send 'new_code' to API if set 2018-03-19 23:32:09 +01:00
xdrm-brackets 228bdddd2d [composer.mpdf] added PDF lib [public_html.pdf.php] PDF basics + layout 2018-03-19 23:15:19 +01:00
xdrm-brackets bef4dad5f7 [api.core.authsystemdefault] removed CAS management [module.cas] implemented good CAS management with database + error management (edge cases) 2018-03-19 19:06:00 +01:00
xdrm-brackets 60ceb9d2a8 [module.department] renamed 'getLinkedDepartments' (plural) 2018-03-19 19:05:19 +01:00
xdrm-brackets b47341f792 [repo.professor] renamed 'getLinkedDepartment' -> 'getLinkedDepartments' (plural) + Error management (edge cases) + update -> updates meta database + delete -> updates meta database 2018-03-19 19:04:57 +01:00
xdrm-brackets 959df5cfde [module.cas] fix1 [webpack.page.login] fix [webpack.data.login] fix 2018-03-19 18:27:33 +01:00
xdrm-brackets 39635cb5fa [webpack.ue.manage] CREATE css minmod 2018-03-18 17:36:23 +01:00
xdrm-brackets dc647f567f [webpack.ue.manage] CREATE new Cours|TD|TP implemented (with real-time feedback (push into VueJS), then updates/remove works) 2018-03-18 17:17:31 +01:00
xdrm-brackets 861fb49846 [webpack.ue.manage] minmod 2018-03-18 16:31:03 +01:00
xdrm-brackets d43c2244a0 [backup.dir] removed + .gitignore 2018-03-18 11:15:30 +01:00
xdrm-brackets 70ff0edeb9 [api.core.AuthSystemDefault] added $_SESSION['VERSION'] [router.controller.js] added 'session.version' in javascript '_SERVER' variable [module.version] minmod [webpack.header] implemented VERSION: fetch|create|switch 2018-03-17 19:07:44 +01:00
xdrm-brackets 4280bbb5f6 [webpack.lib.onblur] js lib to call 'callbacks' when unblur (for example <div> that shows only on click, but now it allows us to hide them when clicking outside this element) [webpack.data.common] added lib in 'window.unblur' [webpack.teacher.view] used the lib for 'filter' list that shows when clicking on filter name [webpack.header] used for 'department' and 'version' popup lists 2018-03-17 18:26:09 +01:00
xdrm-brackets e221452295 [module.department.save] => [module.department.version] refactor + POST split into POST & PUT + used API 'error' return field BIGUPDATE 2018-03-17 14:34:16 +01:00
xdrm-brackets 466d197246 [module.professor] -Removed 'GET professor/stats' 2018-03-17 13:18:37 +01:00
Unknown d8e74ada8a Merge branch 'db-save' 2018-03-16 20:40:14 +01:00
Unknown d240b14a9e Implemented backup preview 2018-03-16 20:40:04 +01:00
Guillaume FAUVET 3be136eff1 Update card.scss 2018-03-16 18:24:57 +01:00
xdrm-brackets fa311d6df7 [webpack.ue.manage] minmod 2018-03-16 16:01:17 +01:00
xdrm-brackets 3b5875ab06 [webpack.ue.manage] implemented 'remove' for Cours|TD|TP 2018-03-16 15:59:17 +01:00
xdrm-brackets 1b8f3eadee [webpack.ue.manage] implemented 'upd_prof' to instant-update a professor for a Cours|TD|TP 2018-03-16 15:39:03 +01:00
xdrm-brackets 045ced9002 [webpack.ue.manage] eased 'add_form' (by index no more ID) 2018-03-16 15:28:47 +01:00
xdrm-brackets 9ae61af2c4 [scss.header] smaller header height 2018-03-16 15:25:05 +01:00
xdrm-brackets cd9f342eda [webpack.ue.view] no more need for $router (it is in Gstore) for navigation funcs [webpack.ue.manage] eased 'rem_form' (by index no more ID) + fetch professors / created layout for changing professor for a cours|TD|TP 2018-03-16 15:18:57 +01:00
xdrm-brackets 8218571498 [scss.container.list] minfix 2018-03-15 20:21:51 +01:00
xdrm-brackets 4360afe212 [scss.container.list] made 'tag's more readable 2018-03-15 20:17:24 +01:00
xdrm-brackets b89eb61943 [scss.container.list] minmod 2018-03-15 20:14:56 +01:00
xdrm-brackets eccaf1161a [webpack.ue.manage] can instant-add formations (api+feedback) 2018-03-15 20:08:27 +01:00
xdrm-brackets 0f57d5bd6e [webpack.ue.manage] can instant-remove formations (api+feedback) 2018-03-15 19:50:15 +01:00
xdrm-brackets c3bebefe0f [repo.tp] fixed + added requests to create|update|delete [module.tp] POST to create + PUT to update (can remove a list of formations, or add a list .., update idProf (-1 to unset), volume) 2018-03-15 19:29:00 +01:00
xdrm-brackets 45e3b005ec [repo.td] fixed + added requests to create|update|delete [module.td] POST to create + PUT to update (can remove a list of formations, or add a list .., update idProf (-1 to unset), volume) 2018-03-15 19:25:42 +01:00
xdrm-brackets 428054e007 Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-03-15 19:17:32 +01:00
xdrm-brackets 0c0c37b0a1 [repo.cours] fixed + added requests to create|update|delete [module.cours] POST to create + PUT to update (can remove a list of formations, or add a list .., update idProf (-1 to unset), volume) 2018-03-15 19:17:28 +01:00
Unknown cc51cb9d1e Merge branch 'db-save' 2018-03-15 18:21:32 +01:00
Unknown aeb39e782f Merge remote-tracking branch 'origin/db-save' into db-save 2018-03-15 18:19:40 +01:00
Unknown a8d671e87c fix Namespace change 2018-03-15 18:18:48 +01:00
Unknown b3990578d3 ajout du gitignore des backups 2018-03-15 18:14:13 +01:00
Unknown 959a1047d8 Implémentation de base des backups 2018-03-15 18:14:13 +01:00
xdrm-brackets e1bdac7f5b renamed 'departement' to 'department' 2018-03-15 17:40:12 +01:00
xdrm-brackets 2a0d8e15b1 [module.department] renamed (got rid of the 'e') | [webpack.header] department switch OK 2018-03-15 17:38:06 +01:00
Unknown 5d130114cf ajout du gitignore des backups 2018-03-15 16:47:43 +01:00
Unknown f979578bbc Implémentation de base des backups 2018-03-15 16:47:22 +01:00
xdrm-brackets 1d0f8933be [webpack.ue.manage] SCSS for adding/removing formations to an existing cours|td|tp (must implement now in JS) 2018-03-15 15:15:12 +01:00
xdrm-brackets 5bf11d0b6d [webpack.ue.manage] hover border color consistent with Cours|TD|TP according to other cards layout 2018-03-15 14:10:08 +01:00
xdrm-brackets 688b0c10c8 [bowdel] + [AuthSystemDefault] + [module.cas] DELETE (now logout works + login + session departE?E?E?E?E?ment data) 2018-03-15 13:13:40 +01:00
xdrm-brackets a5f68b2021 [config.webpack] now works with real hashes 2018-03-15 12:46:16 +01:00
Unknown dbe4599003 Merge branch 'multi-bdd' 2018-03-15 12:02:53 +01:00
Unknown 2a9e1e1474 Implemented department database switch 2018-03-15 12:02:28 +01:00
Unknown 7c2a698733 implemented multi-bdd login 2018-03-15 12:00:48 +01:00
xdrm-brackets 4175d578b0 [webpack.ue.manage] first iface (to be updated) very ugly 2018-03-14 19:57:31 +01:00
xdrm-brackets 30940dda48 [webpack.data.ue] manage page 'manage' load on nav from page 'view' + standalone with redirection if invalid 'code' in URL 2018-03-14 18:56:55 +01:00
xdrm-brackets d8d5c74654 [scss.global.before-icon] fix 2018-03-14 17:56:03 +01:00
xdrm-brackets 3f1037900c moved [container.list] to a new file 2018-03-14 17:43:44 +01:00
xdrm-brackets ae69cdbb42 moved [container.card] to a new file 2018-03-14 17:42:18 +01:00
xdrm-brackets d3a3e13593 moved tags|warning :before|pin :before and used multiple files for [scss.global] 2018-03-14 17:40:41 +01:00
xdrm-brackets cec2c491bb [module.ue.cours|td|tp] GET returns the groups [repo.cours|td|tp.getGroups] used by api 2018-03-14 15:28:41 +01:00
xdrm-brackets 30ffe4f9e1 [scss.layout] loading opacity animation 2018-03-14 12:50:58 +01:00
xdrm-brackets 84ecabedd0 [page.*] [scss.layout] added loader for bad connection 2018-03-14 12:44:11 +01:00
xdrm-brackets f2201ebedc [css.container] minfix 2018-03-14 12:17:19 +01:00
xdrm-brackets 496c0ba529 [webpack.ue.*] manage navigation (2-ways) 2018-03-14 12:12:32 +01:00
xdrm-brackets 561fce6449 [css.container.tag(span)] set cursor not to select text 2018-03-14 10:34:13 +01:00
xdrm-brackets 4053768474 [css.container.cards(section)] animation on display 2018-03-14 10:30:51 +01:00
xdrm-brackets a827e66ba1 [css.prof|ue.view] managed toggle icon with 2 differente sprites 2018-03-14 00:15:51 +01:00
xdrm-brackets a574b3cdf1 [webpack.ue.view] found an design idea for 'required' vs. 'optional' UEs 2018-03-14 00:07:19 +01:00
xdrm-brackets 843251449f [repo.ue] fixed get(code), get(null) already worked | [webpack.ue.view] fixed 'form_by_id' that is now declared before fetching UEs 2018-03-13 23:52:09 +01:00
xdrm-brackets 6c0b6fe32a [webpack.ue.view] removed console.log() 2018-03-13 22:49:19 +01:00
Unknown 127132f9b2 because your request is shit 2018-03-13 21:59:09 +01:00
xdrm-brackets 4999dcee05 [webpack.ue.view] added 'formations' list for each UE 2018-03-13 21:24:55 +01:00
xdrm-brackets 7d2d59402b [repo.ue] now GET returns the field 'formations' that is a JSON array (shitty SQL) [module.ue] converts to real array data 2018-03-13 21:17:32 +01:00
xdrm-brackets 76ade95c18 [repo.ue] now GET returns the field 'formations' that is a JSON array representation containing the 'formation' IDS 2018-03-13 20:10:14 +01:00
xdrm-brackets 3a8178a352 [scss.**] menu color invertion + minmod + fixed margin after search-bar 2018-03-13 19:23:22 +01:00
xdrm-brackets 9d495e2c5c [scss.container] make gooey menu bigger 2018-03-13 19:02:38 +01:00
xdrm-brackets b85a158078 [webpack.ue.view][webpack.ue.manage] created 'nav_in' base animation (subtle) 2018-03-13 15:43:43 +01:00
xdrm-brackets e0d4c278f4 [webpack.ue.view][webpack.ue.manage] created 'nav_in' base animation 2018-03-13 15:02:41 +01:00
xdrm-brackets 7472c8627e [page.*] shring mobile initial aspect ratio 2018-03-13 14:20:28 +01:00
xdrm-brackets fc47675f7e [page.*] double mobile initial aspect ratio 2018-03-13 14:17:46 +01:00
xdrm-brackets 66d5d57ec6 [scss.container][scss.layout] make UI more visible 2018-03-13 14:15:06 +01:00
xdrm-brackets 5a050dbbd1 [module.professor] PUT|POST check for lastName+firstName or casLogin to be unique 2018-03-13 11:44:33 +01:00
xdrm-brackets f3085ec4db [module.professor] PUT now checks for @casLogin to be unique 2018-03-13 11:26:08 +01:00
xdrm-brackets 3e0ccea7df [module.professor] PUT can now remove CAS_LOGIN (argument @remCas = TRUE) 2018-03-13 11:13:03 +01:00
xdrm-brackets f7a63a503d Merge branch 'master' of https://git.xdrm.io/ptut/vhost into ue-transition 2018-03-12 19:51:02 +01:00
xdrm-brackets f7ddd0145c [webpack.header][scss.header] created default version management (only template) for header 2018-03-12 19:50:56 +01:00
xdrm-brackets 1a956cbc58 [webpack.ue.view][webpack.ue.manage] created sub-page of 'ue.view': 'ue.manage' which takes a 'code' as URI argument + $router commands 2018-03-12 19:50:33 +01:00
Guillaume FAUVET 17c78d6e87 Merge remote-tracking branch 'origin/master' 2018-03-12 14:50:10 +01:00
Guillaume FAUVET 18f71fc2fc [scss.container] fix .card.container overflow (solving UE display) 2018-03-12 14:49:59 +01:00
xdrm-brackets 87a069ca84 [webpack.ue.view] accessibility with 'title' attribute 2018-03-12 11:28:22 +01:00
xdrm-brackets 56f94de6a5 [webpack.teacher.view] accessibility with 'title' attribute 2018-03-12 11:23:29 +01:00
xdrm-brackets 2604e4eb80 [scss.container] fix .warning icon overflow 2018-03-12 11:16:27 +01:00
xdrm-brackets 95a983dbf2 [page.ue] rename <title> tag 2018-03-12 11:12:45 +01:00
xdrm-brackets 9b19c42aee Merge branch 'ue-from-teacher' 2018-03-12 11:02:56 +01:00
xdrm-brackets fc26d4a7ef [webpack.ue.view] fixed update 2018-03-12 11:01:23 +01:00
xdrm-brackets fa9964cd78 [module.ue] PUT pass 'defaultFormation' as it (NULL: ignore, -1: unset, *: set) 2018-03-12 10:57:53 +01:00
xdrm-brackets 6de03a80e3 [repo.ue] UPDATE now can have empty 'bind_param' because can only set defaultFormation to NULL 2018-03-12 10:57:05 +01:00
xdrm-brackets 6601880436 [module.ue] POST now default value for 'defaultFormation' is int = -1 (type is INT btw) 2018-03-12 10:43:08 +01:00
xdrm-brackets 1aab7b61bd [api.core.checker] now for 'varchar()' type, pass numeric -> string before checking 'strlen()' (because of json_decode) 2018-03-12 10:42:19 +01:00
xdrm-brackets a0d2ca65f9 [webpack.ue.view] [repo.ue] [module.ue] implemented CREATE|DELETE|UPDATE (but BUGGGS EVERYWHERE !!!) 2018-03-11 19:34:11 +01:00
xdrm-brackets 7da78a648e [webpack.ue.view] fixed 'code' type check 2018-03-11 18:20:50 +01:00
xdrm-brackets eadc3f95d4 [module.ue] DELETE implemented 2018-03-11 18:13:41 +01:00
xdrm-brackets b434a9e658 [webpack.ue.view] fixed 'remove' call 2018-03-11 18:10:49 +01:00
xdrm-brackets 1c62879fad [webpack.ue.view] updated js to handle edit/create (with volumes) 2018-03-11 18:08:33 +01:00
xdrm-brackets 17c7355b4d [webpack.ue.view] updated layout to allow updating 'volumes' [TODO: implement js for managing it] 2018-03-11 17:48:50 +01:00
xdrm-brackets de79bfffde [webpack.ue.view] update [webpack.ue.data] update [scss.container] update [TODO: add volumes in edit/create] [TODO: implement API/repo] 2018-03-11 17:31:46 +01:00
Unknown 1683b3f20d Merge remote-tracking branch 'origin/master' 2018-03-11 16:33:04 +01:00
xdrm-brackets ea3923f002 Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-03-11 16:32:00 +01:00
Unknown 2a6d5e7b94 Fix PhpDoc + fix PhpStan errors 2018-03-11 16:31:36 +01:00
Unknown 13c01ef144 add casLogin option for professor.exists 2018-03-11 16:26:04 +01:00
Unknown 24f7c41705 Fix PhpDoc + fix PhpStan errors 2018-03-11 16:14:12 +01:00
Unknown 12e8d4ea92 hotfix repo debugging 2018-03-08 20:55:00 +01:00
Unknown 64af705c6a Merge branch 'pdo-wrapper' 2018-03-08 20:53:46 +01:00
Unknown 3b853644e0 implemented debugging of the repo 2018-03-08 20:53:40 +01:00
Unknown 1c513acaa4 Implemented Wrapper and Stacker + optimized Excel import 2018-03-08 20:09:02 +01:00
Unknown 78e66a0a26 Merge branch 'statistics' 2018-03-08 18:41:58 +01:00
Unknown 271799e9f4 implemented departement stats 2018-03-08 18:41:52 +01:00
xdrm-brackets 24dcbcc7ba [webpack.teacher.view] instant-edit now updates the 'category label' from 'gstore.get.filters.categories' if possible 2018-03-08 18:34:25 +01:00
xdrm-brackets d9a6320d44 [module.professor.filter] removed unused repo 2018-03-08 18:24:52 +01:00
xdrm-brackets 8a3d83503d [module.professor.filter] can now filter by 'categories' + [repo.category] implemented getProfessors() + [webpack.teacher.view] instant-filter for 'categories' -> will propably help to have categories to update category label when prof edited) 2018-03-08 18:13:07 +01:00
xdrm-brackets 158b9d2cb0 [webpack.teacher.view] instant-filter new design + filter count 2018-03-08 18:03:25 +01:00
xdrm-brackets 0e305499ad [404] upgrade 2018-03-08 15:07:16 +01:00
xdrm-brackets 45a7f126bb created svg filter cluster for better usage 2018-03-08 14:14:22 +01:00
xdrm-brackets da5f51367e [webpack.teacher.view] instant-edit add border 2018-03-08 14:04:10 +01:00
xdrm-brackets 5785b58703 [webpack.teacher.view] instant-edit now works !! (but need to get categoryLabel from other request maybe..) 2018-03-08 13:58:30 +01:00
xdrm-brackets c4041532a8 [webpack.teacher.view] now if you click on the :not(:hover) link, it will be consistent (does not move) 2018-03-08 13:12:29 +01:00
xdrm-brackets c9563ab36d [webpack.teacher.view] gooey effect now invisible when not :hover 2018-03-08 13:07:15 +01:00
xdrm-brackets 7a3ac8ff64 [webpack.teacher.view] instant-remove|instant-edit now have knowledge of the specified professor (from gstore.professors) 2018-03-08 12:45:09 +01:00
xdrm-brackets 3f7aaee9b5 [scss] chrome+firefox cross-compatibility 2018-03-08 12:40:06 +01:00
xdrm-brackets 56b858c044 [webpack.teacher.view] SCSS: gooey effect order change 2018-03-08 12:25:28 +01:00
xdrm-brackets efaaedfd0d [webpack.teacher.view] SCSS: gooey effect 2018-03-08 12:12:12 +01:00
xdrm-brackets 8a22a18b96 [webpack.teacher.view] make instant-buttons (admin, edit, remove) with feedback (TEST) 2018-03-07 19:13:05 +01:00
xdrm-brackets b21635c365 [css.card.container] fix layout for when few cards, align to top (not middle of screen) 2018-03-07 19:06:21 +01:00
xdrm-brackets 2ce339f1e2 [webpack.teacher.view] fixed '(cas_login)' layout (parenthesis are no more in pseudo-elements but included in HTML render) + white-space: nowrap allows it not to be multiline | [css.container.card.instant-search] fixed '+' toggle button layout (except extremely small resolution) 2018-03-07 19:00:21 +01:00
xdrm-brackets e04649a8f5 [webpack.teacher.view] can now toggle 'CREATE' card + fixed layout now 'CREATE' card is !!exactly!! the same size as others 2018-03-07 18:49:28 +01:00
xdrm-brackets c21b744986 [webpack.teacher.view] can now toggle 'ADMIN' property in real-time (+feedback) 2018-03-07 14:58:01 +01:00
xdrm-brackets f010f29477 remove debug 2018-03-07 14:46:41 +01:00
xdrm-brackets f544959e76 [webpack.teacher.view] CREATE feedback (green msg) 2018-03-07 14:43:04 +01:00
xdrm-brackets e818886972 [webpack.teacher.view] can now CREATE professors 2018-03-07 14:34:44 +01:00
xdrm-brackets 0b5272c8ec [config.modules] make POST professor types more flexible 2018-03-07 14:34:18 +01:00
xdrm-brackets 919bccafd9 [webpack.teacher.view] duplicated code from 'REMOVE' to 'UPDATE' (to implement) 2018-03-07 13:20:02 +01:00
xdrm-brackets c3c59737d1 [webpack.teacher.view]] Can now REMOVE (delete) professors 2018-03-07 13:13:31 +01:00
xdrm-brackets f491d9736d minfix css for pop-up 2018-03-07 12:25:57 +01:00
xdrm-brackets ba30174b02 [webpack.teacher.view] added 'remove' and 'edit' icons (to implement) 2018-03-07 12:12:50 +01:00
xdrm-brackets 68d0461d7c Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-03-06 19:42:15 +01:00
xdrm-brackets 3cfde3e948 minmod 2018-03-06 19:42:09 +01:00
Unknown 9dc60ca0cd Fix Request for ctegory stats 2018-03-06 19:40:57 +01:00
xdrm-brackets 39cc5ef906 [webpack.logout] now logout works 2018-03-06 19:39:34 +01:00
xdrm-brackets 9c00c83240 [webpack.login] added icon+title [TODO: animations] 2018-03-06 19:26:56 +01:00
xdrm-brackets 7deff7ae49 [webpack.teacher.view] added 'warning' 2018-03-06 16:37:27 +01:00
xdrm-brackets 276582b131 [webpack.teacher.view] fixed button on 'create' card 2018-03-06 16:34:30 +01:00
xdrm-brackets 54c2455da4 [webpack.teacher.view] minlayoutfix 2018-03-06 16:22:07 +01:00
xdrm-brackets 8f47e3d7ae [webpack.teacher.view] added fetching categories for 'create' card 2018-03-06 16:20:31 +01:00
xdrm-brackets c6fc6631fb [module.category] implemented GET 2018-03-06 16:15:19 +01:00
xdrm-brackets 0a0135487f [repo.category] added get() usual | [repo.professor] fix.. 2018-03-06 16:15:01 +01:00
Unknown 6bcccdae7f Merge remote-tracking branch 'origin/master' 2018-03-06 16:07:21 +01:00
Unknown faa0ce19ce Fix progessor SQL (when UE disabled) 2018-03-06 16:07:15 +01:00
xdrm-brackets 8dff413fce [webpack.teacher.view] added 'create' card 2018-03-06 16:05:29 +01:00
Unknown f0a2e57394 Merge branch 'excel-import' 2018-03-06 15:22:05 +01:00
Unknown ac53d5bf7a Fix Import and request to take in consideration disabled UEs 2018-03-06 15:21:48 +01:00
xdrm-brackets 8326c965a2 [webpack.teacher.view] Cours|TD|TP card footer icons+explicity 2018-03-06 15:02:36 +01:00
xdrm-brackets 4352f02dc9 [webpack.teacher.view] show all professors when (no filter|empty filter) 2018-03-06 14:49:48 +01:00
SeekDaSky f0ea6cf494 fix filter 2018-03-06 14:27:27 +01:00
Unknown c4c891f33f Merge remote-tracking branch 'origin/master' 2018-03-06 10:55:23 +01:00
Unknown 4676df2bff fix professor controller and moved equitd computation to repo 2018-03-06 10:53:02 +01:00
Unknown dbbb0839ea Merge branch 'database-error-detection' 2018-03-05 20:31:40 +01:00
SeekDaSky b1bf05541d fixed encoding + implemented incoherence detection 2018-03-05 20:30:57 +01:00
xdrm-brackets 565f9d8d11 [webpack.teacher.view] filters now works 2018-03-05 19:51:28 +01:00
xdrm-brackets 443e401d66 Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-03-05 19:42:42 +01:00
xdrm-brackets 15c57b7abb [module.professor] GET fixed VH formula (renamed 'du' to 'hoursToDo') 2018-03-05 19:42:37 +01:00
Guillaume FAUVET 6c458fbf82 Merge remote-tracking branch 'origin/master' 2018-03-05 19:40:12 +01:00
Guillaume FAUVET 5ad2f24ff9 Ajout de la page Gestion UE 2018-03-05 19:39:56 +01:00
Guillaume FAUVET 3578b73417 Ajout de la page Fiches 2018-03-05 19:39:39 +01:00
Guillaume FAUVET e3726632a3 Ajout de la page Administration 2018-03-05 19:39:02 +01:00
xdrm-brackets 92dfdbbc5b Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-03-05 19:35:41 +01:00
xdrm-brackets 56cc3eec82 [module.root] to test params | [config.mdules] 2018-03-05 19:35:35 +01:00
xdrm-brackets 8abf8cca2e [BIGUPDATE: api.core.Checker] remove flexibility 2018-03-05 19:33:43 +01:00
xdrm-brackets a9fec0373e [BIGUPDATE: api.core.Request] Now the api tries to parse JSON parameters (if cannot, they are considered as text) -> the parsed data is passed to controllers -> the checker uses the parsed data 2018-03-05 19:16:33 +01:00
xdrm-brackets 3c97079d25 [repo.formation] getProfessors(@form_id) 2018-03-05 18:48:47 +01:00
xdrm-brackets fec2a504a8 [repo.professor] error management 2018-03-05 18:48:30 +01:00
xdrm-brackets ae5a2459ff [js] override Element prototype with adding: Element.addClass('classname') + Element.remClass('classname') | [webpack.teacher.view] implemented filter show/hide 2018-03-05 18:20:47 +01:00
xdrm-brackets 07438b400a [scss.menu] fixed z-index to show item labels + revert change for fixed menu 2018-03-05 17:38:51 +01:00
xdrm-brackets 3e611ba2f3 bugfix 2018-03-05 17:35:20 +01:00
xdrm-brackets 11bda22ffb [TODO: config.modules.professor.filter.POST] 2018-03-05 11:58:44 +01:00
xdrm-brackets 18302be8b6 [webpack.teacher.view] fixed fold filter group layout 2018-03-05 11:49:55 +01:00
xdrm-brackets df520993fb [webpack.teacher.view] added dynamic filter generation 2018-03-05 11:46:01 +01:00
xdrm-brackets b2faf0e736 bugfix 2018-03-05 11:45:43 +01:00
xdrm-brackets 79da633600 [repo.formation] formatted get(ID|ALL) | [module.formation] implemented GET 2018-03-05 11:19:32 +01:00
xdrm-brackets 767abc3063 [repo.ue] added get(ID|ALL) | [module.ue] implemented GET 2018-03-05 10:39:43 +01:00
xdrm-brackets cb0b06feb2 layout minfix 2018-03-04 18:52:36 +01:00
xdrm-brackets 83bb8c803a [webpack.teacher.view] real-time search now 150ms 2018-03-04 18:25:07 +01:00
xdrm-brackets 400709ca08 [webpack.teacher.view] real-time search with 'instant-search' by: lastName + firstName 2018-03-04 18:16:23 +01:00
xdrm-brackets 405e74d8d8 [webpack.teacher.view] added generic CSS+HTML semantic for 'filter' + 'instant search' 2018-03-04 17:23:35 +01:00
xdrm-brackets 0e2ac90b58 [webpack.teacher.view] icons greyed if 0 hours 2018-03-04 12:56:35 +01:00
xdrm-brackets 6ada8fe0a3 [webpack.teacher.view] fixed 'programmed hours' + equiTD 2018-03-04 12:46:47 +01:00
xdrm-brackets 821edf3f70 [repo.professor] prevent wrong statements to be executed 2018-03-04 12:05:10 +01:00
xdrm-brackets 99351cb8ab [repo.professor] remove PDO exception mode 2018-03-04 12:02:50 +01:00
xdrm-brackets 8bb07d4a33 [webpack.teacher.view] updated with VH data 2018-03-04 11:59:10 +01:00
xdrm-brackets 2352842543 [module.professor] GET (first URL0 argument '0' or '1' to activate VH data) 2018-03-04 11:58:56 +01:00
xdrm-brackets 587884d437 [repo.professor] get (gets by id if given, else getAll) | getWithVH (same as 'get' but with VH data) 2018-03-04 11:58:19 +01:00
xdrm-brackets e83b20e9ff minmod 2018-03-03 22:30:26 +01:00
xdrm-brackets b59d1cbeff [webpack.page.teachers] load professors through API + flex layout 2018-03-03 22:27:34 +01:00
xdrm-brackets fbb21b3ffa [page.teacher] card layout (html semantic + generic css) 2018-03-03 19:37:38 +01:00
xdrm-brackets d033df5ee7 removed 'toremove' 2018-03-03 16:47:57 +01:00
xdrm-brackets f046741a89 Removed API/release permission 2018-03-03 16:37:54 +01:00
xdrm-brackets e19a891802 toremove 2018-03-03 16:34:54 +01:00
xdrm-brackets 73a496faae [module.cas] POST fixed 'service' processed from $_SERVER variables 2018-03-03 16:32:10 +01:00
xdrm-brackets fa83d62d72 [webpack.login.data] now works with localhost|xdrm.io (used processed 'api.target') 2018-03-03 16:25:39 +01:00
xdrm-brackets b1c6ab5a0d [scss.global] updated BUTTONs to be more readable | [webpack.login] now works with API for CAS login 2018-03-03 16:21:41 +01:00
xdrm-brackets 0a8a8dc802 [router.controller.js] _SERVER fixed 'connected' variable 2018-03-03 16:01:39 +01:00
xdrm-brackets e80b20c0d2 [error.core.error] added 'MissingBody' and 'MissingHeaders' API download error descriptions 2018-03-03 16:01:20 +01:00
xdrm-brackets 65d1e78cf2 [webpack.login] now works with CAS authentication 2018-03-03 16:00:43 +01:00
xdrm-brackets 58a527d9d1 [webpack.config] added page 'login.js' 2018-03-03 15:55:39 +01:00
xdrm-brackets 2411b2ed88 [router.controller.page] Redirect to LOGIN page if no authentication 2018-03-03 15:55:10 +01:00
xdrm-brackets b537644258 [module.cas] DELETE for logout | GET for callback now works with tested system for pop-up 2018-03-03 15:50:11 +01:00
xdrm-brackets b9c2d119f5 [api.core.auth-system-default] fix 'cas_admin' that was in the wrong format 2018-03-03 15:00:32 +01:00
xdrm-brackets d7c6ac519c [module.cas] Now returns login if already validated by [api.core.auth-system-default]
[api.core.auth-system-default] implemented permission management with : 'cas_user', 'cas_admin' (cas_user is always here, cas_admin is added only if admin)
2018-03-03 14:57:43 +01:00
xdrm-brackets 3a2eaefd7f [database.core.database-driver] now does not emulate prepares nor stringify output 2018-03-03 14:56:19 +01:00
xdrm-brackets d7d08f07f8 [repo.professor] added getByLogin (for CAS authentication check) 2018-03-03 14:30:52 +01:00
xdrm-brackets aadefed195 [module.cas] Created callback (todo: store in SESSION) + [module.*] renamed all with lowercase API path 2018-03-02 09:27:58 +01:00
xdrm-brackets 7dedb80793 [http.core] Added legacy GET parameters to router's URL param 2018-03-02 08:14:58 +01:00
xdrm-brackets c76dc3c5ee added teacher client page 2018-03-01 18:26:07 +01:00
xdrm-brackets 2b71469530 [module.professor] implemented PUT 2018-03-01 18:25:21 +01:00
xdrm-brackets ad3626d64c [module.professor] implemented DELETE 2018-03-01 18:07:40 +01:00
xdrm-brackets 685c3ffc91 [module.professor] fixed POST > optional 'casLogin' | check if already exists | type 2018-03-01 18:01:45 +01:00
xdrm-brackets d0fbaa6f04 [router.controller.api] fixed content-type JSON header 2018-03-01 17:55:13 +01:00
xdrm-brackets 720be931c0 [module.professor] fixed GET + implemented POST 2018-03-01 17:45:40 +01:00
xdrm-brackets 3d56d90b47 [router.controller.api] added content-type JSON header 2018-03-01 17:43:03 +01:00
xdrm-brackets b2bce31632 [module.professor] implemented GET method (getById if id given, else getAll) 2018-03-01 17:31:15 +01:00
xdrm-brackets a2f84116ca [repo.professor] code clean up + error management (to test) 2018-03-01 17:22:22 +01:00
xdrm-brackets ffdc0bd15e [xdrm-framework] update: now implementations have 'Controller' as a suffix for the class name. 2018-03-01 17:21:48 +01:00
Unknown caafc646a8 Merge branch 'statistics' 2018-03-01 16:58:20 +01:00
Unknown ad56ce1751 fix DatabaseDriver encoding + implement prof category stats
(and add possiblity to get all formations stat in one query)
2018-03-01 16:57:58 +01:00
Unknown 8e7694502e Merge branch 'statistics' 2018-03-01 15:57:43 +01:00
Unknown 3ecda58c42 Add default formation for UEs + implemented stats for Formations 2018-03-01 15:57:25 +01:00
xdrm-brackets ddd12ef821 fixed css design features + working on list view 2018-03-01 13:16:22 +01:00
xdrm-brackets 72e140d5c5 Updated menu items 2018-02-28 13:00:51 +01:00
xdrm-brackets 9cb6b429c4 Merge branch 'master' of https://git.xdrm.io/ptut/vhost 2018-02-28 12:37:04 +01:00
xdrm-brackets 9543c7621c +added VueRouter 2018-02-28 12:36:54 +01:00
Unknown 0669ab895a Merge branch 'statistics' 2018-02-27 20:41:45 +01:00
Unknown c0bb4541a7 Refactor Repo + Fix TD Equivalent 2018-02-27 20:41:36 +01:00
SeekDaSky fd9357fdba Implemented TD Equivalent Computing for the professors 2018-02-27 18:25:13 +01:00
Unknown 65a8f7582c Merge branch 'excel-import' 2018-02-27 18:25:07 +01:00
SeekDaSky 58d0a5ee14 fix mising formations and groups 2018-02-27 18:24:49 +01:00
Unknown 3e1ab4796c Merge branch 'phpstan-fix' 2018-02-27 14:48:13 +01:00
Unknown 68cd097dec Fix framework with phpstan 2018-02-27 14:48:07 +01:00
Unknown ee121f225b Merge branch 'excel-import' 2018-02-27 14:47:08 +01:00
Unknown 30e5abede1 Working excel import + added phpstan to composer file 2018-02-27 14:46:53 +01:00
Unknown 1b0a52ded6 Add formations to output JSON 2018-02-27 14:46:53 +01:00
xdrm-brackets 5262318527 fix package.json 'build' also builds scss 2018-02-27 14:36:38 +01:00
xdrm-brackets 1c9fe2244a +add login_wrapper + fix menu + removed popup on page.home + minmod 2018-02-27 14:33:04 +01:00
xdrm-brackets 7073b3f967 updated 404 page 2018-02-22 15:34:24 +01:00
xdrm-brackets 633fc36aeb fixed webpack optimization 2018-02-22 14:26:07 +01:00
xdrm-brackets 70d0ce8143 added `npm run devjs` to watch js files 2018-02-21 19:35:07 +01:00
xdrm-brackets a74555864d No more hash (unconsistent for our use) no more need for cleaning each time (when watchmode active) 2018-02-21 19:34:41 +01:00
146 changed files with 16564 additions and 10866 deletions

5
.gitignore vendored
View File

@ -3,4 +3,7 @@
/vendor
/public_html/css
/public_html/js
/node_modules
/node_modules
/backup
/tmp
/public_html/tmp

View File

@ -6,6 +6,7 @@
if( !defined('__CONFIG__') ) define('__CONFIG__', __ROOT__.'/config' );
if( !defined('__BUILD__') ) define('__BUILD__', __ROOT__.'/build' );
if( !defined('__PUBLIC__') ) define('__PUBLIC__', __ROOT__.'/public_html' );
if( !defined('__BACKUP__') ) define('__BACKUP__', __ROOT__.'/backup' );
/* ACTIVE LE DEBUGGAGE (WARNING + EXCEPTION)

View File

@ -16,14 +16,14 @@
interface AuthSystem{
/* VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
*
* @expected<array> Liste des permissions attendues
*
* @return error<Error> Erreur associée à la permission (Success/PermissionError/TokenError/etc)
*
*/
public static function permission($expected);
/** VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
*
* @param array $expected Liste des permissions attendues
*
* @return Error Erreur associée à la permission (Success/PermissionError/TokenError/etc)
*
*/
public static function permission(array $expected) : Error;
}
?>

View File

@ -13,18 +13,101 @@
use \error\core\Err;
use \error\core\Error;
use \database\core\Repo;
use \database\repo\professor;
class AuthSystemDefault implements AuthSystem{
/* VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
*
* @expected<array> Liste des permissions attendues
*
* @return error<Error> Erreur associée à la permission (Success/PermissionError/TokenError/etc)
*
*/
public static function permission($expected){
return new Error(Err::Success);
public function __construct(){
/* (1) Init session variables
---------------------------------------------------------*/
if( !isset($_SESSION['CAS']) || !is_array($_SESSION['CAS']) ) $_SESSION['CAS'] = [];
if( !isset($_SESSION['AUTH']) || !is_array($_SESSION['AUTH']) ) $_SESSION['AUTH'] = [];
if( !isset($_SESSION['AvailableDepartments']) || !is_array($_SESSION['AvailableDepartments']) ) $_SESSION['AvailableDepartments'] = [];
if( !isset($_SESSION['VERSION']) || !is_array($_SESSION['VERSION']) ) $_SESSION['VERSION'] = [];
if( !isset($_SESSION['CurrentDepartmentId']) || !is_int($_SESSION['CurrentDepartmentId']) ) $_SESSION['CurrentDepartmentId'] = null;
/* (2) Process AUTH
---------------------------------------------------------*/
/* (1) cas_admin | cas_user */
if( isset($_SESSION['CAS']['admin']) && is_bool($_SESSION['CAS']['admin']) ){
// by default: cas_user
$_SESSION['AUTH'] = ['cas_user'];
// if admin: cas_admin
if( $_SESSION['CAS']['admin'] === true )
$_SESSION['AUTH'][] = 'cas_admin';
/* (2) Remove cas in AUTH */
}else{
$_SESSION['AUTH'] = \array_diff($_SESSION['AUTH'], ['cas_user']);
$_SESSION['AUTH'] = \array_diff($_SESSION['AUTH'], ['cas_admin']);
}
/* (3) Other permissions */
// TODO
}
/** VERIFICATION DES ACCES EN FONCTION DE PERMISSIONS ATTENDUES
*
* @param array $expected Liste des permissions attendues
*
* @return Error Erreur associée à la permission (Success/PermissionError/TokenError/etc)
*
*/
public static function permission(array $expected) : Error{
/* (1) Check format -> if not array of array(s) -> ERROR
---------------------------------------------------------*/
/* (1) If not array of array(s) -> ERROR */
foreach($expected as $permission_group)
if( !is_array($permission_group) )
return new Error(Err::FormatError);
/* (2) For each OR group
---------------------------------------------------------*/
foreach($expected as $OR_group){
/* (1) By default suppose the group is valid */
// -> an empty group will grant permission to all
$valid_group = true;
/* (2) Check for each AND permission in the group */
foreach($OR_group as $AND_perm){
/* (3) If not in session.auth -> invalidate the permission group */
if( !in_array($AND_perm, $_SESSION['AUTH']) ){
$valid_group = false;
break;
}
}
/* (4) If valid group -> Success */
if( $valid_group )
return new Error(Err::Success);
}
/* (5) If no valid group -> permission error */
return new Error(Err::PermissionError);
}
}

View File

@ -16,15 +16,15 @@
class Checker{
/* VERIFICATIONS DES TYPES UTILES GENERIQUES
/** VERIFICATIONS DES TYPES UTILES GENERIQUES
*
* @type<String> Type que l'on veut verifier
* @value<mixed*> Valeur a verifier
* @param String $type Type que l'on veut verifier
* @param mixed $value Valeur a verifier
*
* @return match<Boolean> Retourne si oui ou non la valeur @value est du bon type @type
* @return Boolean Retourne si oui ou non la valeur @value est du bon type @type
*
*/
public static function run($type, $value){
public static function run(String $type, $value) : bool {
$checker = true;
/* [0] On verifie que $value n'est pas nul
@ -44,6 +44,10 @@
// On recupere le sous-type si défini
$flags = isset($match[3]) ? explode(',', substr($match[3], 1)) : null;
// Si numeric -> to String
if( is_numeric($value) )
$value = (string) $value;
// On effectue la verification de taille
$lenCheck = $checker && is_string($value) && strlen($value) <= $max && strlen($value) >= $min;
@ -91,6 +95,11 @@
return $checker && is_numeric($value) && $value <= 2147483647 && $value >= 0;
break;
// Entier relatif (neg ou pos)
case 'int':
return $checker && is_int($value);
break;
// String quelconque (peut etre vide)
case 'text':
return $checker && is_string($value);
@ -106,7 +115,7 @@
break;
case 'alphanumeric':
return $checker && is_string($value) && preg_match('/^[\w\.-]+$/ui', $value);
return $checker && is_string($value) && preg_match('/^[\w\. -]+$/ui', $value);
break;
case 'letters':
@ -124,6 +133,7 @@
// Boolean
case 'boolean':
case 'bool':
return $checker && is_bool($value);
break;
@ -138,11 +148,11 @@
break;
case 'numeric':
return $checker && (is_numeric($value) || $value == null || $value == 'null');
return $checker && (is_numeric($value) || $value == null);
break;
case "float":
return $checker && is_float($value);
return $checker && ( is_int($value) || is_float($value) );
break;
default:

View File

@ -11,23 +11,34 @@
/* (1) Attributes
---------------------------------------------------------*/
/* (1) Static */
/** @var Config? */
private static $inst = null; // singleton instance
private static function config_path(){ return __ROOT__.'/config/modules.json'; }
private static function config_path() : String { return __ROOT__.'/config/modules.json'; }
/** @var array[String] */
public static $allowed_http_methods = [ "GET", "POST", "PUT", "DELETE" ];
/* (2) Instance */
/** @var array */
private $raw;
/** @var array */
public $index;
/** @var Error */
public $error;
/* (2) Private constructor
/** (2) Private constructor
*
* @path<String> Configuration path
* @param String|null $path Configuration path
*
---------------------------------------------------------*/
private function __construct($path=null){
private function __construct(?String $path=null){
// Set default error
$this->error = new Error(Err::Success);
@ -37,22 +48,28 @@
---------------------------------------------------------*/ {
/* (1) Vérification existence fichier config */
if( !file_exists($path) )
return $this->error->set(Err::UnreachableResource);
if( !file_exists($path) ) {
$this->error->set(Err::UnreachableResource);
return;
}
/* (2) Lecture fichier config */
$conf = @file_get_contents($path);
/* (3) Si erreur lecture */
if( $conf === false )
return $this->error->set(Err::UnreachableResource);
if( $conf === false ) {
$this->error->set(Err::UnreachableResource);
return;
}
/* (4) Parsage json */
$this->raw = json_decode( $conf, true );
/* (5) Gestion de l'erreur de parsage */
if( $this->raw == null )
return $this->error->set(Err::ParsingFailed, 'json');
if( $this->raw == null ) {
$this->error->set(Err::ParsingFailed, 'json');
return;
}
}
@ -62,7 +79,7 @@
/* (1) Initialisation */
$this->index = [];
$ref = [ '/' => array_merge($this->raw) ];
$ref = [ '/' => $this->raw ];
/* (2) Tant qu'il reste des @ref à traiter */
@ -110,12 +127,12 @@
/* (3) Static singleton 'get-or-create'
/** (3) Static singleton 'get-or-create'
*
* @return inst<Config> Configuration singleton
* @return Config Configuration singleton
*
---------------------------------------------------------*/
public static function get(){
public static function get() : Config{
/* (1) If @inst already exists -> return singleton */
if( self::$inst instanceof Config )

View File

@ -20,7 +20,11 @@
/* (2) Builds the documentation
*
---------------------------------------------------------*/
public function generate(Request $rq=null){
public static function generate(Request $rq=null){
if(is_null($rq)){
return new Response(new Error(Err::NullRequest));
}
/* (1) Get data from config
---------------------------------------------------------*/

View File

@ -15,15 +15,15 @@
class ModuleFactory{
/* INSTANCIE UN MODULE
/** INSTANCIE UN MODULE
*
* @module<String> Nom du module
* @arguments<Array> [OPTIONNEL] Arguments à passer au constructeur
* @param String $module Nom du module
* @param array $arguments [OPTIONNEL] Arguments à passer au constructeur
*
* @return instance<Module> Instance du module en question
* @return object|false Instance du module en question
*
*/
public static function getModule($module, $arguments=[]){
public static function getModule(String $module, array $arguments=[]){
/* (1) On gère les arguments */
$arguments = is_array($arguments) ? $arguments : [];
@ -35,11 +35,11 @@
$module_ns = str_replace('/', '\\', $module);
/* (4) On vérifie que la classe existe */
if( !file_exists(__BUILD__."/api/module$module.php") )
if( !file_exists(__BUILD__."/api/module${module}Controller.php") )
return false;
/* (5) On récupère la classe */
$class_name = "\\api\\module$module_ns";
$class_name = "\\api\\module${module_ns}Controller";
/* (6) On retourne une instance */
return new $class_name($arguments);

View File

@ -5,77 +5,98 @@
use \api\core\AuthSystem;
use \api\core\ModuleFactory;
use \api\core\Config;
use \error\core\Error;
use database\core\Repo;
use \error\core\Error;
use \error\core\Err;
class Request{
// Constantes
/** @var array[bool] */
private static $default_options = [ 'download' => false ];
/** @var AuthSystem|null */
private static $authsystem = null;
// Attributs prives utiles (initialisation)
/** @var array */
private $id; // chemin extrait de l'URI
/** @var array */
private $raw_params; // paramètres reçus
/** @var array */
private $params; // paramètres donnés à la fonction
/** @var array */
private $options; // options
/** @var String */
private $http_method; // methode HTTP appelante
// Contiendra l'etat de la requete
/** @var Error */
public $error;
/* (0) Constructeur d'une requete de module
/** (0) Constructeur d'une requete de module
*
* @uri<String> URI relative de l'appel
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
* @forced_method<String> Méthode demandée (optionnel)
* @param String|null $uri URI relative de l'appel
* @param array|null $params Tableau associatif contenant les parametres utiles au traitement
* @param String|null $forced_method Méthode demandée (optionnel)
*
* @return instance<Request> Instance crée
*
---------------------------------------------------------*/
public function __construct($uri=null, $params=null, $forced_method=null){
return $this->buildRequestObject($uri, $params, $forced_method);
$this->buildRequestObject($uri, $params, $forced_method);
}
/* (1) Constructeur d'une requete de module (delegation)
/** (1) Constructeur d'une requete de module (delegation)
*
* @uri<String> URI relative de l'appel
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
* @forced_method<String> Méthode demandée (optionnel)
* @param String|null $uri URI relative de l'appel
* @param array|null $params Tableau associatif contenant les parametres utiles au traitement
* @param String|null $forced_method Méthode demandée (optionnel)
*
* @return status<Boolean> Retourne si oui ou non tout s'est bien passe
* @return boolean Retourne si oui ou non tout s'est bien passe
*
---------------------------------------------------------*/
private function buildRequestObject($uri=null, $params=null, $forced_method=null){
private function buildRequestObject($uri=null, $params=null, $forced_method=null) :bool{
/* (1) Initialisation
---------------------------------------------------------*/
/* (1) Erreur par défaut */
$this->error = new Error(Err::Success);
/* (2) Si pas parametre manquant, on quitte */
if( is_null($uri) )
return $this->error->set(Err::MissingPath);
if( is_null($uri) ){
$this->error->set(Err::MissingPath);
return false;
}
/* (2) On vérifie la configuration
---------------------------------------------------------*/
/* (1) Dispatch if error */
if( Config::get()->error->get() != Err::Success )
return ($this->error = Config::get()->error);
if( Config::get()->error->get() != Err::Success ){
$this->error = Config::get()->error;
return false;
}
/* (3) Verification des types des parametres
---------------------------------------------------------*/
/* (1) Si path est une <string> */
if( !is_string($uri) ) // Si le type est incorrect
return $this->error->set(Err::WrongPathModule);
if( !is_string($uri) ){
$this->error->set(Err::WrongPathModule);
return false;
}
/* (2) Add slash at the beginning of URI */
if( !preg_match('@^\/@', $uri) )
@ -85,8 +106,10 @@
$this->raw_params = (is_array($params)) ? $params : [];
/* (4) On définit en constante la méthode HTTP */
if( !isset($_SERVER['REQUEST_METHOD']) && !is_string($forced_method) )
return $this->error->set(Err::UnknownHttpMethod);
if( !isset($_SERVER['REQUEST_METHOD']) && !is_string($forced_method) ){
$this->error->set(Err::UnknownHttpMethod);
return false;
}
$this->http_method = is_string($forced_method) ? strtoupper($forced_method) : strtoupper($_SERVER['REQUEST_METHOD']);
@ -129,14 +152,14 @@
/* (2) Definit le systeme d'authentification
/** (2) Definit le systeme d'authentification
*
* @instance<AuthSystem> Instance de type AuthSystem
* @param AuthSystem $instance Instance de type AuthSystem
*
* @return success<Boolean> Whether the AuthSystem is valid or not
* @return boolean Whether the AuthSystem is valid or not
*
---------------------------------------------------------*/
public static function setAuthSystem($instance=null){
public static function setAuthSystem( ?AuthSystem $instance=null) : bool{
/* (1) Check instance type */
if( !($instance instanceof AuthSystem) )
return false;
@ -149,20 +172,22 @@
/* (3) Verification du format et de la coherence du chemin specifie
/** (3) Verification du format et de la coherence du chemin specifie
*
* @URI<String> URI d'appel (commence par /)
* @param String $uri URI d'appel (commence par /)
*
* @return validity<Boolean> Retourne si oui ou non l'objet est correct
* @return boolean Retourne si oui ou non l'objet est correct
*
---------------------------------------------------------*/
private function checkURI($uri){
private function checkURI(String $uri) : bool{
/* (1) Verification format general
---------------------------------------------------------*/
/* (1) If wrong format -> exit */
if( !preg_match('@^\/[^\/]*(\/[^\/]*)*\/?$@', $uri) )
return $this->error->set(Err::WrongPathModule);
if( !preg_match('@^\/[^\/]*(\/[^\/]*)*\/?$@', $uri) ){
$this->error->set(Err::WrongPathModule);
return false;
}
/* (2) Add ending '/' if not there */
if( $uri[strlen($uri)-1] != '/' )
@ -188,8 +213,10 @@
}
/* (2) If @path not found -> exit */
if( is_null($path) )
return $this->error->set(Err::UnknownModule);
if( is_null($path) ){
$this->error->set(Err::UnknownModule);
return false;
}
/* (3) Extract URI parameters
@ -202,8 +229,10 @@
$uri_end = "/$uri_end";
/* (3) If invalid format, return error */
if( !preg_match('@^((?:\/[^\/]*)*)\/?$@', $uri_end, $uri_match) )
return $this->error->set(Err::InvalidURI);
if( !preg_match('@^((?:\/[^\/]*)*)\/?$@', $uri_end, $uri_match) ){
$this->error->set(Err::InvalidURI);
return false;
}
/* (4) Add each URI parameter to the parameter store */
$uri_args = array_slice( explode('/', $uri_match[1]), 1);
@ -219,12 +248,16 @@
$doc_req = $this->http_method == 'OPTIONS';
/* (2) Check if HTTP method is in allowed methods */
if( !in_array($this->http_method, Config::$allowed_http_methods) && !$doc_req )
return $this->error->set(Err::UnknownHttpMethod, $this->http_method);
if( !in_array($this->http_method, Config::$allowed_http_methods) && !$doc_req ){
$this->error->set(Err::UnknownHttpMethod, $this->http_method);
return false;
}
/* (3) Check if HTTP method is defined for this @path */
if( !isset(Config::get()->index[$path][$this->http_method]) && !$doc_req )
return $this->error->set(Err::UnknownMethod, $this->http_method);
if( !isset(Config::get()->index[$path][$this->http_method]) && !$doc_req ){
$this->error->set(Err::UnknownMethod, $this->http_method);
return false;
}
@ -241,12 +274,12 @@
/* (4) Retourne si on a la permission d'executer cette methode
/** (4) Retourne si on a la permission d'executer cette methode
*
* @return permission<bool> Retourne si on a les droits ou pas pour executer cette methode
* @return bool Retourne si on a les droits ou pas pour executer cette methode
*
---------------------------------------------------------*/
private function checkPermission(){
private function checkPermission() : bool{
/* (1) On recupere les informations utiles
---------------------------------------------------------*/
@ -263,8 +296,10 @@
if( !is_object(self::$authsystem) || !self::$authsystem instanceof AuthSystem ){
// try to load default AuthSystem
if( !file_exists(__BUILD__.'/api/core/AuthSystemDefault.php') )
return $this->error->set(Err::UnreachableResource);
if( !file_exists(__BUILD__.'/api/core/AuthSystemDefault.php') ){
$this->error->set(Err::UnreachableResource);
return false;
}
// load default AuthSystem class
$classname = '\\api\\core\\AuthSystemDefault';
@ -288,25 +323,29 @@
/* (5) Verification du type des parametres envoyes
/** (5) Verification du type des parametres envoyes
*
* @return correct<bool> Retourne si oui ou non les parametres ont le bon type
* @return bool Retourne si oui ou non les parametres ont le bon type
*
---------------------------------------------------------*/
private function checkParams(){
private function checkParams() : bool{
/* (1) On verifie qu'il ne manque aucun parametre
---------------------------------------------------------*/
/* (1) Si @params n'est pas un tableau */
if( !is_array($this->raw_params) )
return $this->error->set(Err::MissingParam);
if( !is_array($this->raw_params) ){
$this->error->set(Err::MissingParam);
return false;
}
/* (2) On récupère les données de la méthode */
$method = Config::get()->index[$this->id['path']][$this->id['method']];
/* (3) Si pas 'parameters' dans la config */
if( !isset($method['par']) || !is_array($method['par']) )
return $this->error->set(Err::ConfigError);
if( !isset($method['par']) || !is_array($method['par']) ){
$this->error->set(Err::ConfigError);
return false;
}
/* (2) Si le type est defini, pour chaque param, on teste
@ -316,16 +355,22 @@
/* (2.1) Vérification des données
---------------------------------------------------------*/
/* (1) Si @name n'est pas une string */
if( !is_string($name) )
return $this->error->set(Err::ConfigError);
if( !is_string($name) ){
$this->error->set(Err::ConfigError);
return false;
}
/* (2) Si @config n'est pas un tableau */
if( !is_array($config) )
return $this->error->set(Err::ConfigError);
if( !is_array($config) ){
$this->error->set(Err::ConfigError);
return false;
}
/* (3) So @config['typ] manquant ou incorrect */
if( !isset($config['typ']) || !is_string($config['typ']) )
return $this->error->set(Err::ConfigError);
if( !isset($config['typ']) || !is_string($config['typ']) ) {
$this->error->set(Err::ConfigError);
return false;
}
/* (2.2) Gestion des spécifications
@ -348,10 +393,12 @@
$default = $config['def'];
/* (3.1.2) If FILE and not null -> Check type */
if( $config['typ'] != 'FILE' || $default != null )
if( !Checker::run($config['typ'], $default) )
return $this->error->set(Err::WrongDefaultParam, $rename, $config['typ']);
if( $config['typ'] != 'FILE' || $default != null ){
if( !Checker::run($config['typ'], $default) ) {
$this->error->set(Err::WrongDefaultParam, $rename, $config['typ']);
return false;
}
}
}
/* (4) Si de type 'FILE' + fichier existe => on enregistre la ref. */
@ -359,8 +406,10 @@
$this->params[$rename] = &$_FILES[$name];
/* (4) Si param obligatoire et manquant -> erreur */
if( !isset($this->raw_params[$name]) && !$optional )
return $this->error->set(Err::MissingParam, $rename);
if( !isset($this->raw_params[$name]) && !$optional ) {
$this->error->set(Err::MissingParam, $rename);
return false;
}
/* (2.3) Gestion des valeurs
@ -374,9 +423,18 @@
/* (2) Si le paramètre est renseigné (sauf FILE) */
}elseif( $config['typ'] != 'FILE' ){
// Try to get json representation
$json_rep = json_decode('{"json": '.$this->raw_params[$name].'}', true);
// Use only if not failed
if( is_array($json_rep) && isset($json_rep['json']) )
$this->raw_params[$name] = $json_rep['json'];
// Si la verification est fausse, on retourne faux
if( !Checker::run($config['typ'], $this->raw_params[$name]) )
return $this->error->set(Err::WrongParam, $rename, $config['typ']);
if( !Checker::run($config['typ'], $this->raw_params[$name]) ){
$this->error->set(Err::WrongParam, $rename, $config['typ']);
return false;
}
// Sinon, on ajoute aux params qu'on enverra à l'appel
else
@ -395,12 +453,12 @@
/* (6) Ajout des options a partir de la configuration
/** (6) Ajout des options a partir de la configuration
*
* @return correct<bool> Retourne FAUS en cas d'erreur
* @return bool Retourne FAUS en cas d'erreur
*
---------------------------------------------------------*/
private function buildOptions(){
private function buildOptions() : bool{
/* (1) On récupère les options de la méthode en cours
---------------------------------------------------------*/
@ -440,12 +498,12 @@
/* (7) Execute le traitement associe et remplie la reponse
/** (7) Execute le traitement associe et remplie la reponse
*
* @return answer<Response> Retourne une reponse de type <Response> si tout s'est bien passe
* @return Response Retourne une reponse de type <Response> si tout s'est bien passe
*
---------------------------------------------------------*/
public function dispatch(){
public function dispatch() : Response{
/* (1) Vérifications de niveau 0
---------------------------------------------------------*/
@ -488,7 +546,7 @@
---------------------------------------------------------*/
/* (1) S'il s'agit d'un téléchargement -> on dispatch */
if( $this->options['download'] === true )
return $this->download();
return $this->download($returned);
/* (2) On construit la réponse avec l'erreur */
$response = new Response($this->error);
@ -496,6 +554,11 @@
/* (3) On ajoute les données */
$response->appendAll($returned);
/* (4) Si le Debug est actif on ajoute le debug des repo */
if(Repo::isDebugEnabled()){
$response->append("repoDebug" , Repo::getDebug());
}
/* (4) On retourne la réponse */
return $response;
@ -503,10 +566,11 @@
/* (8) Gestion d'un téléchargement HTTP
*
*/
public function download(){
/** (8) Gestion d'un téléchargement HTTP
*
* @return Response
*/
public function download($returned) : Response{
/* (1) Vérification des erreurs et paramètres
---------------------------------------------------------*/
@ -543,46 +607,51 @@
/* (2) On affiche le contenu */
echo $returned['body'];
return true;
return new Response();
}
/* (3) Gestion du téléchargement différé (AJAX)
---------------------------------------------------------*/
/* (1) On génère les noms de fichiers utiles */
/* (1) Create if not exists public_html/tmp */
if( !is_dir(__PUBLIC__.'/tmp') ){
mkdir(__PUBLIC__.'/tmp');
chmod(__PUBLIC__.'/tmp', 0775);
}
/* (2) On génère les noms de fichiers utiles */
$target_fname = '/tmp/download_'.uniqid().'.php'; // cible
$buffer_fname = __ROOT__.'/tmp/content_'.uniqid().'.php'; // buffer
/* (2) On écrit le BODY dans un fichier buffer */
/* (3) On écrit le BODY dans un fichier buffer */
$buffer_file = fopen($buffer_fname, 'w');
fwrite($buffer_file, $returned['body']);
fclose($buffer_file);
/* (3) On crée le fichier cible */
/* (4) On crée le fichier cible */
$target_fnameroot = __PUBLIC__.$target_fname;
$taret_file = fopen($target_fnameroot, 'w');
fwrite($taret_file, '<?php'.PHP_EOL);
/* (4) Script qui écrira les headers */
/* (5) Script qui écrira les headers */
foreach($returned['headers'] as $header=>$value)
fwrite($taret_file, "header(\"$header: $value\");".PHP_EOL);
fwrite($taret_file, 'header(\''.$header.': '.$value.'\');'.PHP_EOL);
/* (5) Script qui écrira le contenu du buffer */
/* (6) Script qui écrira le contenu du buffer */
chmod($buffer_fname, 0775);
fwrite($taret_file, "readfile('$buffer_fname');".PHP_EOL);
/* (6) Script qui supprimera les fichiers: buffer+target */
/* (7) Script qui supprimera les fichiers: buffer+target */
fwrite($taret_file, "unlink('$buffer_fname');".PHP_EOL);
fwrite($taret_file, "unlink(__FILE__);".PHP_EOL);
fwrite($taret_file, '?>'.PHP_EOL);
/* (7) On ferme le fichier cible */
/* (8) On ferme le fichier cible */
fclose($taret_file);
chmod($target_fnameroot, 0775);
/* (8) On envoie la réponse contenant le lien du fichier cible */
/* (9) On envoie la réponse contenant le lien du fichier cible */
$response = new Response($this->error);
$response->append('link', $target_fname);
@ -592,12 +661,13 @@
/* (9) Getter générique
/** (9) Getter générique
*
* @index<String> Index de l'attribut
* @param String $index Index de l'attribut
*
* @return mixed
---------------------------------------------------------*/
public function get($index=null){
public function get(?String $index=null){
switch($index){

View File

@ -17,31 +17,36 @@
class Response{
// Attributs prives utiles (initialisation)
/** @var array */
private $data;
/** @var Error */
public $error;
/* CONSTRUCTEUR D'UNE REPONSE DE MODULE
/** CONSTRUCTEUR D'UNE REPONSE DE MODULE
*
* @error<ModuleError> Erreur passee par la requete (si existe)
* @param Error $error Erreur passee par la requete (si existe)
*
*/
public function __construct($error=null){
public function __construct(?Error $error=null){
if( !( $error instanceof Error ) )
$error = new Error(Err::Success);
$this->data = [];
$this->error = $error;
}
/* AJOUTE UNE DONNEE A LA REPONSE
/** AJOUTE UNE DONNEE A LA REPONSE
*
* @key<String> Le nom de la valeur a ajouter
* @value<mixed*> La valeur a ajouter
* @param String $key Le nom de la valeur a ajouter
* @param mixed $value La valeur a ajouter
*
* @return Response
*/
public function append($key, $value){
public function append(String $key, $value) : Response{
// Ajoute une entree pour la cle @key et de valeur @value
$this->data[$key] = $value;
@ -49,12 +54,13 @@
}
/* AJOUTE TOUTES LES DONNEES A LA REPONSE
/** AJOUTE TOUTES LES DONNEES A LA REPONSE
*
* @dataset<Array> Le tableau associatif correspondant a la reponse
* @param array $dataset Le tableau associatif correspondant a la reponse
*
* @return Response
*/
public function appendAll($dataset){
public function appendAll(array $dataset) : Response{
// Si ce n'est pas un tableau, on ne fais rien
if( !is_array($dataset) )
return $this;
@ -72,17 +78,16 @@
return $this;
}
/* RECUPERE UNE DONNEE DE LA REPONSE
/** RECUPERE UNE DONNEE DE LA REPONSE
*
* @key<String> Le nom de la valeur a recuperer
* @param String $key Le nom de la valeur a recuperer
*
* @return value<mixed*> La valeur a cette cle
* @return error<null> Retourne NULL si aucune valeur pour cette cle
* @return mixed|null La valeur a cette cle, NULL si aucune valeur pour cette cle
*
*/
public function get($key){
public function get(String $key){
// Si la valeur de cle @key n'existe pas, on retourne NULL
if( !isset($this->data[$key]) )
return null;
@ -92,9 +97,9 @@
}
/* RECUPERE TOUTES LES DONNEES DE LA REPONSE
/** RECUPERE TOUTES LES DONNEES DE LA REPONSE
*
* @return data<Array> Les donnees de la reponse
* @return array Les donnees de la reponse
*
*/
public function getAll(){
@ -103,12 +108,12 @@
}
/* SERIALISATION A PARTIR DES DONNEES
/** SERIALISATION A PARTIR DES DONNEES
*
* @return json<String> Retourne les donnees serialisees
* @return String Retourne les donnees serialisees
*
*/
public function serialize(){
public function serialize() : String{
// Code Http
$this->error->setHttpCode();

View File

@ -1,235 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 19/02/18
* Time: 21:31
*/
namespace api\module;
use error\core\Err;
use error\core\Error;
use PhpOffice\PhpSpreadsheet\Exception;
class Excel
{
private const startLineUE = 5;
private const startLineProf = 10;
public function post($args){
if(isset($_FILES["file"]["tmp_name"])){
try{
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($_FILES["file"]["tmp_name"]);
$spreadsheet->setActiveSheetIndex(0);
$UESpreadsheet = $spreadsheet->getActiveSheet();
/*
* Setting Up state variables
*/
//current formation
$formation = "";
//current UE code
$UECode = "";
//current UE
$UE = [];
//array containing all the UEs
$allUE = [];
/*
* declare the lambda that will add finalized UE to the array
*/
$addEU = function() use (&$UECode,&$allUE,&$UE){
if($UECode != ""){
if(isset($allUE[$UECode])){
$counter = 1;
while(isset($allUE[$UECode.$counter])) $counter++;
$allUE[$UECode.$counter] = $UE;
}else{
$allUE[$UECode] = $UE;
}
$UE = [];
}
};
/*
* declaring the lambda tha twill extract the list of formation involved in the group
*/
$getFormations = function(?string $group) use (&$formation) : array{
if(!$group) return [$formation];
//replace the generic "INFO" keyword by the actual formation
$group = str_replace("INFO",$formation,$group);
//split the string
$groups = explode("+",$group);
//trim the strings
$groups = array_map('trim', $groups);
//delete empty strings
return array_filter($groups);
};
/*
* declaring the lambda that will compute the part of internal students in the course (used for stats purpose)
*/
$getInternalStudentPart = function(?string $group) use (&$formation, $getFormations) : float{
if(!$group) return 1.0;
$groups = $getFormations($group);
if(!in_array($formation,$groups)){
return 0.0;
}else{
return 1/count($groups);
}
};
//starting the iteration
foreach($UESpreadsheet->getRowIterator() as $row){
//skip the first rows
if($row->getRowIndex() < Excel::startLineUE) continue;
$firstCellValue = $UESpreadsheet->getCellByColumnAndRow(1,$row->getRowIndex())->getValue();
$secondCellValue = $UESpreadsheet->getCellByColumnAndRow(2,$row->getRowIndex())->getValue();
//if the first value is not null and the second is, this means we change formation and rest the UUCode
if($secondCellValue == "" and $firstCellValue != "") {$formation = $firstCellValue; $addEU(); $UECode = ""; continue; }
//if no UE is set yet, find it
if($UECode == "" and $firstCellValue != "") $UECode = $firstCellValue;
//if the line is empty this means we change UE
if($firstCellValue == "" and $secondCellValue == "") {$addEU(); $UECode = ""; continue;}
//now we have a formation, a UE and we are sure the line is not empty, let's fill up this bad boy
//if the required field is not set this means we are at the header of the UE
if(!isset($UE["required"])){
$UE["name"] = $UESpreadsheet->getCellByColumnAndRow(2,$row->getRowIndex())->getCalculatedValue();
$UE["required"] = $UESpreadsheet->getCellByColumnAndRow(3,$row->getRowIndex())->getValue();
$UE["TotalVH"] = $UESpreadsheet->getCellByColumnAndRow(4,$row->getRowIndex())->getCalculatedValue();
$UE["CourseVH"] = $UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex())->getValue() ?: 0.0;
$UE["CourseGroup"] = $UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex())->getValue() ?: 0;
$UE["TdVH"] = $UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex())->getValue() ?: 0.0;
$UE["TdGroup"] = $UESpreadsheet->getCellByColumnAndRow(9,$row->getRowIndex())->getValue() ?: 0;
$UE["TpVH"] = $UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex())->getValue() ?: 0.0;
$UE["TpGroup"] = $UESpreadsheet->getCellByColumnAndRow(12,$row->getRowIndex())->getValue() ?: 0;
continue;
}
//we have a new group! if the array is not set, initialize it
if(!isset($UE["groups"])) $UE["groups"] = [
"Course" => [],
"TD" => [],
"TP" => []
];
//compute Course
if ($UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex())->getCalculatedValue()){
$UE["groups"]["Course"][] = [
"VH" => $UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex())->getValue()),
"formations" => $getFormations($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex())->getValue()),
"professor" => $UESpreadsheet->getCellByColumnAndRow(7,$row->getRowIndex())->getValue() ?: null
];
}
//compute TDs
if($UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex())->getCalculatedValue()){
$UE["groups"]["TD"][] = [
"VH" => $UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart($UESpreadsheet->getCellByColumnAndRow(9,$row->getRowIndex())->getValue()),
"formations" => $getFormations($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex())->getValue()),
"professor" => $UESpreadsheet->getCellByColumnAndRow(10,$row->getRowIndex())->getValue() ?: null
];
}
//compute TPs
if($UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex())->getCalculatedValue()){
$UE["groups"]["TP"][] = [
"VH" => $UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart($UESpreadsheet->getCellByColumnAndRow(12,$row->getRowIndex())->getValue()),
"formations" => $getFormations($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex())->getValue()),
"professor" => $UESpreadsheet->getCellByColumnAndRow(13,$row->getRowIndex())->getValue() ?: null
];
}
}
/*
* Now we compute the professor list to get the full name , the number of hour he must do and the category he is in
*/
$spreadsheet->setActiveSheetIndex(1);
$ProfSpreadshit = $spreadsheet->getActiveSheet();
//array containing all the professors
$allProf = [];
//current professor category
$currentCategory = "";
//category as represented in the excel (as a number)
$currentCategoryIndex = 0;
foreach($ProfSpreadshit->getRowIterator() as $row){
//skip the first lines
if($row->getRowIndex() < Excel::startLineProf) continue;
$firstCellValue = $ProfSpreadshit->getCellByColumnAndRow(2,$row->getRowIndex())->getValue();
$secondCellValue = $ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex())->getValue();
//skip empty lines
if(!$firstCellValue and !$secondCellValue) continue;
//if the first cell contains something and not the second, it means that we change category
if($firstCellValue && !$secondCellValue){
$currentCategory = $firstCellValue;
$currentCategoryIndex++;
}
//if the line is valid
if($ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex())->getValue() and $ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex())->getValue()){
$allProf[$ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex())->getValue()] = [
"categoryLabel" => $currentCategory,
"categoryIndex" => $currentCategoryIndex,
"lastName" => explode(" ",$ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex())->getValue(),2)[1],
"firstName" => explode(" ",$ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex())->getValue(),2)[0],
"hoursToDo" => $ProfSpreadshit->getCellByColumnAndRow(5,$row->getRowIndex())->getValue() ?: 0
];
}
}
return [ 'data' => ["professors" => $allProf, "UEs" => $allUE ] ];
}catch (Exception $e){
return [ 'error' => new Error(Err::UnknownError) ];
}
}else{
return [ 'error' => new Error(Err::UploadError) ];
}
}
}

View File

@ -1,133 +0,0 @@
<?php
namespace api\module;
use \error\core\Error;
use \error\core\Err;
use \database\core\Repo;
class admin{
/* (1) Return an admin data
*
* @id_admin<id> [OPT] UID de l'administrateur
*
* @return data<Array> Administrateurs correspondants
*
---------------------------------------------------------*/
public static function get($args){
extract($args);
/* (1) If @id_admin is set -> get by id
---------------------------------------------------------*/
if( is_numeric($id_admin) ){
/* (1) Search admin by id */
$fetch_admin = Repo::request('admin', 'getById', $id_admin);
/* (2) If not found -> return empty data */
if( !$fetch_admin )
return [ 'data' => [] ];
/* (3) Return fetched admin */
return [ 'data' => [$fetch_admin] ];
/* (2) Else -> get all
---------------------------------------------------------*/
}else
return [ 'data' => Repo::request('admin', 'getAll') ];
}
/* (2) Creates a new administrator
*
* @username<string> Identifiant de l'administrateur
* @mail<string> Adresse mail de l'administrateur
* @password<string> Mot de passe de l'administrateur
*
* @return admin<array> Données de l'administrateur crée
*
---------------------------------------------------------*/
public static function post($args){
extract($args);
/* (1) Création admin */
$id_created = Repo::request('admin', 'create', $username, $mail, $password);
/* (2) Gestion erreur */
if( $id_created === false )
return [ 'error' => new Error(Err::RepoError) ];
/* (3) Renvoi @id_admin */
return [ 'id_admin' => Repo::request('admin', 'getById', $id_created) ];
}
/* (3) Updates an existing administrator
*
* @id_admin<id> UID de l'administrateur
* @mail<string> [OPT] Adresse mail de l'administrateur
* @password<string> [OPT] Mot de passe de l'administrateur
*
* @return admin<array> The new administrator data
*
---------------------------------------------------------*/
public static function put($args){
extract($args);
/* (1) If @mail given
---------------------------------------------------------*/
if( !is_null($mail) ){
/* (1) Update mail address */
$updated = Repo::request('admin', 'setMail', $id_admin, $mail);
/* (2) Gestion erreur */
if( $updated === false )
return [ 'error' => new Error(Err::RepoError) ];
}
/* (2) If @password given
---------------------------------------------------------*/
if( !is_null($password) ){
/* (1) Update password */
$updated = Repo::request('admin', 'setPassword', $id_admin, $password);
/* (2) Gestion erreur */
if( $updated === false )
return [ 'error' => new Error(Err::RepoError) ];
}
/* (3) Renvoi @id_admin */
return [ 'id_admin' => Repo::request('admin', 'getById', $id_admin) ];
}
/* (4) Deletes an existing administrator
*
* @id_admin<id> UID de l'administrateur
*
* @return removed<bool> Whether the admin has been removed
*
---------------------------------------------------------*/
public static function delete($args){
extract($args);
/* (1) Dispatch du status */
return [ 'removed' => Repo::request('admin', 'delete', $id_admin) ];
}
}

View File

@ -0,0 +1,262 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 27/02/18
* Time: 16:19
*/
namespace api\module;
use database\core\Repo;
use database\repo\professor;
use database\repo\meta;
use error\core\Error;
use error\core\Err;
class casController{
/* (1) Authentication callback
*
* @popup_mode<boolean> Whether to manage the popup
* @GET[ticket]<String> CAS callback @ticket
*
* @return headers|body<array> The download content
*
---------------------------------------------------------*/
public static function get($args){
$popup_mode = false;
extract($args);
// login: https://sso.univ-pau.fr/cas/login?service=http://ptut.com:8080/api/v/1.0/cas
// Communicate over popups
// ----------------------------
// window.pop = { closed: false };
//
// window.cas_callback = function(cas_login){
//
// setTimeout( function(){
//
// if( window.pop.closed )
// console.log('CAS login (null means error): '+cas_login);
//
// }, 1);
//
// };
// Launch PopUp
// window.pop = window.open('https://sso.univ-pau.fr/cas/login?service=http://ptut.com:8080/api/v/1.0/cas', '_blank', 'location=no,height=1024,width=1024,scrollbars=yes,status=no');
/* (0) Initialize
---------------------------------------------------------*/
/* (1) Global DOWNLOAD data */
$headers = ['Content-Type' => 'text/html; charset=UTF-8' ];
/* (2) If @popup_mode */
if( $popup_mode !== 0 ){
$body_start = "Veuillez patienter...<br>Vous allez être redirigés<script type='text/javascript'>( typeof window.opener.cas_callback === 'function' ) && window.opener.cas_callback(";
$body_end = "); window.close();</script>";
/* (3) Else -> redirection */
}else{
$homepage = ($_SERVER['SERVER_NAME'] == 'ptut.com' ) ? 'http' : 'https';
$homepage .= '://'.$_SERVER['HTTP_HOST'].'/home';
$body_start = "Veuillez patienter...<br>Vous allez être redirigés<script type='text/javascript'>console.log(";
$body_end = "); document.location = '$homepage'; </script>";
}
/* (4) Reset SESSION */
// $_SESSION['CAS'] = [];
/* (1) Check if already connected
---------------------------------------------------------*/
/* (1) If already -> return @cas_login */
if( in_array('cas_user', $_SESSION['AUTH']) ){
return [
'headers' => $headers,
'body' => $body_start."'".$_SESSION['CAS']['login']."'".$body_end
];
}
/* (2) Fail if no ticket */
if( !isset($_GET['ticket']) || !is_string($_GET['ticket']) || strlen($_GET['ticket']) < 1 )
return [ 'headers' => $headers, 'body' => $body_start.'-1'.$body_end ];
/* (2) Check ticket (validate)
---------------------------------------------------------*/
/* (1) Build useful variables */
$service = ($_SERVER['SERVER_PORT'] == 80) ? 'http' : 'https';
$service .= '://'.$_SERVER['HTTP_HOST'].'/api/v/1.0/cas/'.$popup_mode;
$ticket = urlencode($_GET['ticket']);
$validate_url = "https://sso.univ-pau.fr/cas/serviceValidate?ticket=$ticket&service=$service";
/* (2) Configure & Prepare CURL */
$ch = \curl_init();
\curl_setopt($ch, CURLOPT_URL, $validate_url);
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
/* (3) Execute CURL & Close it */
$output = \curl_exec($ch);
\curl_close($ch);
/* (4) Fail if not validated */
if( strpos($output, 'user') === false )
return [ 'headers' => $headers, 'body' => $body_start.'-2'.$body_end ];
/* (5) Extract cas_login */
$cas_login = trim(strip_tags($output));
/* (6) Check empty */
if( strlen($cas_login) < 1 )
return [ 'headers' => $headers, 'body' => $body_start.'-2'.$body_end ];
/* (3) Meta database: check if @cas_login referenced
---------------------------------------------------------*/
/** @var professor $prof_repo */
$prof_repo = Repo::getRepo('professor');
/** @var meta $meta_repo */
$meta_repo = Repo::getRepo('meta');
/* (1) Get the list of linked departments for this @cas_login */
$departments = $meta_repo->get_prof_departments($cas_login);
/* (2) Failure: if no department for @cas_login */
if( count($departments) === 0 )
return [ 'headers' => $headers, 'body' => $body_start.'-3'.$body_end ];
/* (3) Set departments data */
$_SESSION['AvailableDepartments'] = $departments;
/* (4) Choose first department by default */
$_SESSION['CurrentDepartmentId'] = $departments[0]['idDep'];
$_SESSION['VERSION'] = [
'list' => $departments[0]['versions'],
'current' => null
];
/* (5) select version with default = 1 */
foreach($_SESSION['VERSION']['list'] as $v){
if( $v['default'] == 1 ){
$_SESSION['VERSION']['current'] = intval($v['iddatabase']);
$_SESSION['CurrentDatabase'] = $v['dbName'];
break;
}
}
/* (6) if no default -> select first */
if( !is_int($_SESSION['VERSION']) ){
$_SESSION['VERSION']['current'] = intval($_SESSION['VERSION']['list'][0]['iddatabase']);
$_SESSION['CurrentDatabase'] = $_SESSION['VERSION']['list'][0]['dbName'];
}
/* (7) Use this department's database */
Repo::switchDatabase($_SESSION['CurrentDatabase']);
/* (4) Fetch @cas_login professor data
---------------------------------------------------------*/
/* (1) Try to fetch professor */
$by_login = $prof_repo->getByLogin($cas_login);
/* (2) If not found -> reset SESSION */
if( !is_array($by_login) || !isset($by_login['idProfesseur']) || !isset($by_login['admin']) )
return [ 'headers' => $headers, 'body' => $body_start.'-4'.$body_end ];
/* (5) Store data in session
---------------------------------------------------------*/
/* (1) Security */
\session_regenerate_id();
/* (2) Store CAS user data in SESSION */
$_SESSION['CAS'] = [
'login' => $cas_login,
'ticket' => $ticket,
'id' => (int) $by_login['idProfesseur'],
'admin' => (bool) $by_login['admin']
];
/* (3) Success CAS login */
return [
'headers' => $headers,
'body' => $body_start."'".$_SESSION['CAS']['login']."'".$body_end
];
}
/* (2) Logout from CAS server
*
* @return logged_out<bool> Whether you have been logged out
*
---------------------------------------------------------*/
public function put(){
/* (1) Call logout script
---------------------------------------------------------*/
/* (1) Build useful variables */
$logout_url = "https://sso.univ-pau.fr/cas/logout";
/* (2) Configure & Prepare CURL */
$ch = \curl_init();
\curl_setopt($ch, CURLOPT_URL, $logout_url);
\curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
\curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
/* (3) Execute CURL & Close it */
$output = \curl_exec($ch);
\curl_close($ch);
/* (4) Error if no output */
if( strlen($output) < 1 )
return ['logged_out' => false, 'redirect_url' => $logout_url];
/* (4) Destroy session */
\session_destroy();
/* (5) Return if logged out */
return ['logged_out' => true, 'redirect_url' => $logout_url];
}
/* (3) Logout (not from CAS server)
*
* @return logged_out<bool> Whether you have been logged out
*
---------------------------------------------------------*/
public function delete(){
\session_destroy();
/* (3) Return if logged out */
return ['logged_out' => true];
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 01/03/18
* Time: 16:43
*/
namespace api\module;
use database\core\Repo;
use database\repo\category;
class categoryController{
/* (1) Returns 1 or all categories
*
* @cat_id<int> [OPT] The category id
*
* @return categories<array> The categorie(s) data
*
---------------------------------------------------------*/
public function get($args){
$cat_id = null;
extract($args);
/** @var category $cat_repo */
$cat_repo = Repo::getRepo('category');
/* (1) Get All categories or 1 by its id (if set) */
$fetched = $cat_repo->get($cat_id);
/* (2) Return data */
return ['categories' => $fetched];
}
}

View File

@ -0,0 +1,25 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 05/03/18
* Time: 19:36
*/
namespace api\module\department;
use database\core\Repo;
use database\repo\department;
class errorsController
{
public static function get($args){
/** @var department $repo */
$repo = Repo::getRepo("department");
return ["data" => $repo->getErrors()];
}
}

View File

@ -0,0 +1,182 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 10/05/18
* Time: 13:03
*/
namespace api\module\department;
use database\core\Repo;
use database\repo\cours;
use database\repo\formation;
use database\repo\td;
use database\repo\tp;
use database\repo\ue;
use PhpOffice\PhpSpreadsheet\Reader\Xls\Style\Border;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Borders;
class exportController
{
public function get($args){
/** @var ue $ueRepo */
$ueRepo = Repo::getRepo("ue");
/** @var cours $cmRepo */
$cmRepo = Repo::getRepo("cours");
/** @var td $tdRepo */
$tdRepo = Repo::getRepo("td");
/** @var tp $tpRepo */
$tpRepo = Repo::getRepo("tp");
/** @var formation $formationRepo */
$formationRepo = Repo::getRepo("formation");
$ues = $ueRepo->exportUE();
$formations = [];
//cache formations labels
foreach ($formationRepo->get(null) as $form){
$formations[$form["idForm"]] = $form["labelForm"];
}
$formatFormations = function(String $formationsId) use ($formations) : String{
$returned = "";
foreach (json_decode($formationsId,true) as $form){
$returned .= $formations[$form]."+";
}
return rtrim($returned,"+");
};
$spreadsheet = new Spreadsheet();
$excel = $spreadsheet->getActiveSheet();
//set up base document
$arrayHeaders = ["Code","Intitulé","Statut","V.H.","Cours","NbGr","Enseignant","TD","NbGr","Enseignant","TP","NbGr","Enseignant","Equ. TD","Total"];
$excel->setCellValue("B2","CODIFICATION DES UE");
$i = 1;
foreach ($arrayHeaders as $header){
$excel->setCellValueByColumnAndRow($i,4,$header);
$i++;
}
$excel->freezePane("O5");
//set up state variables
$currentFormation = null;
$currentLine = 5;
foreach ($ues as $ue){
if($currentFormation != $ue["labelFormation"]){
$currentFormation = $ue["labelFormation"];
$excel->setCellValue("A$currentLine",$ue["labelFormation"]);
$excel->getStyle("A$currentLine")->getFont()->setBold(true)->setSize(11);
$excel->getStyle("A$currentLine:O$currentLine")->getBorders()->getTop()->setBorderStyle(\PhpOffice\PhpSpreadsheet\Style\Border::BORDER_DOUBLE);
$currentLine += 2;
}
//get all groups data
$cm = $cmRepo->getGroups($ue["code"]);
$td = $tdRepo->getGroups($ue["code"]);
$tp = $tpRepo->getGroups($ue["code"]);
//set UE header
$nbrGroupeCM = count($cm);
$nbrGroupeTD = count($td);
$nbrGroupeTP = count($tp);
$volumeUE = $ue["volumeCours"] + $ue["volumeTD"] + $ue["volumeTP"];
$equiTDUE = $nbrGroupeCM*1.5*$ue["volumeCours"] + $nbrGroupeTD*$ue["volumeTD"] + $nbrGroupeTP*$ue["volumeTP"];
$excel->setCellValue("A$currentLine",$ue["code"]);
$excel->setCellValue("B$currentLine",$ue["label"]);
$excel->setCellValue("C$currentLine",$ue["required"] == 1? "OBL" : "OPT");
$excel->setCellValue("D$currentLine","$volumeUE");
$excel->setCellValue("E$currentLine","{$ue["volumeCours"]}");
$excel->setCellValue("F$currentLine","$nbrGroupeCM");
$excel->setCellValue("H$currentLine","{$ue["volumeTD"]}");
$excel->setCellValue("I$currentLine","$nbrGroupeTD");
$excel->setCellValue("K$currentLine","{$ue["volumeTP"]}");
$excel->setCellValue("L$currentLine","$nbrGroupeTP");
$excel->setCellValue("O$currentLine","$equiTDUE");
$excel->getStyle("A$currentLine:O$currentLine")->getFont()->setBold( true )->setSize(9);
$currentLine++;
$nbrLine = max($nbrGroupeCM,$nbrGroupeTD,$nbrGroupeTP)-1;
foreach (range(0,$nbrLine) as $n){
$excel->setCellValue("A$currentLine",$ue["code"]);
$excel->setCellValue("B$currentLine",$ue["label"]);
$equiTD = 0;
if(isset($cm[$n])){
$excel->setCellValue("E$currentLine","{$cm[$n]["volume"]}");
$excel->setCellValue("F$currentLine",$formatFormations($cm[$n]["formations"]));
$excel->setCellValue("G$currentLine",$cm[$n]["lastName"]." ".$cm[$n]["firstName"]);
$equiTD += 1.5*$cm[$n]["volume"];
}
if(isset($td[$n])){
$excel->setCellValue("H$currentLine","{$td[$n]["volume"]}");
$excel->setCellValue("I$currentLine",$formatFormations($td[$n]["formations"]));
$excel->setCellValue("J$currentLine",$td[$n]["lastName"]." ".$td[$n]["firstName"]);
$equiTD += $td[$n]["volume"];
}
if(isset($tp[$n])){
$excel->setCellValue("K$currentLine","{$tp[$n]["volume"]}");
$excel->setCellValue("L$currentLine",$formatFormations($tp[$n]["formations"]));
$excel->setCellValue("M$currentLine",$tp[$n]["lastName"]." ".$tp[$n]["firstName"]);
$equiTD += $tp[$n]["volume"];
}
$excel->setCellValue("N$currentLine","$equiTD");
$excel->getStyle("A$currentLine:O$currentLine")->getFont()->setSize(8);
$currentLine++;
}
$currentLine++;
}
//resize all columns
foreach(range('A','O') as $columnID) {
$excel->getColumnDimension($columnID)->setAutoSize(true);
}
//set content type headers
// header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//reating writer
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xls($spreadsheet);
//as phpSpreadSheet do not support output on the buffer, we have to write in a temp file then read it
//create temporary file;
$file = tmpfile();
//get URI
$metaDatas = stream_get_meta_data($file);
$tmpFilename = $metaDatas['uri'];
//close file pointer
fclose($file);
//write data
$writer->save("$tmpFilename");
//get file content
return [
'headers' => [
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'Content-Disposition' => 'attachment; filename=archive.xls'
],
'body' => file_get_contents($tmpFilename)
];
}
}

View File

@ -0,0 +1,25 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 08/03/18
* Time: 17:36
*/
namespace api\module\department;
use database\core\Repo;
use database\repo\department;
class statsController
{
public static function get($args){
/** @var department $repo */
$repo = Repo::getRepo("department");
return ["data" => $repo->getStats()];
}
}

View File

@ -0,0 +1,28 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 07/05/18
* Time: 17:59
*/
namespace api\module\department\version;
use database\core\Repo;
class switchController
{
public function get($args){
$version = null;
extract($args);
$versionData = Repo::getRepo("meta")->getVersionById($version);
$_SESSION['CurrentDatabase'] = $versionData["dbName"];
$_SESSION['VERSION']['current'] = intval( $version );
return ["success" => true];
}
}

View File

@ -0,0 +1,158 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 15/03/18
* Time: 15:50
*/
namespace api\module\department;
use database\core\Repo;
use database\repo\meta;
use error\core\Error;
use error\core\Err;
use database\repo\department;
use Ifsnop\Mysqldump\Mysqldump;
class versionController{
/* (4) List available versions for this department
*
* @return versions<array> Version list
*
---------------------------------------------------------*/
public function get($args){
//search for the current department in the session and return its versions
/** @var meta $depRepo */
$depRepo = Repo::getRepo("meta");
//if no department found, return an empty array
return ['versions' => $depRepo->getAllVersions($_SESSION['CurrentDepartmentId']) ];
}
/* (5) Remove an existing version for this department
*
* @version<int> Version name (typically snapshot date)
*
* @return deleted<bool> Whether the version has been deleted
*
---------------------------------------------------------*/
public function delete($args){
$version = null;
extract($args);
/* (1) Try to delete */
$deleted = Repo::getRepo("meta")->deleteVersion($version);
if( !$deleted )
return ['error' => new Error(Err::ModuleError)];
/* (2) Update version list */
$_SESSION['VERSION']['list'] = Repo::getRepo("meta")->getAllVersions($_SESSION['CurrentDepartmentId']);
/* (3) Update current */
$_SESSION['VERSION']['current'] = null;
// select version with default = 1
foreach($_SESSION['VERSION']['list'] as $v){
if( $v['default'] == 1 ){
$_SESSION['VERSION']['current'] = intval($v['iddatabase']);
$_SESSION['CurrentDatabase'] = $v['dbName'];
break;
}
}
// if no default -> select first
if( !is_int($_SESSION['VERSION']) ){
$_SESSION['VERSION']['current'] = intval($_SESSION['VERSION']['list'][0]['iddatabase']);
$_SESSION['CurrentDatabase'] = $_SESSION['VERSION']['list'][0]['dbName'];
}
return ['deleted' => true];
}
/* (6) Creates a new version (snapshot of database) from now
*
* @return created_id<String> The created version id (date)
*
---------------------------------------------------------*/
public function post($args){
$label = null;
extract($args);
/* (2) Try to create the snapshot */
try{
/* (2.1) Get database configuration */
$conf = Repo::getDBConfig();
/* (2.2) Try to dump the database */
/** @var Mysqldump*/
$dump = new Mysqldump(
'mysql:host='.$conf['host'].';dbname='.$_SESSION['CurrentDatabase'],
$conf['username'],
$conf['password']
);
//create temporary file;
$file = tmpfile();
//get URI
$metaDatas = stream_get_meta_data($file);
$tmpFilename = $metaDatas['uri'];
//close file pointer
fclose($file);
//fill the file with sql dump
$dump->start($tmpFilename);
/** @var department $depRepo */
$depRepo = Repo::getRepo("department");
$dbName = $depRepo->createVersionDatabase($_SESSION['CurrentDepartmentId'],file_get_contents($tmpFilename));
/** @var meta $metaRep */
$metaRep = Repo::getRepo("meta");
$versionId = $metaRep->createVersion($label, $dbName,$_SESSION['CurrentDepartmentId'] ,false);
/* (2.5) Return status */
return ['created_id' => $versionId ];
/* (3) On error -> dispatch error */
}catch(\Exception $e){
return ['error' => new Error(Err::RepoError)];
}
}
/* (6) Modify a version and use it
*
*
* @return bool success
*
---------------------------------------------------------*/
public function put($args){
$label = null;
$version = null;
$default = null;
extract($args);
/** @var meta $metaRepo */
$metaRepo = Repo::getRepo("meta");
/* (4) Return status */
return [ 'updated' => $metaRepo->updateVersion($version,$label,$default) ];
}
}

View File

@ -0,0 +1,164 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 15/03/18
* Time: 11:47
*/
namespace api\module;
use database\core\Repo;
use database\repo\database;
use database\repo\department;
use database\repo\meta;
use database\repo\professor;
class departmentController
{
/* (1) Get 1 | all departments
*
* @id_dep<int> [OPT] Department id
*
* @return departments<array> Matching departments
*
---------------------------------------------------------*/
public function get($args){
$id_dep = null;
extract($args);
/** @var meta $meta_repo */
$meta_repo = Repo::getRepo('meta');
/* (1) Get the list of linked departments for this @cas_login */
$departments = $meta_repo->get_prof_departments($_SESSION['CAS']['login']);
/* (2) If no @id_dep -> return all */
if( is_null($id_dep) )
return ['departments' => $departments];
/* (3) If @id_dep -> Only add elements that are @id_dep */
$filtered = [];
foreach($departments as $dep){
if( $dep['idDep'] == $id_dep ){
$filtered[] = $dep;
break;
}
}
/* (4) Return filtered departments */
return ['departments' => $filtered];
}
public function put($args){
$department = 0;
extract($args);
/** @var meta $meta_repo */
$meta_repo = Repo::getRepo('meta');
$deps = $meta_repo->get_prof_departments($_SESSION['CAS']['login']);
if( count($deps) > 0 ){
foreach($deps as $dep){
if( $dep['idDep'] == $department ){
$_SESSION['AvailableDepartments'] = $deps;
$_SESSION['CurrentDepartmentId'] = $dep['idDep'];
$_SESSION['VERSION'] = [
'list' => $dep['versions'],
'current' => null
];
// select version with default = 1
foreach($_SESSION['VERSION']['list'] as $v){
if( $v['default'] == 1 ){
$_SESSION['VERSION']['current'] = intval($v['iddatabase']);
$_SESSION['CurrentDatabase'] = $v['dbName'];
break;
}
}
// if no default -> select first
if( !is_int($_SESSION['VERSION']) ){
$_SESSION['VERSION']['current'] = intval($_SESSION['VERSION']['list'][0]['iddatabase']);
$_SESSION['CurrentDatabase'] = $_SESSION['VERSION']['list'][0]['dbName'];
}
return ['switched' => true];
}
}
}
return ['switched' => false];
}
public function post($args){
$name = null;
extract($args);
/** @var meta $metaRepo */
$metaRepo = Repo::getRepo("meta");
/** @var professor $profRep */
$profRep = Repo::getRepo("professor");
/** @var database $dbRepo */
$dbRepo = Repo::getRepo("database");
//create the department in the meta database
$depId = $metaRepo->createDepartment($name);
//link the current user to that department
$metaRepo->link($_SESSION['CAS']['login'],$depId);
//create the database and init the structure
$dbName = $dbRepo->init($depId);
//link the new database to the department
$metaRepo->createVersion("Version 1",$dbName,$depId,true);
//get the current user data from current department
$user = $profRep->get($_SESSION['CAS']['id'])[0];
//switch our connexion to that database
Repo::switchDatabase($dbName);
//create the default admin in the new database (categories are common to all department)
$profRep->create($user["lastName"],
$user["firstName"],
$user["Categorie_idCategorie"],
$user["hoursToDo"],
$user["abreviation"],
true,
$user["casLogin"]);
//update user session
$departments = $metaRepo->get_prof_departments($user["casLogin"]);
$_SESSION['AvailableDepartments'] = $departments;
//we are good now
return [];
}
}

View File

@ -0,0 +1,444 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 19/02/18
* Time: 21:31
*/
namespace api\module;
use database\core\Repo;
use database\core\Repo_i;
use database\repo\category;
use database\repo\cours;
use database\repo\professor;
use database\repo\td;
use database\repo\tp;
use database\repo\ue;
use error\core\Err;
use error\core\Error;
use PhpOffice\PhpSpreadsheet\Exception;
class excelController
{
private const startLineUE = 5;
private const startLineProf = 10;
public function post($args){
if(isset($_FILES["file"]["tmp_name"])){
//put everything in a try so we catch all PhpExcel exceptions and return a clean API Response
try{
$reader = new \PhpOffice\PhpSpreadsheet\Reader\Xls();
$reader->setReadDataOnly(true);
$spreadsheet = $reader->load($_FILES["file"]["tmp_name"]);
$spreadsheet->setActiveSheetIndex(0);
$UESpreadsheet = $spreadsheet->getActiveSheet();
/*
* Setting Up state variables
*/
//current formation
$formation = "";
//current UE code
$UECode = "";
//current UE
$UE = [];
//array containing all the UEs
$allUE = [];
//array containing all the formations
$allFormations = [];
//can the current UE have a default formation
$isDefaultFormationPossible = false;
/*
* declare the lambda that will add finalized UE to the array
*/
$addEU = function() use (&$UECode,&$allUE,&$UE){
//determine if UE is disabled (if cours+td+tp = 0)
$totalVH = 0;
if(is_array($UE["groups"]) && count($UE["groups"]) > 0){
foreach ($UE["groups"] as $groups){
foreach ($groups as $group){
$totalVH += $group["VH"];
}
}
}
$UE["disabled"] = $totalVH == 0;
if($UECode != ""){
if(isset($allUE[$UECode])){
$counter = 1;
while(isset($allUE[$UECode.$counter])) $counter++;
$allUE[$UECode.$counter] = $UE;
}else{
$allUE[$UECode] = $UE;
}
$UE = [];
}
};
/*
* declaring the lambda tha twill extract the list of formation involved in the group
*/
$getFormations = function(?string $group) use (&$formation,&$allFormations) : array{
$group = trim($group);
if($group == ""){
if(!isset($allFormations[$formation])){
$allFormations[$formation] = [
"name" => $formation,
"internal" => strpos($formation,"Info") !== false ? true : false
];
}
return [$formation];
}
//replace the generic "INFO" keyword by the actual formation
$group = str_replace("INFO",$formation,$group);
//split the string
$groups = explode("+",$group);
//trim the strings
$groups = array_map('trim', $groups);
//delete empty strings
$groups = array_filter($groups);
foreach ($groups as $group){
if(!isset($allFormations[$group])){
$allFormations[$group] = [
"name" => $group,
"internal" => strpos(strtolower($group),"info") !== false ? true : false
];
}
}
return $groups;
};
/*
* declaring the lambda that will compute the part of internal students in the course (used for stats purpose)
*/
$getInternalStudentPart = function(?string $group) use (&$formation, $getFormations) : float{
if(!$group) return 1.0;
$groups = $getFormations($group);
if(!in_array($formation,$groups)){
return 0.0;
}else{
return 1/count($groups);
}
};
$exitWithNullException = function(){
exit(json_encode(["error" => true, "message" => "NullCellException"]));
};
//starting the iteration
foreach($UESpreadsheet->getRowIterator() as $row){
//skip the first rows
if($row->getRowIndex() < self::startLineUE) continue;
$firstCellValue = ($UESpreadsheet->getCellByColumnAndRow(1,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
$secondCellValue = ($UESpreadsheet->getCellByColumnAndRow(2,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
//if the first value is not null and the second is, this means we change formation and rest the UUCode
if($secondCellValue == "" and $firstCellValue != "") {$formation = $firstCellValue; $addEU(); $UECode = ""; continue; }
//if no UE is set yet, find it
if($UECode == "" and $firstCellValue != "") $UECode = $firstCellValue;
//if the line is empty this means we change UE
if($firstCellValue == "" and $secondCellValue == "") {$addEU(); $UECode = ""; continue;}
//now we have a formation, a UE and we are sure the line is not empty, let's fill up this bad boy
//if the required field is not set this means we are at the header of the UE
if(!isset($UE["required"])){
$UE["name"] = ($UESpreadsheet->getCellByColumnAndRow(2,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue();
$UE["required"] = ($UESpreadsheet->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
$UE["TotalVH"] = ($UESpreadsheet->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue();
$UE["CourseVH"] = ($UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0.0;
$UE["CourseGroup"] = ($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0;
$UE["TdVH"] = ($UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0.0;
$UE["TdGroup"] = ($UESpreadsheet->getCellByColumnAndRow(9,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0;
$UE["TpVH"] = ($UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0.0;
$UE["TpGroup"] = ($UESpreadsheet->getCellByColumnAndRow(12,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0;
$UE["defaultFormation"] = null;
$isDefaultFormationPossible = true;
continue;
}
//we have a new group! if the array is not set, initialize it
if(!isset($UE["groups"])) $UE["groups"] = [
"Course" => [],
"TD" => [],
"TP" => []
];
//compute Course
if (is_numeric(($UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue())){
$group = [
"VH" => ($UESpreadsheet->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart(($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"formations" => $getFormations(($UESpreadsheet->getCellByColumnAndRow(6,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"professor" => ($UESpreadsheet->getCellByColumnAndRow(7,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: null
];
if(count($group["formations"]) == 1 and $isDefaultFormationPossible and ($UE["defaultFormation"] == null or $UE["defaultFormation"] == $group["formations"][0])){
$UE["defaultFormation"] = $group["formations"][0];
}else{
$UE["defaultFormation"] = null;
$isDefaultFormationPossible = false;
}
$UE["groups"]["Course"][] = $group;
}
//compute TDs
if(is_numeric(($UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue())){
$group = [
"VH" => ($UESpreadsheet->getCellByColumnAndRow(8,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart(($UESpreadsheet->getCellByColumnAndRow(9,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"formations" => $getFormations(($UESpreadsheet->getCellByColumnAndRow(9,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"professor" => ($UESpreadsheet->getCellByColumnAndRow(10,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: null
];
if(count($group["formations"]) == 1 and $isDefaultFormationPossible and ($UE["defaultFormation"] == null or $UE["defaultFormation"] == $group["formations"][0])){
$UE["defaultFormation"] = $group["formations"][0];
}else{
$UE["defaultFormation"] = null;
$isDefaultFormationPossible = false;
}
$UE["groups"]["TD"][] = $group;
}
//compute TPs
if(is_numeric(($UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue())){
$group = [
"VH" => ($UESpreadsheet->getCellByColumnAndRow(11,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue(),
"internalStudentPart" => $getInternalStudentPart(($UESpreadsheet->getCellByColumnAndRow(12,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"formations" => $getFormations(($UESpreadsheet->getCellByColumnAndRow(12,$row->getRowIndex()) ?? $exitWithNullException())->getCalculatedValue()),
"professor" => ($UESpreadsheet->getCellByColumnAndRow(13,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: null
];
if(count($group["formations"]) == 1 and $isDefaultFormationPossible and ($UE["defaultFormation"] == null or $UE["defaultFormation"] == $group["formations"][0])){
$UE["defaultFormation"] = $group["formations"][0];
}else{
$UE["defaultFormation"] = null;
$isDefaultFormationPossible = false;
}
$UE["groups"]["TP"][] = $group;
}
}
/*
* Now we compute the professor list to get the full name , the number of hour he must do and the category he is in
*/
$spreadsheet->setActiveSheetIndex(1);
$ProfSpreadshit = $spreadsheet->getActiveSheet();
//array containing all the professors
$allProf = [];
//current professor category
$currentCategory = "";
//category as represented in the excel (as a number)
$currentCategoryIndex = 0;
foreach($ProfSpreadshit->getRowIterator() as $row){
//skip the first lines
if($row->getRowIndex() < self::startLineProf) continue;
$firstCellValue = ($ProfSpreadshit->getCellByColumnAndRow(2,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
$secondCellValue = ($ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue();
//skip empty lines
if(!$firstCellValue and !$secondCellValue) continue;
//if the first cell contains something and not the second, it means that we change category
if($firstCellValue && !$secondCellValue){
$currentCategory = $firstCellValue;
$currentCategoryIndex++;
}
//if the line is valid
if(($ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue() and ($ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getValue()){
$allProf[($ProfSpreadshit->getCellByColumnAndRow(3,$row->getRowIndex()) ?? $exitWithNullException())->getValue()] = [
"categoryLabel" => $currentCategory,
"categoryIndex" => $currentCategoryIndex,
"lastName" => explode(" ",($ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getValue(),2)[1],
"firstName" => explode(" ",($ProfSpreadshit->getCellByColumnAndRow(4,$row->getRowIndex()) ?? $exitWithNullException())->getValue(),2)[0],
"hoursToDo" => ($ProfSpreadshit->getCellByColumnAndRow(5,$row->getRowIndex()) ?? $exitWithNullException())->getValue() ?: 0
];
}
}
/*
* adding data to the database
*/
//professors
/** @var professor $profRepo */
$profRepo = Repo::getRepo("professor");
/** @var category $catRepo */
$catRepo = Repo::getRepo("category");
foreach ($allProf as $initials => &$prof){
//create or update the professor category
$catRepo->create($prof["categoryIndex"], $prof["categoryLabel"]);
//create the professor, as some names are missing, we replace them by something else
if(!$prof["lastName"]) $prof["lastName"] = "missingLastName";
if(!$prof["firstName"]) $prof["firstName"] = "missingFirstName";
$prof["dbId"] = $profRepo->exists($prof["lastName"], $prof["firstName"]);
if(!$prof["dbId"]){
$prof["dbId"] = $profRepo->create( $prof["lastName"], $prof["firstName"], $prof["categoryIndex"], $prof["hoursToDo"], $initials);
}
}
//formation and retreive the databse IDs
/** @var \database\repo\formation $formRepo */
$formRepo = Repo::getRepo("formation");
foreach ($allFormations as &$form){
$form["dbId"] = $formRepo->exists( $form["name"]);
if(!$form["dbId"]){
$form["dbId"] = $formRepo->create( $form["name"], $form["internal"]);
}
}
//UEs and corresponding groups
/** @var ue $ueRepo */
$ueRepo = Repo::getRepo("ue");
/** @var cours $coursRepo */
$coursRepo = Repo::getRepo("cours");
/** @var td $tdRepo */
$tdRepo = Repo::getRepo("td");
/** @var tp $tpRepo */
$tpRepo = Repo::getRepo("tp");
$CoursToLink = [];
$TDToLink = [];
$TPToLink = [];
foreach ($allUE as $codeUE => $UE){
if($UE["defaultFormation"]){
$UE["defaultFormationId"] = $allFormations[$UE["defaultFormation"]]["dbId"];
}else{
$UE["defaultFormationId"] = null;
}
$ueRepo->create($codeUE,
$UE["name"],
$UE["required"] == "OBL",
$UE["CourseVH"],
$UE["TdVH"],
$UE["TpVH"],
$UE["disabled"],
$UE["defaultFormationId"]
);
if(isset($UE["groups"])){
foreach ($UE["groups"] as $type => $groups){
foreach ($groups as $group){
$formations = [];
foreach ($group["formations"] as $format){
if(isset($allFormations[$format]["dbId"])){
$formations[] = $allFormations[$format]["dbId"];
}
}
switch ($type){
case "Course":
$CoursToLink[] = ["id" => $coursRepo->create( $codeUE,
$allProf[$group["professor"]]["dbId"],
$UE["disabled"] ? $UE["CourseVH"] : $group["VH"],
[]),
"form" => $formations];
break;
case "TD":
$TDToLink[] = ["id" => $tdRepo->create($codeUE,
$allProf[$group["professor"]]["dbId"],
$UE["disabled"] ? $UE["TdVH"] : $group["VH"],
[]),
"form" => $formations];
break;
case "TP":
$TPToLink[] = ["id" => $tpRepo->create($codeUE,
$allProf[$group["professor"]]["dbId"],
$UE["disabled"] ? $UE["TpVH"] : $group["VH"],
[]),
"form" => $formations];
break;
}
}
}
}
}
Repo::enableStacking();
foreach ($CoursToLink as $cour){
foreach ($cour["form"] as $formation){
$coursRepo->linkFormation($formation,$cour["id"]);
}
}
foreach ($TDToLink as $cour){
foreach ($cour["form"] as $formation){
$tdRepo->linkFormation($formation,$cour["id"]);
}
}
foreach ($TPToLink as $cour){
foreach ($cour["form"] as $formation){
$tpRepo->linkFormation($formation,$cour["id"]);
}
}
Repo::flushStack();
//return [ 'data' => ["professors" => $allProf, "formations" => $allFormations, "UEs" => $allUE ] ];
return["data" => true];
}catch (Exception $e){
return [ 'error' => new Error(Err::UnknownError) ];
}
}else{
return [ 'error' => new Error(Err::UploadError) ];
}
}
}

View File

@ -0,0 +1,60 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 27/02/18
* Time: 17:31
*/
namespace api\module;
use database\core\Repo;
class formationController
{
public function get($args){
$form_id = null;
extract($args);
/** @var \database\repo\formation $repo */
$repo = Repo::getRepo("formation");
return ['formations' => $repo->get($form_id)];
}
public function post($args){
$label = null;
$isInternal = null;
extract($args);
/** @var \database\repo\formation $repo */
$repo = Repo::getRepo("formation");
return ['idFormation' => $repo->create($label,$isInternal)];
}
public function put($args){
$idFormation = null;
$label = null;
$isInternal = null;
extract($args);
/** @var \database\repo\formation $repo */
$repo = Repo::getRepo("formation");
return ['success' => $repo->update($idFormation,$label,$isInternal)];
}
public function delete($args){
$idFormation = null;
extract($args);
/** @var \database\repo\formation $repo */
$repo = Repo::getRepo("formation");
return ['success' => $repo->delete($idFormation)];
}
}

View File

@ -0,0 +1,142 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 27/02/18
* Time: 16:19
*/
namespace api\module\professor;
use database\core\Repo;
use database\repo\category;
use database\repo\formation;
use database\repo\ue;
use error\core\Error;
use error\core\Err;
class filterController{
/* (1) Get professor ID(s) matching a specific filter
*
* @categories<array> [OPT] Array of categories IDS
* @formations<array> [OPT] Array of formation IDS
* @ues<array> [OPT] Array of UE codes
*
* @return matches<array> Array of matching professor IDs
*
---------------------------------------------------------*/
public static function post($args){
$categories = [];
$formations = [];
$ues = [];
extract($args);
/* (1) If no filter -> return error
---------------------------------------------------------*/
/* (1) Pre-process conditions */
$no_category = !is_array($categories) || count($categories) < 1;
$no_ue = !is_array($ues) || count($ues) < 1;
$no_formation = !is_array($formations) || count($formations) < 1;
/* (2) Exit if no filter */
if( $no_category && $no_ue && $no_formation )
return ['error' => new Error(Err::MissingParam, 'You must give at least 1 parameter')];
/* (3) Init. result array (only keys used for unicity) */
$matches_uniq = [];
/* (2) Filter by categories
---------------------------------------------------------*/
if( is_array($categories) ){
/** @var category $cat_repo */
$cat_repo = Repo::getRepo('category');
/* (1) For each formation -> get request */
foreach($categories as $cat_id){
// 1. Ignore if wrong format
if( !is_numeric($cat_id) || !is_int($cat_id) )
continue;
// 2. Get from repo
$fetched_ids = $cat_repo->getProfessors( intval($cat_id) );
// 3. Add in unique set
foreach($fetched_ids as $prof_id)
$matches_uniq[ intval($prof_id['idProfesseur']) ] = null;
}
}
/* (3) Filter by formation
---------------------------------------------------------*/
if( is_array($formations) ){
/** @var formation $form_repo */
$form_repo = Repo::getRepo('formation');
/* (1) For each formation -> get request */
foreach($formations as $form_id){
// 1. Ignore if wrong format
if( !is_numeric($form_id) || !is_int($form_id) )
continue;
// 2. Get from repo
$fetched_ids = $form_repo->getProfessors( intval($form_id) );
// 3. Add in unique set
foreach($fetched_ids as $prof_id)
$matches_uniq[ intval($prof_id['idProfesseur']) ] = null;
}
}
/* (4) Filter by ue
---------------------------------------------------------*/
if( is_array($ues) ){
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) For each ue -> get request */
foreach($ues as $ue_code){
// 1. Ignore if wrong format
if( !is_string($ue_code) || strlen($ue_code) < 1 )
continue;
// 2. Get from repo
$fetched_ids = $ue_repo->getProfessors($ue_code);
// 3. Add in unique set
foreach($fetched_ids as $prof_id)
$matches_uniq[ intval($prof_id['idProfesseur']) ] = null;
}
}
return ['matches' => array_keys($matches_uniq)];
}
}

View File

@ -0,0 +1,437 @@
<?php
namespace api\module\professor;
use database\core\Repo;
use database\repo\prof;
use database\repo\cours;
use database\repo\td;
use database\repo\tp;
use database\repo\formation;
use error\core\Error;
use error\core\Err;
class pdfController{
/* (1) Get professor PDF fiche matching a specific ID
*
* @prof_id<array> Professor ID
*
* @return download<File> The PDF fiche
---------------------------------------------------------*/
public static function get($args){
$prof_id = -1;
extract($args);
if(!$_SESSION["CAS"]["admin"] && $_SESSION["CAS"]["id"] != $prof_id){
return [
'headers' => ["Content-Type" => "text/html"],
'body' => "Unauthorized access"
];
}
/* (0) Initialize
---------------------------------------------------------*/
/* (1) Initialize data structure */
$data = [
'prof' => [],
'cours' => [],
'td' => [],
'tp' => [],
'form' => []
];
/* (2) Get repositories */
/** @var professor $prof_repo */
$prof_repo = Repo::getRepo('professor');
/** @var formation $form_repo */
$form_repo = Repo::getRepo('formation');
/** @var cours $cours_repo */
$cours_repo = Repo::getRepo('cours');
/** @var td $td_repo */
$td_repo = Repo::getRepo('td');
/** @var tp $tp_repo */
$tp_repo = Repo::getRepo('tp');
/* (1) Get professor data
---------------------------------------------------------*/
/* (1) Request */
$fetched = $prof_repo->getWithVH($prof_id);
/* (2) Error */
if( count($fetched) < 1 )
return ['error' => new Error(Err::NoMatchFound)];
/* (3) Extract data */
$data['prof'] = $fetched[0];
/* (2) Get each Cours
---------------------------------------------------------*/
/* (1) Request */
$fetched = $cours_repo->getForProfessor($prof_id);
/* (2) Store data if no error */
if( !is_null($fetched) )
$data['cours'] = $fetched;
/* (3) For each Cours -> parse formation list */
foreach($data['cours'] as $kcours=>$cours)
$data['cours'][$kcours]['formations'] = json_decode($cours['formations']);
/* (3) get each TD
---------------------------------------------------------*/
/* (1) Request */
$fetched = $td_repo->getForProfessor($prof_id);
/* (2) Store data if no error */
if( !is_null($fetched) )
$data['td'] = $fetched;
/* (3) For each TD -> parse formation list */
foreach($data['td'] as $ktd=>$td)
$data['td'][$ktd]['formations'] = json_decode($td['formations']);
/* (4) get each TP
---------------------------------------------------------*/
/* (1) Request */
$fetched = $tp_repo->getForProfessor($prof_id);
/* (2) Store data if no error */
if( !is_null($fetched) )
$data['tp'] = $fetched;
/* (3) For each TP -> parse formation list */
foreach($data['tp'] as $ktp=>$tp)
$data['tp'][$ktp]['formations'] = json_decode($tp['formations']);
/* (5) Get formations (id => label)
---------------------------------------------------------*/
/* (1) Request */
$fetched = $form_repo->get(null);
/* (2) Error: no formation found */
if( !is_array($fetched) )
return ['error' => new Error(Err::RepoError)];
/* (3) Reference formations by key = idForm */
foreach($fetched as $form)
$data['form'][intval($form['idForm'])] = $form;
/* (6) Render PDF
---------------------------------------------------------*/
/* (1) Generate body */
$body = self::generate_pdf_body($data);
/* (2) Set headers */
$fullname = $data['prof']['firstName'].' '.$data['prof']['lastName'];
$date = date('d-m-Y');
$title = "Fiche enseignant - $fullname ($date)";
$headers = [
// 'Content-Description' => 'File Transfer',
'Content-Transfer-Encoding' => 'binary',
'Content-Disposition' => 'attachment; filename="'.$title.'"',
'Cache-Control' => 'public, must-revalidate, max-age=0',
'Pragma' => 'public',
'X-Generator' => 'mPDF',
'Expires' => 'Sat, 26 Jul 1997 05:00:00 GMT',
'Last-Modified' => gmdate('D, d M Y H:i:s').' GMT',
'Content-Type' => 'application/pdf'
];
/* (3) Generate download */
return [
'headers' => $headers,
'body' => $body
];
}
private static function generate_pdf_body($data){
/* (1) Format data
---------------------------------------------------------*/
/* (1) Get fullname */
$fullname = $data['prof']['firstName'].' '.$data['prof']['lastName'];
/* (2) Get formatted date */
$date = date('d-m-Y');
/* (3) Total horaire */
$total_h = floatval($data['prof']['VHCours'])
+ floatval($data['prof']['VHTd'])
+ floatval($data['prof']['VHTp']);
$equiTD = floatval($data['prof']['equiTD']);
/* (4) Heures manquantes */
// TOTAL_H or equiTD ???
$missing_h = floatval($data['prof']['hoursToDo']) - $equiTD;
$missing_h = $missing_h < 0 ? 0 : $missing_h;
/* (5) Heures sup */
$sup_h = $equiTD > floatval($data['prof']['hoursToDo']) ? $equiTD - floatval($data['prof']['hoursToDo']) : 0;
/* (2) Initialize PDF
---------------------------------------------------------*/
/* (1) Get Font default directory */
$defaultConfig = (new \Mpdf\Config\ConfigVariables())->getDefaults();
$fontDirs = $defaultConfig['fontDir'];
/* (2) Get Font data */
$defaultFontConfig = (new \Mpdf\Config\FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
/* (3) Create PDF file */
$pdf = new \Mpdf\Mpdf([
'mode' => 'utf-8',
'defaultCssFile' => __PUBLIC__.'/css/pdf.css',
'tempDir' => __ROOT__.'/tmp',
'fontDir' => array_merge($fontDirs, [ __PUBLIC__.'/font/' ]),
'fontdata' => $fontData + [
'Fira Sans' => [
'R' => 'FiraSans-Regular.ttf'
]
],
'default_font' => 'Fira Sans'
]);
/* (4) Set PDF title */
$pdf->SetTitle("Fiche enseignant - $fullname ($date)");
/* (5) Store SVG */
$svg_warning = '<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" height="10" width="10" viewBox="0 0 1792 1792">
<path d="m 1024,1375 v -190 q 0,-14 -9.5,-23.5 Q 1005,1152 992,1152 H 800 q -13,0 -22.5,9.5 -9.5,9.5 -9.5,23.5 v 190 q 0,14 9.5,23.5 9.5,9.5 22.5,9.5 h 192 q 13,0 22.5,-9.5 9.5,-9.5 9.5,-23.5 z m -2,-374 18,-459 q 0,-12 -10,-19 -13,-11 -24,-11 H 786 q -11,0 -24,11 -10,7 -10,21 l 17,457 q 0,10 10,16.5 10,6.5 24,6.5 h 185 q 14,0 23.5,-6.5 9.5,-6.5 10.5,-16.5 z m -14,-934 768,1408 q 35,63 -2,126 -17,29 -46.5,46 -29.5,17 -63.5,17 H 128 Q 94,1664 64.5,1647 35,1630 18,1601 -19,1538 16,1475 L 784,67 q 17,-31 47,-49 30,-18 65,-18 35,0 65,18 30,18 47,49 z" style="fill: #ea4b35" />
</svg>';
/* (3) Set Header|Footer
---------------------------------------------------------*/
/* (1) Set Header content (Left, Right) */
$header_content = [
'C' => [ 'color' => '#aaa', 'content' => "Fiche enseignant $fullname" ],
'line' => 1
];
/* (2) Apply Header */
$pdf->setHeader([
'odd' => $header_content,
'even' => $header_content
]);
/* (1) Set Footer content (Left, Right) */
$footer_content = [
'L' => [ 'color' => '#aaa', 'content' => "Généré le $date" ],
'R' => [ 'color' => '#aaa', 'content' => 'Page {PAGENO} sur {nbpg}' ],
'line' => 1
];
/* (2) Apply Footer */
$pdf->setFooter([
'odd' => $footer_content,
'even' => $footer_content
]);
/* (4) Page 1 - Récapitulatif
---------------------------------------------------------*/
/* (1) Initialize page */
$pdf->AddPage();
/* (2) Write content */
$pdf->WriteHTML('<br>
<h3>1. Récapitulatif</h3>
<hr>
<article>
<p>
La liste des informations récapitulative est basée sur les données de tous les enseignants enregistrés à ce jour.
</p>
<blockquote>
Il est à noter qu\'elle contient les données générées au '.$date.'. Elle peut ne plus être à jour.
</blockquote>
<br><br><br>
<table>
<thead>
<tr>
<td class="color ac">Donnée</td>
<td class="color ac">Valeur</td>
</tr>
</thead>
<tbody>
<tr>
<td class="ar">Heures à faire</td>
<td>'.$data['prof']['hoursToDo'].' h</td>
</tr>
<tr>
<td class="ar">Equivalents TD</td>
<td>'.$data['prof']['equiTD'].' h</td>
</tr>
<tr>
<td class="ar">Heures programmées</td>
<td>'.$total_h.' h</td>
</tr>
<tr>
<td class="ar">Sous service</td>
<td>'.( $missing_h>0 ? "$svg_warning $missing_h" : $missing_h).' h</td>
</tr>
<tr>
<td class="ar">Sur service</td>
<td>'.$sup_h.' h</td>
</tr>
</tbody>
</table>
</article>
');
/* (5) Page 2 - Enseignements
---------------------------------------------------------*/
/* (1) Initialize page */
$pdf->AddPage();
/* (2) Write content */
$pdf->WriteHTML('<br>
<h3>2. Enseignements</h3>
<hr>
<article>
<p>
La liste des enseignements générée dans le tableau ci-dessous est uniquement à titre informatif et n\'est pas contractuelle.
</p>
<blockquote>
Il est à noter qu\'elle contient les données générées au '.$date.'. Elle peut ne plus être à jour.
</blockquote>
<br><br><br>
<table>
<thead>
<tr>
<th colspan="5" class="ac">Liste des enseignements programmés</th>
</tr>
<tr>
<td class="color ac">Code UE</td>
<td class="color ac">Nom UE</td>
<td class="color ac">Prestation</td>
<td class="color ac">volume horaire</td>
<td class="color ac">formations</td>
</tr>
</thead>
<tbody>');
/* (3) List Cours */
foreach($data['cours'] as $kc=>$c){
$pdf->WriteHTML('<tr>
<td>'.$c['code'].'</td>
<td>'.$c['label'].'</td>
<td>Cours</td>
<td>'.$c['volume'].' heures</td>
<td><ul>');
// print formations
foreach($c['formations'] as $f)
if( isset($data['form'][$f]) )
$pdf->WriteHTML('<li>'.$data['form'][$f]['labelForm'].'</li>');
$pdf->WriteHTML('</ul></td></tr>');
}
/* (4) List TD */
foreach($data['td'] as $kc=>$c){
$pdf->WriteHTML('<tr>
<td>'.$c['code'].'</td>
<td>'.$c['label'].'</td>
<td>TD</td>
<td>'.$c['volume'].' heures</td>
<td><ul>');
// print formations
foreach($c['formations'] as $f)
if( isset($data['form'][$f]) )
$pdf->WriteHTML('<li>'.$data['form'][$f]['labelForm'].'</li>');
$pdf->WriteHTML('</ul></td></tr>');
}
/* (5) List TP */
foreach($data['tp'] as $kc=>$c){
$pdf->WriteHTML('<tr>
<td>'.$c['code'].'</td>
<td>'.$c['label'].'</td>
<td>TP</td>
<td>'.$c['volume'].' heures</td>
<td><ul>');
// print formations
foreach($c['formations'] as $f)
if( isset($data['form'][$f]) )
$pdf->WriteHTML('<li>'.$data['form'][$f]['labelForm'].'</li>');
$pdf->WriteHTML('</ul></td></tr>');
}
/* (6) End HTML */
$pdf->WriteHTML('</tr>
</tbody>
</table>
</article>');
/* (N) Print out PDF file
---------------------------------------------------------*/
return $pdf->Output("Fiche enseignant - $fullname ($date)", 'S');
}
}

View File

@ -0,0 +1,240 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 27/02/18
* Time: 16:19
*/
namespace api\module;
use database\core\Repo;
use database\repo\professor;
use error\core\Error;
use error\core\Err;
class professorController{
/* (1) Returns 1 or all professors
*
* @prof_id<int> [OPT] The professor UID
*
* @return professors<array> The professor(s) data
*
---------------------------------------------------------*/
public static function get($args){
$prof_id = null;
$with_vh = 0;
extract($args);
/* Get the professor repo */
/** @var professor $prof_repo */
$prof_repo = Repo::getRepo('professor');
/* (1) If with VH data
---------------------------------------------------------*/
if( is_int($with_vh) && $with_vh === 1 ){
/* (1) Get All professors or 1 by its id (if set) */
$fetched = $prof_repo->getWithVH($prof_id);
/* (2) Return data */
return ['professors' => $fetched];
}
/* (2) If without VH data (only Professor.*)
---------------------------------------------------------*/
/* (1) Get All professors or 1 by its id (if set) */
$fetched = $prof_repo->get($prof_id);
/* (3) Return data */
return ['professors' => $fetched];
}
/* (2) Creates a new professor
*
* @lastName<String> The professor's lastName
* @firstName<String> The professor's firstName
* @category<int> The professor's category ID
* @hoursToDo<int> The professor's number of hours to do
* @initials<int> The professor's initials
* @isAdmin<bool> Whether the professor is an admin
* @casLogin<String> The professor's CAS username
*
* @return prof_id<int> The created professor UID (if no error)
*
---------------------------------------------------------*/
public static function post($args){
$lastName = "";
$firstName = "";
$category = 0;
$hoursToDo = 0;
$initials = "";
$isAdmin = false;
$casLogin = null;
extract($args);
/* Get the professor repo */
/** @var professor $prof_repo */
$prof_repo = Repo::getRepo('professor');
/* (1) Check for unique field to be unique
---------------------------------------------------------*/
/* (1) Check @firstName + @lastName */
$exists = $prof_repo->exists($lastName, $firstName, $casLogin);
/* (2) If found -> already exists */
if( !is_null($exists) )
return ['error' => new Error(Err::AlreadyExists)];
/* (3) if @casLogin -> check unique */
if( !is_null($casLogin) ){
/* (1) Check if @casLogin already exists */
$exists = $prof_repo->getByLogin($casLogin);
/* (2) If found -> already exists */
if( !is_null($exists) )
return ['error' => new Error(Err::AlreadyExists)];
}
/* (3) Else try to create */
$repo_rtn = $prof_repo->create(
$lastName,
$firstName,
$category,
$hoursToDo,
$initials,
$isAdmin,
is_null($casLogin) ? "" : $casLogin
);
/* (4) If repo error -> return it */
if( is_null($repo_rtn) )
return ['error' => new Error(Err::RepoError)];
/* (5) Else return UID */
return ['created_uid' => $repo_rtn];
}
/* (3) Deletes an existing professor
*
* @prof_id<int> The professor UID
*
* @return deleted<bool> Whether it has been removed
*
---------------------------------------------------------*/
public static function delete($args){
$prof_id = 0;
extract($args);
/* Get the professor repo */
/** @var professor $prof_repo */
$prof_repo = Repo::getRepo('professor');
/* (1) Try to delete */
return ['deleted' => $prof_repo->delete($prof_id)];
}
/* (4) Edits an existing professor
*
* @prof_id<int> The professor UID
* @lastName<String> [OPT] The professor's lastName
* @firstName<String> [OPT] The professor's firstName
* @category<int> [OPT] The professor's category ID
* @hoursToDo<int> [OPT] The professor's number of hours to do
* @initials<int> [OPT] The professor's initials
* @isAdmin<bool> [OPT] Whether the professor is an admin
* @casLogin<String> [OPT] The professor's CAS username
* @remCas<bool> [OPT] Whether to remove the CAS login (only works if @casLogin is NULL)
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public static function put($args){
$prof_id = 0;
$lastName = null;
$firstName = null;
$category = null;
$hoursToDo = null;
$initials = null;
$isAdmin = null;
$casLogin = null;
$remCas = true;
extract($args);
/* Get the professor repo */
/** @var professor $prof_repo */
$prof_repo = Repo::getRepo('professor');
/* (1) If @casLogin -> check unique
---------------------------------------------------------*/
if( !is_null($casLogin) ){
/* (1) Check if @casLogin already exists */
$exists_cas = $prof_repo->getByLogin($casLogin);
/* (2) If found -> already exists */
if( !is_null($exists_cas) )
return ['error' => new Error(Err::AlreadyExists)];
}
/* (2) If @lastName or @firstName -> check unique
---------------------------------------------------------*/
if( !is_null($firstName) || !is_null($lastName) ){
/* (1) Try to fetch @prof_id data */
$fetched = $prof_repo->get($prof_id);
/* (2) Error if cannot find */
if( count($fetched) < 1 )
return ['error' => new Error(Err::NoMatchFound)];
/* (3) Extract @firstName + @lastName */
$names = [
'lastName' => is_null($lastName) ? $fetched[0]['lastName'] : $lastName,
'firstName' => is_null($firstName) ? $fetched[0]['firstName'] : $firstName
];
/* (4) Check if exists */
$exists = $prof_repo->exists($names['lastName'], $names['firstName']);
/* (2) If found -> already exists */
if( !is_null($exists) )
return ['error' => new Error(Err::AlreadyExists)];
}
/* (3) Try to update */
return ['updated' => $prof_repo->update(
$prof_id,
$lastName,
$firstName,
$category,
$hoursToDo,
$initials,
$isAdmin,
$remCas === true && is_null($casLogin) ? '' : $casLogin
)];
}
}

View File

@ -6,7 +6,7 @@
use \error\core\Err;
class release{
class releaseController{
/* Releases a project
*
@ -15,6 +15,8 @@
*
*/
public function get($args){
$project = "";
$step = null;
extract($args);
/* (1) Load projects' configuration

View File

@ -5,12 +5,12 @@
use \error\core\Error;
class root{
class rootController{
/* Generates the API documentation
*
*/
public function get($args){
public function post($args){
extract($args);
return [ 'args' => $args ];

View File

@ -0,0 +1,191 @@
<?php
namespace api\module\ue;
use database\core\Repo;
use database\repo\cours;
use error\core\Error;
use error\core\Err;
class coursController{
/* (1) Create a new Cours
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
*
---------------------------------------------------------*/
public static function post($args){
$code = "";
$idProf = null;
$volume = 0;
$formations = [];
extract($args);
/* Get the repos */
/** @var cours $cours_repo */
$cours_repo = Repo::getRepo('cours');
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) Fetch default formation from UE
---------------------------------------------------------*/
/* (1) Try to fetch the cours' UE */
$fetched_ue = $ue_repo->get($code);
/* (2) Manage error */
if( !is_array($fetched_ue) || count($fetched_ue) < 1 )
return ['error' => new Error(Err::RepoError)];
$defaultForm = intval($fetched_ue[0]['idForm']);
/* (3) Add to formation list if got a valid default formation */
if( is_int($defaultForm) && $defaultForm >= 0 && !in_array($defaultForm, $formations) )
$formations[] = $defaultForm;
/* (2) Create the cours
---------------------------------------------------------*/
/* (1) Try to create cours */
$created_id = $cours_repo->create($code, $idProf, $volume, $formations);
/* (2) Manage error */
if( is_null($created_id) || !is_int($created_id) )
return ['error' => new Error(Err::RepoError)];
return ['created_id' => $created_id, 'formations' => $formations];
}
/* (2) Get groups for a specific UE
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
*
---------------------------------------------------------*/
public static function get($args){
$code = "";
extract($args);
/* Get the cours repo */
/** @var cours $cours_repo */
$cours_repo = Repo::getRepo('cours');
/* (1) Try to fetch data */
$fetched = $cours_repo->getGroups($code);
/* (2) Manage error */
if( is_null($fetched) || !is_array($fetched) )
return ['error' => new Error(Err::RepoError)];
/* (3) Parse JSON list */
foreach($fetched as $f=>$v)
$fetched[$f]['formations'] = json_decode($v['formations']);
return ['groups' => $fetched];
}
/* (3) Updates an existing Cours
*
* @idCours<int> Id of the Cours to update
* @idProf<int> [OPT] The new professor ID (-1 to unset)
* @volume<int> [OPT] The new number of hours for the Cours
* @add_form<array> List of ids of formations to add
* @rem_form<array> List of ids of formations to remove
*
* @return updated<bool> Whether the Cours have been updated
*
---------------------------------------------------------*/
public static function put($args){
$idCours = -1;
$idProf = null;
$volume = null;
$add_form = [];
$rem_form = [];
extract($args);
/* Get the cours repo */
/** @var cours $cours_repo */
$cours_repo = Repo::getRepo('cours');
/* (1) If nothing to do -> error */
if( is_null($idProf) && is_null($volume) && count($add_form) + count($rem_form) == 0)
return ['error' => new Error(Err::MissingParam)];
/* (2) If have to update @idProf */
if( !is_null($idProf) ){
// call repo
$updated = $cours_repo->updateProf($idCours, $idProf < 0 ? NULL : $idProf );
// if error -> dispatch
if( !$updated )
return ['error' => new Error(Err::RepoError)];
}
/* (3) If have to update @volume */
if( !is_null($volume) ){
// call repo
$updated = $cours_repo->updateVolume($idCours, $volume);
// if error -> dispatch
if( !$updated )
return ['error' => new Error(Err::RepoError)];
}
/* (4) If have to add formations -> add them */
if( count($add_form) > 0 ){
foreach($add_form as $id_form)
$cours_repo->linkFormation($id_form, $idCours);
}
/* (5) If have to remove formations -> remove them */
if( count($rem_form) > 0 ){
foreach($rem_form as $id_form)
$cours_repo->unlinkFormation($id_form, $idCours);
}
return ['updated' => true];
}
/* (4) Deletes an existing Cours
*
* @idCours<int> Id of the Cours
*
* @return deleted<bool> Whether it has been deleted
*
---------------------------------------------------------*/
public static function delete($args){
$idCours = 0;
extract($args);
/* Get the cours repo */
/** @var cours $cours_repo */
$cours_repo = Repo::getRepo('cours');
/* (1) Dispatch response from repo */
return ['deleted' => $cours_repo->delete($idCours)];
}
}

View File

@ -0,0 +1,191 @@
<?php
namespace api\module\ue;
use database\core\Repo;
use database\repo\td;
use error\core\Error;
use error\core\Err;
class tdController{
/* (1) Create a new TD
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
*
---------------------------------------------------------*/
public static function post($args){
$code = "";
$idProf = null;
$volume = 0;
$formations = [];
extract($args);
/* Get the repos */
/** @var td $td_repo */
$td_repo = Repo::getRepo('td');
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) Fetch default formation from UE
---------------------------------------------------------*/
/* (1) Try to fetch the TD' UE */
$fetched_ue = $ue_repo->get($code);
/* (2) Manage error */
if( !is_array($fetched_ue) || count($fetched_ue) < 1 )
return ['error' => new Error(Err::RepoError)];
$defaultForm = intval($fetched_ue[0]['idForm']);
/* (3) Add to formation list if got a valid default formation */
if( is_int($defaultForm) && $defaultForm >= 0 && !in_array($defaultForm, $formations) )
$formations[] = $defaultForm;
/* (2) Create the TD
---------------------------------------------------------*/
/* (1) Try to create td */
$created_id = $td_repo->create($code, $idProf, $volume, $formations);
/* (2) Manage error */
if( is_null($created_id) || !is_int($created_id) )
return ['error' => new Error(Err::RepoError)];
return ['created_id' => $created_id, 'formations' => $formations];
}
/* (2) Get groups for a specific UE
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
*
---------------------------------------------------------*/
public static function get($args){
$code = "";
extract($args);
/* Get the td repo */
/** @var td $td_repo */
$td_repo = Repo::getRepo('td');
/* (1) Try to fetch data */
$fetched = $td_repo->getGroups($code);
/* (2) Manage error */
if( is_null($fetched) || !is_array($fetched) )
return ['error' => new Error(Err::RepoError)];
/* (3) Parse JSON list */
foreach($fetched as $f=>$v)
$fetched[$f]['formations'] = json_decode($v['formations']);
return ['groups' => $fetched];
}
/* (3) Updates an existing TD
*
* @idTD<int> Id of the TD to update
* @idProf<int> [OPT] The new professor ID (-1 to unset)
* @volume<int> [OPT] The new number of hours for the TD
* @add_form<array> List of ids of formations to add
* @rem_form<array> List of ids of formations to remove
*
* @return updated<bool> Whether the TD have been updated
*
---------------------------------------------------------*/
public static function put($args){
$idTD = -1;
$idProf = null;
$volume = null;
$add_form = [];
$rem_form = [];
extract($args);
/* Get the td repo */
/** @var td $td_repo */
$td_repo = Repo::getRepo('td');
/* (1) If nothing to do -> error */
if( is_null($idProf) && is_null($volume) && count($add_form) + count($rem_form) == 0)
return ['error' => new Error(Err::MissingParam)];
/* (2) If have to update @idProf */
if( !is_null($idProf) ){
// call repo
$updated = $td_repo->updateProf($idTD, $idProf < 0 ? NULL : $idProf );
// if error -> dispatch
if( !$updated )
return ['error' => new Error(Err::RepoError)];
}
/* (3) If have to update @volume */
if( !is_null($volume) ){
// call repo
$updated = $td_repo->updateVolume($idTD, $volume);
// if error -> dispatch
if( !$updated )
return ['error' => new Error(Err::RepoError)];
}
/* (4) If have to add formations -> add them */
if( count($add_form) > 0 ){
foreach($add_form as $id_form)
$td_repo->linkFormation($id_form, $idTD);
}
/* (5) If have to remove formations -> remove them */
if( count($rem_form) > 0 ){
foreach($rem_form as $id_form)
$td_repo->unlinkFormation($id_form, $idTD);
}
return ['updated' => true];
}
/* (4) Deletes an existing TD
*
* @idTD<int> Id of the TD
*
* @return deleted<bool> Whether it has been deleted
*
---------------------------------------------------------*/
public static function delete($args){
$idTD = 0;
extract($args);
/* Get the td repo */
/** @var td $td_repo */
$td_repo = Repo::getRepo('td');
/* (1) Dispatch response from repo */
return ['deleted' => $td_repo->delete($idTD)];
}
}

View File

@ -0,0 +1,191 @@
<?php
namespace api\module\ue;
use database\core\Repo;
use database\repo\tp;
use error\core\Error;
use error\core\Err;
class tpController{
/* (1) Create a new TP
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
*
---------------------------------------------------------*/
public static function post($args){
$code = "";
$idProf = null;
$volume = 0;
$formations = [];
extract($args);
/* Get the repos */
/** @var tp $tp_repo */
$tp_repo = Repo::getRepo('tp');
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) Fetch default formation from UE
---------------------------------------------------------*/
/* (1) Try to fetch the TP' UE */
$fetched_ue = $ue_repo->get($code);
/* (2) Manage error */
if( !is_array($fetched_ue) || count($fetched_ue) < 1 )
return ['error' => new Error(Err::RepoError)];
$defaultForm = intval($fetched_ue[0]['idForm']);
/* (3) Add to formation list if got a valid default formation */
if( is_int($defaultForm) && $defaultForm >= 0 && !in_array($defaultForm, $formations) )
$formations[] = $defaultForm;
/* (2) Create the TP
---------------------------------------------------------*/
/* (1) Try to create tp */
$created_id = $tp_repo->create($code, $idProf, $volume, $formations);
/* (2) Manage error */
if( is_null($created_id) || !is_int($created_id) )
return ['error' => new Error(Err::RepoError)];
return ['created_id' => $created_id, 'formations' => $formations];
}
/* (2) Get groups for a specific UE
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
*
---------------------------------------------------------*/
public static function get($args){
$code = "";
extract($args);
/* Get the tp repo */
/** @var tp $tp_repo */
$tp_repo = Repo::getRepo('tp');
/* (1) Try to fetch data */
$fetched = $tp_repo->getGroups($code);
/* (2) Manage error */
if( is_null($fetched) || !is_array($fetched) )
return ['error' => new Error(Err::RepoError)];
/* (3) Parse JSON list */
foreach($fetched as $f=>$v)
$fetched[$f]['formations'] = json_decode($v['formations']);
return ['groups' => $fetched];
}
/* (3) Updates an existing TP
*
* @idTP<int> Id of the TP to update
* @idProf<int> [OPT] The new professor ID (-1 to unset)
* @volume<int> [OPT] The new number of hours for the TP
* @add_form<array> List of ids of formations to add
* @rem_form<array> List of ids of formations to remove
*
* @return updated<bool> Whether the TP have been updated
*
---------------------------------------------------------*/
public static function put($args){
$idTP = -1;
$idProf = null;
$volume = null;
$add_form = [];
$rem_form = [];
extract($args);
/* Get the tp repo */
/** @var tp $tp_repo */
$tp_repo = Repo::getRepo('tp');
/* (1) If nothing to do -> error */
if( is_null($idProf) && is_null($volume) && count($add_form) + count($rem_form) == 0)
return ['error' => new Error(Err::MissingParam)];
/* (2) If have to update @idProf */
if( !is_null($idProf) ){
// call repo
$updated = $tp_repo->updateProf($idTP, $idProf < 0 ? NULL : $idProf );
// if error -> dispatch
if( !$updated )
return ['error' => new Error(Err::RepoError)];
}
/* (3) If have to update @volume */
if( !is_null($volume) ){
// call repo
$updated = $tp_repo->updateVolume($idTP, $volume);
// if error -> dispatch
if( !$updated )
return ['error' => new Error(Err::RepoError)];
}
/* (4) If have to add formations -> add them */
if( count($add_form) > 0 ){
foreach($add_form as $id_form)
$tp_repo->linkFormation($id_form, $idTP);
}
/* (5) If have to remove formations -> remove them */
if( count($rem_form) > 0 ){
foreach($rem_form as $id_form)
$tp_repo->unlinkFormation($id_form, $idTP);
}
return ['updated' => true];
}
/* (4) Deletes an existing TP
*
* @idTP<int> Id of the TP
*
* @return deleted<bool> Whether it has been deleted
*
---------------------------------------------------------*/
public static function delete($args){
$idTP = 0;
extract($args);
/* Get the tp repo */
/** @var tp $tp_repo */
$tp_repo = Repo::getRepo('tp');
/* (1) Dispatch response from repo */
return ['deleted' => $tp_repo->delete($idTP)];
}
}

View File

@ -0,0 +1,196 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 27/02/18
* Time: 16:19
*/
namespace api\module;
use database\core\Repo;
use database\repo\ue;
use error\core\Error;
use error\core\Err;
class ueController{
/* (1) Returns 1 or all UEs
*
* @code<String> [OPT] The UE code
*
* @return ues<array> The UE(s) data
*
---------------------------------------------------------*/
public static function get($args){
$code = null;
extract($args);
/* Get the ue repo */
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) Get All ues or 1 by its code (if set) */
$fetched = $ue_repo->get($code);
/* (2) Parse 'formations' from json array */
foreach($fetched as $f=>$v)
$fetched[$f]['formations'] = \json_decode($v['formations']);
/* (3) Return data */
return ['ues' => $fetched];
}
/* (2) Creates a new UE
*
* @code<String> The code of the UE
* @label<String> The UE label (name)
* @required<bool> If the UE is required
* @volumeCours<float> The UE required volume of COURSES
* @volumeTD<float> The UE required volume of TD
* @volumeTP<float> The UE required volume of TP
* @disabled<bool> [OPT] If it is disabled
* @defaultFormation<int> [OPT] If there is a foreign key for a default formation (if only one formation)
*
* @return created_code<int> The created UE code (if no error)
*
---------------------------------------------------------*/
public static function post($args){
$code = "";
$label = "";
$required = false;
$volumeCours = 0;
$volumeTD = 0;
$volumeTP = 0;
$disabled = true;
$defaultFormation = -1;
extract($args);
/* Get the ue repo */
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) Check if ue code already exists */
$exists = $ue_repo->get($code);
/* (2) If found -> already exists */
if( count($exists) > 0 )
return ['error' => new Error(Err::AlreadyExists)];
/* (3) Else try to create */
$repo_rtn = $ue_repo->create(
$code,
$label,
$required,
$volumeCours,
$volumeTD,
$volumeTP,
$disabled,
is_int($defaultFormation) && $defaultFormation < 0 ? null : $defaultFormation
);
/* (4) If repo error -> return it */
if( is_null($repo_rtn) )
return ['error' => new Error(Err::RepoError)];
/* (5) Else return UID */
return ['created_code' => $repo_rtn];
}
/* (3) Deletes an existing UE
*
* @code<String> The UE code
*
* @return deleted<bool> Whether it has been removed
*
---------------------------------------------------------*/
public static function delete($args){
$code = '';
extract($args);
/* Get the ue repo */
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) Try to delete */
return ['deleted' => $ue_repo->delete($code)];
}
/* (4) Edits an existing UE
*
* @code<String> The code of the UE
* @new_code<String> [OPT] The new code of the UE
* @label<String> [OPT] The UE label (name)
* @required<bool> [OPT] If the UE is required
* @volumeCours<float> [OPT] The UE required volume of COURSES
* @volumeTD<float> [OPT] The UE required volume of TD
* @volumeTP<float> [OPT] The UE required volume of TP
* @disabled<bool> [OPT] If it is disabled
* @defaultFormation<int> [OPT] default formation for this UE (-1 to unset, NULL to ignore)
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public static function put($args){
$code = "";
$new_code = "";
$label = "";
$required = false;
$volumeCours = 0;
$volumeTD = 0;
$volumeTP = 0;
$disabled = true;
$defaultFormation = null;
extract($args);
/* Get the ue repo */
/** @var ue $ue_repo */
$ue_repo = Repo::getRepo('ue');
/* (1) Check for @new_code to be unique (not already used)
---------------------------------------------------------*/
if( !is_null($new_code) ){
/* (1) Check @new_code */
$exists = $ue_repo->get($new_code);
/* (2) If found -> already exists */
if( count($exists) > 0 )
return ['error' => new Error(Err::AlreadyExists)];
}
/* (2) Try to update
---------------------------------------------------------*/
return ['updated' => $ue_repo->update(
$code,
$new_code,
$label,
$required,
$volumeCours,
$volumeTD,
$volumeTP,
$disabled,
$defaultFormation
)];
}
}

View File

@ -11,6 +11,7 @@
**************************/
namespace database\core;
use database\core\PDOWrapper\PDOWrapper;
use \error\core\Error;
use \error\core\Err;
@ -18,7 +19,7 @@
class DatabaseDriver{
/* STATIC ATTRIBUTES */
private static function conf(){
private static function conf() : array{
// YOUR CONFIGURATION BEHIND
$path = __CONFIG__.'/database-driver.json';
@ -36,11 +37,10 @@
return $parsed;
}
private static $path; // Databases configurations files
private static $config; // PDO configurations
/** @var DatabaseDriver[] */
private static $instance = []; // Database driver instance list
/** @var Error */
public $error;
/* ATTRIBUTES */
@ -52,15 +52,16 @@
/* CONSTRUCTOR OF A DATABASE DRIVER
/** CONSTRUCTOR OF A DATABASE DRIVER
*
* @host<String> Database Server's host
* @dbname<String> Database name
* @username<String> Database username
* @password<String> Database password
* @param String $host Database Server's host
* @param String $dbname Database name
* @param String $username Database username
* @param String $password Database password
* @param bool $debug
*
*/
private function __construct($host, $dbname, $username, $password){
private function __construct(String $host, String $dbname, String $username, String $password, bool $debug = false){
/* (2) Stores configuration */
$this->host = $host;
$this->dbname = $dbname;
@ -69,15 +70,23 @@
try{
$this->pdo = new \PDO('mysql:host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password, [
$this->pdo = new PDOWrapper('mysql:host='.$this->host.';dbname='.$this->dbname.';charset=utf8', $this->username, $this->password, [
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,
\PDO::ATTR_TIMEOUT => 5
\PDO::ATTR_TIMEOUT => 5,
\PDO::ERRMODE_EXCEPTION => true
]);
$this->pdo->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, false);
$this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
if($debug){
$this->pdo->enableDebug();
}
// On signale que tout s'est bien passe
$this->error = new Error(Err::Success);
}catch(Exception $e){
}catch(\Exception $e){
// On signale qu'il y a une erreur
$this->error = new Error(Err::PDOConnection);
}
@ -89,22 +98,20 @@
**** Multiton Management (static) ****
************************************************/
/* ADDS A NEW CONNECTION
/** ADDS A NEW CONNECTION
*
* @label<String> [optional] Database Label
* @param String $label [optional] Database Label
*
* @return status<Boolean> If added successfully
* @return boolean If added successfully
*
*/
private static function add($label=null){
private static function add(String $label='default') : bool{
$conf = self::conf();
/* [1] Default values
=========================================================*/
/* (1) If label isn't given */
is_null($label) && ($label = 'default');
/* (2) If label and no path */
/* (1) If label and no path */
if( $label !== 'default' && !isset($conf[$label]) )
return false;
@ -115,12 +122,20 @@
/* (1) If local -> instanciates with local configuration */
// if( !checkdnsrr($_SERVER['SERVER_NAME'], 'NS') )
self::$instance[$label] = new DatabaseDriver($conf[$label]['local']['host'], $conf[$label]['local']['dbname'], $conf[$label]['local']['user'], $conf[$label]['local']['password']);
/* (2) If Remote -> instanciates with Remote configuration */
// else
// self::$instance[$label] = new DatabaseDriver($conf[$label]['remote']['host'], $conf[$label]['remote']['dbname'], $conf[$label]['remote']['user'], $conf[$label]['remote']['password']);
if(!isset($conf[$label]['local']['debug'])){
$conf[$label]['local']['debug'] = false;
}
return true;
if(isset($_SESSION['CurrentDatabase']) && is_string($_SESSION['CurrentDatabase'])){
$conf[$label]['local']['dbname'] = $_SESSION['CurrentDatabase'];
}else{
$_SESSION["CurrentDatabase"] = $conf[$label]['local']['dbname'];
}
self::$instance[$label] = new DatabaseDriver($conf[$label]['local']['host'], $conf[$label]['local']['dbname'], $conf[$label]['local']['user'], $conf[$label]['local']['password'],$conf[$label]['local']['debug']);
return true ;
}catch(\Exception $e){
@ -132,23 +147,21 @@
}
/* GET A DATABASE DRIVER INSTANCE
/** GET A DATABASE DRIVER INSTANCE
*
* @label<String> [optional] Driver's label
*
* @return driver<Database> Multiton
* @param String $label [optional] Driver's label
* @throws \Exception
* @return DatabaseDriver Multiton
*
*/
public static function get($label=null){
public static function get(String $label='default') : DatabaseDriver{
$conf = self::conf();
/* [1] Checks arguments
=========================================================*/
/* (1) Label default value */
is_null($label) && ($label = 'default');
/* (2) If no label, or unknown label */
if( is_null($label) || !isset(self::$instance[$label]) ){
/* (1) If no label, or unknown label */
if( !isset(self::$instance[$label]) ){
/* (2.1) Try to add the configuration if exists */
if( isset($conf[$label]) ){
@ -168,29 +181,68 @@
/** retourne la connection statique
* @param null $label
* @param String|null $label
* @throws \Exception
* @return \PDO
*/
public static function getPDO($label=null){
$instance = self::get($label);
public static function getPDO(?String $label=null) : \PDO{
if(is_string($label)){
$instance = self::get($label);
}else{
$instance = self::get();
}
return $instance->pdo;
}
/**
* @return \PDO
*/
public function pdo(){
return $this->pdo;
}
/**
* @return array
*/
public function getConfig(){
return [
'host' => $this->host,
'dbname' => $this->dbname,
'username' => $this->username
'username' => $this->username,
'password' => $this->password
];
}
/**
* enable request stacking
*/
public function enableStacking(){
$this->pdo->enableStacking();
}
/**
* send all the stacked request and flush the stack
*/
public function flushStack(){
$this->pdo->executeStack();
}
/** get all debug data
* @return array
*/
public function getDebug() : array{
return $this->pdo->getDebug();
}
/**
* @return bool
*/
public function isDebugEnabled() : bool {
return $this->pdo->isDebugEnabled();
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 30/08/16
* Time: 17:42
*/
namespace database\core\PDOWrapper;
class PDOStatementWrapper extends \PDOStatement
{
/** @var String */
private $statement;
/** @var array */
private $parameters;
/** @var PDOWrapper */
private $connexion;
/**
* PDOStatementWrapper constructor.
* @param String $statement
* @param PDOWrapper $connexion
*/
public function __construct(String $statement, PDOWrapper $connexion)
{
$this->statement = $statement;
$this->connexion = $connexion;
}
/**
* @param array $input_parameters
* @return bool
*/
public function execute($input_parameters = []) : bool
{
$this->parameters = $input_parameters;
$this->connexion->stackStatement($this);
return true;
}
/**
* @return string
*/
public function getStatement() : String
{
return $this->statement;
}
/**
* @return array
*/
public function getParameters() : array
{
return $this->parameters;
}
}

View File

@ -0,0 +1,198 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 30/08/16
* Time: 17:26
*/
namespace database\core\PDOWrapper;
class PDOWrapper extends \PDO
{
/** @var PDOStatementWrapper[] */
private $statements = [];
/** @var bool */
private $stacking = false;
/** @var array */
private $debug = [];
/** @var bool */
private $debugEnabled = false;
/**
* PDOWrapper constructor.
* @param String $dsn
* @param String $username
* @param String $passwd
* @param array $options
*/
public function __construct(String $dsn, String $username, String $passwd, array $options = [])
{
parent::__construct($dsn, $username, $passwd, $options);
}
/**
* @param string $statement
* @param array $options
* @return \PDOStatement
*/
public function prepare($statement, $options = []) : \PDOStatement
{
if($this->debugEnabled){
$this->storeDebug();
}
if($this->stacking){
return new PDOStatementWrapper($statement, $this);
}else{
$st = parent::prepare($statement, $options);
if($st === false){
throw new \PDOException("There is an error in your SQL statement");
}
return $st;
}
}
/**
* @throws \ReflectionException
*
* @return void
*/
private function storeDebug(){
//get all the debug info about the repo
$prepareStack = debug_backtrace(0,3)[1];
$stack = debug_backtrace(0,3)[2];
//create the reflection object
$f = new \ReflectionMethod($stack["class"],$stack["function"]);
//get only the repo name
$className = explode("\\",$stack["class"]);
$className = $className[count($className)-1];
$result = [];
//if we are flushing a stack, just count the number of request stacked
if($stack["function"] == "executeStack"){
$result["StackedRequest"] = true;
$result["numberOfStackedRequest"] = substr_count($prepareStack["args"][0],";");
//if we are not stacking, log the repo call
}else if(!$this->stacking){
//store results
$result["repoName"] = $className;
$result["methodName"] = $stack["function"];
$result["args"] = [];
foreach ($f->getParameters() as $key => $param) {
$result["args"][$param->name] = $stack["args"][$key];
}
//else we are stacking a request, we should not log it
}else{
return;
}
$this->debug[] = $result;
}
/**
* @return array
*/
public function getDebug() : array{
return $this->debug;
}
/**
* Enable request stacking
*/
public function enableStacking(){
$this->stacking = true;
}
/**
* @return bool
*/
public function isDebugEnabled() : bool{
return $this->debugEnabled;
}
/**
* @param PDOStatementWrapper $st
*/
public function stackStatement(PDOStatementWrapper $st){
array_push($this->statements,$st);
}
/**
* Enable repo debug
*/
public function enableDebug(){
$this->debugEnabled = true;
}
/**
* disable repo debug
*/
public function disableDebug(){
$this->debugEnabled = false;
}
/** Execute the stored request stack
* @return bool
*/
public function executeStack(){
//init the statements and the generator of number
$finalStatement = '';
$finalExecute = [];
$i = 0;
//for each request stacked
foreach ($this->statements as $request){
$statement = $request->getStatement();
// we have to modify the parameters index at the same time that we modify the request, so we use static class attribute
$tempParametes = $request->getParameters();
//find the given pattern in the request, then call our function and replace the matched string by the return value of our function
$finalStatement .= rtrim(preg_replace_callback("/(:[a-z_\-0-9]*)/is",function($matches) use (&$i,&$tempParametes){
//copy the parameter with the modified index
$tempParametes[":$i"] = $tempParametes[$matches[0]];
//delete the old index
unset($tempParametes[$matches[0]]);
//return the modified string for replacement
return ":".$i++;
},$statement),';').';';
$finalExecute += $tempParametes;
}
//disable stacking
$this->stacking = false;
//enable prepare emulation (native prepare do not accept stacked requests
parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
$this->beginTransaction();
$req = $this->prepare($finalStatement);
$success = $req->execute($finalExecute);
//as we execute multiple query that we don't fetch, we have to close the cursor if we want to do other requests later
$req->closeCursor();
$this->commit();
//using beginTransaction/commit disable the autocommit, we re-activate it
$this->setAttribute(\PDO::ATTR_AUTOCOMMIT,1);
parent::setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
return $success;
}
}

View File

@ -12,6 +12,7 @@
namespace database\core;
use database\core\PDOWrapper\PDOWrapper;
use \error\core\Error;
use \error\core\Err;
@ -20,13 +21,16 @@
/* (1) Driver
---------------------------------------------------------*/
/**
* @var DatabaseDriver
*/
private static $driver = null;
public static function setDriver(DatabaseDriver $driver){ self::$driver = $driver; }
public static function request(String $repo=null, String $method=null){
public static function getRepo(String $repo=null) : Repo_i{
/* (1) Check arguments
---------------------------------------------------------*/
@ -34,11 +38,7 @@
if( !is_string($repo) || strlen($repo) < 1 )
throw new \Exception("@repo is not a non-empty string");
/* (2) Check @method */
if( !is_string($method) || strlen($method) < 1 )
throw new \Exception("@method is not a non-empty string");
/* (3) Check class path */
/* (1) Check class path */
$class_path = "\\database\\repo\\$repo";
if( !\class_exists($class_path) )
@ -58,19 +58,31 @@
\call_user_func([$instance, 'setPDO'], self::$driver->pdo());
/* (3) Check if the method exists */
if( !\method_exists($instance, $method) )
throw new \Exception("Repo '$repo' has no public method '$method'");
return $instance;
}
/* (4) Fetch response (send arguments as well) */
$response = call_user_func_array([$instance, $method], array_slice(func_get_args(), 2));
public static function enableStacking(){
static::$driver->enableStacking();
}
/* (5) Call post-script */
$instance = null;
public static function flushStack(){
static::$driver->flushStack();
}
/* (6) Dispatch response */
return $response;
public static function getDebug() : array{
return static::$driver->getDebug();
}
public static function isDebugEnabled() : bool{
return static::$driver->isDebugEnabled();
}
public static function switchDatabase(string $dbName){
return static::$driver->pdo()->exec("USE $dbName;SET autocommit=1;");
}
public static function getDBConfig() : array{
return static::$driver->getConfig();
}

View File

@ -0,0 +1,141 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 20/02/18
* Time: 21:00
*/
namespace database\repo;
use database\core\Repo_i;
class category extends Repo_i{
public function create(int $id, string $label) : bool{
//create the category or update the label
$st = $this->pdo->prepare("INSERT INTO Categorie (idCategorie, labelCategorie) VALUE (:id, :label)");
return $st->execute([
"id" => $id,
"label" => $label
]);
}
public function delete(int $id) :bool{
$st = $this->pdo->prepare("DELETE FROM Categorie WHERE idCategorie = :id");
return $st->execute([
"id" => $id
]);
}
public function getStats(?int $id = null){
$st = $this->pdo->prepare("SELECT IFNULL(VHCours,0) VHCours, IFNULL(VHTd,0)VHTd, IFNULL(VHTp,0)VHTp, Cat.idCategorie idCat, count(P.idProfesseur) nbrProf, Cat.labelCategorie labelCat
FROM Categorie Cat
LEFT JOIN (SELECT IFNULL(SUM(Cours.volume),0) VHCours, Prof.Categorie_idCategorie idCat
FROM Professeur Prof
LEFT JOIN Cours ON Prof.idProfesseur = Cours.Professeur_idProfesseur
LEFT JOIN UE U ON Cours.UE_code = U.code
GROUP BY Prof.Categorie_idCategorie, U.disabled
HAVING U.disabled = 0) VHCours ON VHCours.idCat = Cat.idCategorie
LEFT JOIN (SELECT IFNULL(SUM(TD.volume),0) VHTd , Prof.Categorie_idCategorie idCat
FROM Professeur Prof
LEFT JOIN TD ON TD.Professeur_idProfesseur = Prof.idProfesseur
LEFT JOIN UE U2 ON TD.UE_code = U2.code
GROUP BY Prof.Categorie_idCategorie, U2.disabled
HAVING U2.disabled = 0) VHTd ON VHTd.idCat = Cat.idCategorie
LEFT JOIN (SELECT IFNULL(SUM(TP.volume),0) VHTp, Prof.Categorie_idCategorie idCat
FROM Professeur Prof
LEFT JOIN TP ON TP.Professeur_idProfesseur = Prof.idProfesseur
LEFT JOIN UE U3 ON TP.UE_code = U3.code
GROUP BY Prof.Categorie_idCategorie, U3.disabled
HAVING U3.disabled = 0) VHTp ON VHTp.idCat = Cat.idCategorie
LEFT JOIN Professeur P ON Cat.idCategorie = P.Categorie_idCategorie
".($id ? " WHERE Cat.idCategorie = :idCat" : "")."
GROUP BY Cat.idCategorie;");
$st->execute($id ? ["idCat" => $id] : []);
if($id){
return $st->fetch() ?: [];
}else{
return $st->fetchAll();
}
}
/* (4) Gets a category by its UID ||| getAll
*
* @cat_id<int> [OPT] The category UID, if not set, getAll()
*
* @return categories<array> The categories matching id (NULL on error)
*
---------------------------------------------------------*/
public function get(?int $cat_id=null) : ?array{
/* (1) Manage if no id given */
$cond = is_null($cat_id) ? '' : ' WHERE `idCategorie` = :id';
$parm = is_null($cat_id) ? [] : [':id' => $cat_id];
/* (2) Prepare Statement */
$st = $this->pdo->prepare("SELECT * FROM `Categorie`$cond ORDER BY `labelCategorie` ASC");
/* (3) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute($parm);
/* (4) Manage error */
if( !$success )
return [];
/* (5) Get data */
$fetched = $st->fetchAll();
/* (6) Return [] on no result */
if( $fetched === false )
return [];
/* (7) Return data */
return $fetched;
}
/* (5) Gets all professors who teaches a category by ids (array)
*
* @cat_id<int> The category id
*
* @return professors<array> The professors' UID matching the @cat_id category
*
---------------------------------------------------------*/
public function getProfessors(int $cat_id) : array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT idProfesseur FROM Professeur WHERE Categorie_idCategorie = :cat_id;");
/* (2) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute([ ':cat_id' => $cat_id ]);
/* (3) Manage error */
if( !$success )
return [];
/* (4) Get data */
$fetched = $st->fetchAll();
/* (5) Return [] on no result */
if( $fetched === false )
return [];
/* (6) Return data */
return $fetched;
}
}

View File

@ -0,0 +1,294 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 22/02/18
* Time: 13:27
*/
namespace database\repo;
use database\core\Repo_i;
class cours extends Repo_i {
/* (1) Create a new Cours
*
* @code<String> The code of the UE containing the Cours
* @idProf<String> [OPT] The ID of the prof who teaches the Cours
* @volume<float> The number of hours (float)
* @formations<array> The list of formations for that Cours (list of int)
* @return created_code<String> Code of the created UE (NULL on error)
*
* @return created_id<int> UID of the created Cours (NULL on error)
*
---------------------------------------------------------*/
public function create(string $code, ?int $idProf, float $volume, array $formations) : ?int{
/* (1) Prepare statement */
$st = $this->pdo->prepare('INSERT INTO Cours(UE_code, Professeur_idProfesseur, volume)
VALUE(:UE, :idProf, :vol)');
/* (2) Manage statement error */
if( is_bool($st) )
return NULL;
/* (3) Try to execute request */
$success = $st->execute([
':UE' => $code,
':idProf' => $idProf,
':vol' => $volume
]);
/* (4) Manage error */
if( !$success )
return NULL;
/* (5) Store @created_id */
$created_id = (int) $this->pdo->lastInsertId();
/* (6) We are done if there is no formations */
if( count($formations) <= 0)
return $created_id;
/* (7) Else -> create each formation */
foreach($formations as $form_id){
// 1. Ignore if wrong format
if( !is_int($form_id) || $form_id < 0 )
continue;
// 2. Link formation to created Cours
$this->linkFormation($form_id, $created_id);
}
/* (7) Return @created_id */
return $created_id;
}
/* (2) Unlink a formation from a Cours
*
* @idFormation<int> Id of the formation
* @idCours<int> Id of the Cours
*
* @return unlinked<bool> Whether it has been unlinked
*
---------------------------------------------------------*/
public function unlinkFormation(int $idFormation, int $idCours) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare('DELETE FROM GroupeCours WHERE Cours_idCours = :cours AND Formation_idFormation = :form');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) EXecute and dispatch status */
return $st->execute([
':cours' => $idCours,
':form' => $idFormation
]);
}
/* (3) Link a formation to a Cours
*
* @idFormation<int> Id of the formation
* @idCours<int> Id of the Cours
*
* @return linked<bool> Whether it has been linked
*
---------------------------------------------------------*/
public function linkFormation(int $idFormation, int $idCours) : bool{
/* (1) Try to remove first if it already exists */
$this->unlinkFormation($idFormation, $idCours);
/* (2) Prepare statement */
$st = $this->pdo->prepare('INSERT INTO GroupeCours(Cours_idCours,Formation_idFormation)
VALUE(:cours, :form)');
/* (3) Manage statement error */
if( is_bool($st) )
return false;
/* (4) EXecute and dispatch status */
return $st->execute([
':cours' => $idCours,
':form' => $idFormation
]);
}
/* (4.1) Updates an existing Cours
*
* @idCours<int> Id of the Cours
* @idProf<int> [OPT] Id of the prof (NULL to set to NULL)
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public function updateProf(int $idCours, ?int $idProf) : bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare('UPDATE Cours
SET Professeur_idProfesseur = :idProf
WHERE idCours = :idCours');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':idCours' => $idCours, ':idProf' => $idProf ]);
}
/* (4.2) Updates an existing Cours
*
* @idCours<int> Id of the Cours
* @volume<float> [OPT] The new number of hours
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public function updateVolume(int $idCours, float $volume) : bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare('UPDATE Cours
SET volume = :volume
WHERE idCours = :idCours');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':idCours' => $idCours, ':volume' => $volume ]);
}
/* (5) Deletes an existing cours
*
* @idCours<int> Id of the Cours
*
* @return deleted<bool> Whether it has been deleted
*
---------------------------------------------------------*/
public function delete(int $id) :bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare("DELETE FROM Cours WHERE idCours = :id");
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':id' => $id ]);
}
/* (6) Get groups for a specific UE
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
* NULL on error
*
---------------------------------------------------------*/
public function getGroups(String $code) : ?array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT
c.UE_code code,
c.idCours,
p.idProfesseur idProf,
p.firstName,
p.lastName,
IFNULL(lform.flist, '[]') formations,
c.volume
FROM Cours c
LEFT JOIN ( SELECT gc.Cours_idCours idCours, CONCAT('[', GROUP_CONCAT(DISTINCT gc.Formation_idFormation),']') flist
FROM GroupeCours gc
GROUP BY gc.Cours_idCours
ORDER BY gc.Formation_idFormation DESC
) lform ON c.idCours = lform.idCours
LEFT JOIN Professeur p ON p.idProfesseur = c.Professeur_idProfesseur
WHERE c.UE_code = :code;");
/* (2) Check statement */
if( is_bool($st) )
return NULL;
/* (3) Execute statement */
$success = $st->execute([':code' => $code]);
/* (4) Check error */
if( !$success )
return NULL;
/* (5) Dispatch fetch result */
return $st->fetchAll();
}
/* (7) Get groups for a specific Professor
*
* @prof_id<int> Professor ID
*
* @return groups<array> The list of groups for this Professor
* NULL on error
*
---------------------------------------------------------*/
public function getForProfessor(int $prof_id) : ?array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT
c.UE_code code,
ue.label label,
c.idCours,
IFNULL(lform.flist, '[]') formations,
c.volume
FROM Cours c
LEFT JOIN ( SELECT gc.Cours_idCours idCours, CONCAT('[', GROUP_CONCAT(DISTINCT gc.Formation_idFormation),']') flist
FROM GroupeCours gc
GROUP BY gc.Cours_idCours
ORDER BY gc.Formation_idFormation DESC
) lform ON c.idCours = lform.idCours
JOIN UE ue ON ue.code = c.UE_code
WHERE c.Professeur_idProfesseur = :prof_id;");
/* (2) Check statement */
if( is_bool($st) )
return NULL;
/* (3) Execute statement */
$success = $st->execute([':prof_id' => $prof_id]);
/* (4) Check error */
if( !$success )
return NULL;
/* (5) Dispatch fetch result */
return $st->fetchAll();
}
}

View File

@ -0,0 +1,266 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 09/05/18
* Time: 16:55
*/
namespace database\repo;
use database\core\Repo;
use database\core\Repo_i;
class database extends Repo_i {
/**
* @param int $depId
* @return String the name of the department database
* @throws \Exception
*/
public function init(int $depId) : String{
/** @var department $metaRep */
$metaRep = Repo::getRepo("department");
$SQL = "
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
-- -----------------------------------------------------
-- Table `Categorie`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Categorie` (
`idCategorie` INT(11) NOT NULL,
`labelCategorie` VARCHAR(100) NOT NULL,
PRIMARY KEY (`idCategorie`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `Professeur`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Professeur` (
`idProfesseur` INT(11) NOT NULL AUTO_INCREMENT,
`casLogin` VARCHAR(50) NULL DEFAULT NULL,
`lastName` VARCHAR(50) NULL DEFAULT NULL,
`firstName` VARCHAR(50) NULL DEFAULT NULL,
`abreviation` VARCHAR(10) NULL DEFAULT NULL COMMENT 'Abreviation used in the excel document',
`admin` TINYINT(4) NOT NULL DEFAULT 0,
`hoursToDo` INT(11) NOT NULL DEFAULT 0,
`Categorie_idCategorie` INT(11) NOT NULL,
PRIMARY KEY (`idProfesseur`),
INDEX `fk_Professeur_Categorie1_idx` (`Categorie_idCategorie` ASC),
CONSTRAINT `fk_Professeur_Categorie1`
FOREIGN KEY (`Categorie_idCategorie`)
REFERENCES `Categorie` (`idCategorie`)
ON DELETE NO ACTION
ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 34
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `Formation`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Formation` (
`idFormation` INT(11) NOT NULL AUTO_INCREMENT,
`labelFormation` VARCHAR(50) NULL DEFAULT NULL,
`isInternal` TINYINT(4) NULL DEFAULT 1,
PRIMARY KEY (`idFormation`))
ENGINE = InnoDB
AUTO_INCREMENT = 20
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `UE`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `UE` (
`code` VARCHAR(20) NOT NULL,
`label` VARCHAR(100) NOT NULL,
`required` TINYINT(4) NOT NULL DEFAULT 1,
`volumeCours` FLOAT NOT NULL DEFAULT 0,
`volumeTP` FLOAT NOT NULL DEFAULT 0,
`volumeTD` FLOAT NOT NULL,
`disabled` TINYINT(4) NOT NULL DEFAULT 0,
`Formation_idFormation` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`code`),
INDEX `fk_UE_Formation1_idx` (`Formation_idFormation` ASC),
CONSTRAINT `fk_UE_Formation1`
FOREIGN KEY (`Formation_idFormation`)
REFERENCES `Formation` (`idFormation`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1
COMMENT = 'Table contenant le code et le label des UE';
-- -----------------------------------------------------
-- Table `Cours`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `Cours` (
`idCours` INT(11) NOT NULL AUTO_INCREMENT,
`UE_code` VARCHAR(20) NOT NULL,
`Professeur_idProfesseur` INT(11) NULL DEFAULT NULL,
`volume` FLOAT NOT NULL DEFAULT 0,
PRIMARY KEY (`idCours`),
INDEX `fk_Cours_UE_idx` (`UE_code` ASC),
INDEX `fk_Cours_Professeur1_idx` (`Professeur_idProfesseur` ASC),
CONSTRAINT `fk_Cours_Professeur1`
FOREIGN KEY (`Professeur_idProfesseur`)
REFERENCES `Professeur` (`idProfesseur`)
ON DELETE SET NULL
ON UPDATE SET NULL,
CONSTRAINT `fk_Cours_UE`
FOREIGN KEY (`UE_code`)
REFERENCES `UE` (`code`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 88
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `GroupeCours`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `GroupeCours` (
`Formation_idFormation` INT(11) NOT NULL,
`Cours_idCours` INT(11) NOT NULL,
PRIMARY KEY (`Formation_idFormation`, `Cours_idCours`),
INDEX `fk_Formation_has_Cours_Cours1_idx` (`Cours_idCours` ASC),
INDEX `fk_Formation_has_Cours_Formation1_idx` (`Formation_idFormation` ASC),
CONSTRAINT `fk_Formation_has_Cours_Cours1`
FOREIGN KEY (`Cours_idCours`)
REFERENCES `Cours` (`idCours`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `fk_Formation_has_Cours_Formation1`
FOREIGN KEY (`Formation_idFormation`)
REFERENCES `Formation` (`idFormation`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `TD`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `TD` (
`idTD` INT(11) NOT NULL AUTO_INCREMENT,
`UE_code` VARCHAR(20) NOT NULL,
`Professeur_idProfesseur` INT(11) NULL DEFAULT NULL,
`volume` FLOAT NOT NULL DEFAULT 0,
PRIMARY KEY (`idTD`),
INDEX `fk_TD_UE1_idx` (`UE_code` ASC),
INDEX `fk_TD_Professeur1_idx` (`Professeur_idProfesseur` ASC),
CONSTRAINT `fk_TD_Professeur1`
FOREIGN KEY (`Professeur_idProfesseur`)
REFERENCES `Professeur` (`idProfesseur`)
ON DELETE SET NULL
ON UPDATE SET NULL,
CONSTRAINT `fk_TD_UE1`
FOREIGN KEY (`UE_code`)
REFERENCES `UE` (`code`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 107
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `GroupeTD`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `GroupeTD` (
`Formation_idFormation` INT(11) NOT NULL,
`TD_idTD` INT(11) NOT NULL,
PRIMARY KEY (`Formation_idFormation`, `TD_idTD`),
INDEX `fk_Formation_has_TD_TD1_idx` (`TD_idTD` ASC),
INDEX `fk_Formation_has_TD_Formation1_idx` (`Formation_idFormation` ASC),
CONSTRAINT `fk_Formation_has_TD_Formation1`
FOREIGN KEY (`Formation_idFormation`)
REFERENCES `Formation` (`idFormation`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `fk_Formation_has_TD_TD1`
FOREIGN KEY (`TD_idTD`)
REFERENCES `TD` (`idTD`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `TP`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `TP` (
`idTP` INT(11) NOT NULL AUTO_INCREMENT,
`UE_code` VARCHAR(20) NOT NULL,
`Professeur_idProfesseur` INT(11) NULL DEFAULT NULL,
`volume` FLOAT NOT NULL DEFAULT 0,
PRIMARY KEY (`idTP`),
INDEX `fk_TP_UE1_idx` (`UE_code` ASC),
INDEX `fk_TP_Professeur1_idx` (`Professeur_idProfesseur` ASC),
CONSTRAINT `fk_TP_Professeur1`
FOREIGN KEY (`Professeur_idProfesseur`)
REFERENCES `Professeur` (`idProfesseur`)
ON DELETE SET NULL
ON UPDATE SET NULL,
CONSTRAINT `fk_TP_UE1`
FOREIGN KEY (`UE_code`)
REFERENCES `UE` (`code`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
AUTO_INCREMENT = 164
DEFAULT CHARACTER SET = latin1;
-- -----------------------------------------------------
-- Table `GroupeTP`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `GroupeTP` (
`Formation_idFormation` INT(11) NOT NULL,
`TP_idTP` INT(11) NOT NULL,
PRIMARY KEY (`Formation_idFormation`, `TP_idTP`),
INDEX `fk_Formation_has_TP_TP1_idx` (`TP_idTP` ASC),
INDEX `fk_Formation_has_TP_Formation1_idx` (`Formation_idFormation` ASC),
CONSTRAINT `fk_Formation_has_TP_Formation1`
FOREIGN KEY (`Formation_idFormation`)
REFERENCES `Formation` (`idFormation`)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT `fk_Formation_has_TP_TP1`
FOREIGN KEY (`TP_idTP`)
REFERENCES `TP` (`idTP`)
ON DELETE CASCADE
ON UPDATE CASCADE)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
LOCK TABLES `Categorie` WRITE;
/*!40000 ALTER TABLE `Categorie` DISABLE KEYS */;
INSERT INTO `Categorie` VALUES (1,'Professeurs et Maîtres de Conférences'),(2,'ATERs'),(3,'CDDs enseignement'),(4,'Doctorants Vacataires'),(5,'Permanents UPPA'),(6,'Vacataires extérieurs');
/*!40000 ALTER TABLE `Categorie` ENABLE KEYS */;
UNLOCK TABLES;
";
return $metaRep->createVersionDatabase($depId,$SQL);
}
}

View File

@ -0,0 +1,179 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 05/03/18
* Time: 19:39
*/
namespace database\repo;
use database\core\Repo;
use database\core\Repo_i;
class department extends Repo_i
{
public function getErrors() : array {
$results = [];
/* (1) Find Groups without formation bound */
$GroupWithoutFormation = $this->pdo->prepare("
(SELECT 'NO_FORMATION_ASSIGNED' errorType, 'Cours' entityType, idCours id FROM Cours WHERE idCours NOT IN (SELECT Cours_idCours FROM GroupeCours))
UNION
(SELECT 'NO_FORMATION_ASSIGNED' errorType, 'TD' entityType, idTD id FROM TD WHERE idTD NOT IN (SELECT TD_idTD FROM GroupeTD))
UNION
(SELECT 'NO_FORMATION_ASSIGNED' errorType, 'TP' entityType, idTP id FROM TP WHERE idTP NOT IN (SELECT TP_idTP FROM GroupeTP))");
$GroupWithoutFormation->execute([]);
$results = array_merge($results,$GroupWithoutFormation->fetchAll());
/* (2) Find Groups without a professor bound */
$GroupWithoutProfessor = $this->pdo->prepare("
(SELECT 'NO_PROFESSOR_ASSIGNED' errorType, 'Cours' entityType, idCours id FROM Cours WHERE Professeur_idProfesseur IS NULL)
UNION
(SELECT 'NO_PROFESSOR_ASSIGNED' errorType, 'TD' entityType, idTD id FROM TD WHERE Professeur_idProfesseur IS NULL)
UNION
(SELECT 'NO_PROFESSOR_ASSIGNED' errorType, 'TP' entityType, idTP id FROM TP WHERE Professeur_idProfesseur IS NULL)");
$GroupWithoutProfessor->execute([]);
$results = array_merge($results,$GroupWithoutProfessor->fetchAll());
/* (3) Find Groups a null VH */
$GroupWithNullVH = $this->pdo->prepare("
(SELECT 'NULL_VH' errorType, 'Cours' entityType, idCours id FROM Cours WHERE volume = 0)
UNION
(SELECT 'NULL_VH' errorType, 'TD' entityType, idTD id FROM TD WHERE volume = 0)
UNION
(SELECT 'NULL_VH' errorType, 'TP' entityType, idTP id FROM TP WHERE volume = 0)");
$GroupWithNullVH->execute([]);
$results = array_merge($results,$GroupWithNullVH->fetchAll());
/* (4) Find UE with an incorrect VH in the groups compared to what's supposed to be */
$UEWithIncorrectGroupVH = $this->pdo->prepare("
(SELECT 'UNEQUIVALENT_VH' errorType, 'Cours' entityType, U.code
FROM UE U
WHERE
0 != (SELECT MOD(SUM(volume),U.volumeCours) modCours FROM Cours WHERE UE_code = U.code GROUP BY Cours.UE_code)
)
UNION
(SELECT 'UNEQUIVALENT_VH' errorType, 'TD' entityType, U.code
FROM UE U
WHERE
0 != (SELECT MOD(SUM(volume),U.volumeTD) modCours FROM TD WHERE UE_code = U.code GROUP BY TD.UE_code)
)
UNION
(SELECT 'UNEQUIVALENT_VH' errorType, 'TP' entityType, U.code
FROM UE U
WHERE
0 != (SELECT MOD(SUM(volume),U.volumeTP) modCours FROM TP WHERE UE_code = U.code GROUP BY TP.UE_code)
)");
$UEWithIncorrectGroupVH->execute([]);
$results = array_merge($results,$UEWithIncorrectGroupVH->fetchAll());
return $results;
}
public function getStats() : array{
/* (1) Potentiel horaire du département */
$Potentiel = $this->pdo->prepare("SELECT SUM(hoursToDo) potentiel
FROM Professeur
WHERE Categorie_idCategorie IN (1,2,3)
GROUP BY Categorie_idCategorie IN (1,2,3);");
$Potentiel->execute([]);
$results = $Potentiel->fetch();
/* (2) Sous-service (professeurs ayant moins d'heure prévu que d'heure du) */
/** @var professor $ProfRepo */
$ProfRepo = Repo::getRepo("professor");
$profs = $ProfRepo->getWithVH(null);
$results["sous_service"] = 0;
$results["heures_comp"] = 0;
$results["heures_vacataire"] = 0;
foreach ($profs as $prof){
if(in_array($prof["idCat"],[1,2,3,4]) and $prof["equiTD"] < $prof["hoursToDo"]){
$results["sous_service"] += $prof["hoursToDo"] - $prof["equiTD"];
/* (3) Heures effectués par des vacataires */
}else if(in_array($prof["idCat"],[5,6])){
$results["heures_vacataire"] += $prof["equiTD"];
}
/* (4) Heures complementaires */
if(is_numeric($prof["VHComp"])){
$results["heures_comp"] += $prof["VHComp"];
}
}
/* (5) Heures effectuées pour des départements exterieurs */
//je crois que j'ai créé un montre - Lucas - 2018
$HDepExt = $this->pdo->prepare("
SELECT U.disabled disabled,
count(U.code) nbrUe,
SUM((IFNULL(T1.VolumeCours,0)*IFNULL(tauxInfoCours,0) + IFNULL(T2.VolumeTD,0)*IFNULL(tauxInfoTD,0) + IFNULL(T3.VolumeTP,0)*IFNULL(tauxInfoTP,0))) totalInfo,
SUM((IFNULL(T1.VolumeCours,0)*(1-IFNULL(tauxInfoCours,0)) + IFNULL(T2.VolumeTD,0)*(1-IFNULL(tauxInfoTD,0)) + IFNULL(T3.VolumeTP,0)*(1-IFNULL(tauxInfoTP,0)))) totalExterieur
FROM UE U
LEFT JOIN (SELECT SUM(F.isInternal)/count(F.idFormation) tauxInfoCours,SUM(C.volume)*1.5 VolumeCours, C.UE_code code_UE
FROM Cours C
JOIN GroupeCours C2 ON C.idCours = C2.Cours_idCours
JOIN Formation F ON C2.Formation_idFormation = F.idFormation
GROUP BY C.UE_code) T1 ON U.code = T1.code_UE
LEFT JOIN (SELECT SUM(F.isInternal)/count(F.idFormation) tauxInfoTD,SUM(T1.volume) VolumeTD, T1.UE_code code_UE
FROM TD T1
JOIN GroupeTD GT ON T1.idTD = GT.TD_idTD
JOIN Formation F ON GT.Formation_idFormation = F.idFormation
GROUP BY T1.UE_code) T2 ON U.code = T2.code_UE
LEFT JOIN (SELECT SUM(F.isInternal)/count(F.idFormation) tauxInfoTP,SUM(T1.volume) VolumeTP, T1.UE_code code_UE
FROM TP T1
JOIN GroupeTP TP2 ON T1.idTP = TP2.TP_idTP
JOIN Formation F ON TP2.Formation_idFormation = F.idFormation
GROUP BY T1.UE_code) T3 ON U.code = T3.code_UE
GROUP BY U.disabled");
$HDepExt->execute([]);
$HDepExtData = $HDepExt->fetchAll();
$results = array_merge($results,[
"heures_exterieur" => $HDepExtData[0]["totalExterieur"],
"heures_ue_desactive" => $HDepExtData[1]["totalExterieur"] + $HDepExtData[1]["totalInfo"],
"nbr_ue_desactive" => $HDepExtData[1]["nbrUe"]
]);
return $results;
}
public function createVersionDatabase(String $depId, String $SQL) : String{
$dbName = uniqid($depId)."";
$this->pdo->exec("CREATE DATABASE $dbName; USE $dbName;".$SQL."USE {$_SESSION["CurrentDatabase"]};SET autocommit=1;");
$this->pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT,1);
return $dbName;
}
}

View File

@ -0,0 +1,194 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 20/02/18
* Time: 21:35
*/
namespace database\repo;
use database\core\Repo_i;
class formation extends Repo_i {
/* (1) Creates a new formation
*
* @label<String> The formation label
* @isInternal<bool> Whether the formation is internal
*
* @return form_id<int> The formation UID (or NULL on error)
*
---------------------------------------------------------*/
public function create(string $label, bool $isInternal) : ?int{
/* (1) Prepare statement */
$st = $this->pdo->prepare("INSERT INTO `Formation` (`labelFormation`, `isInternal`) VALUE (:label, :isInternal);");
/* (2) Bind params and execute statement */
if( is_bool($st) ) return NULL;
$success = $st->execute([
':label' => $label,
':isInternal' => $isInternal ? 1 : 0
]);
/* (3) Manage error */
if( !$success )
return NULL;
/* (4) Return inserted ID */
return $this->pdo->lastInsertId();
}
public function update(int $idFormation, ?String $label, ?bool $isInternal) : bool{
$req = "";
$execute = [];
if($label != null){
$req .= "labelFormation=:label,";
$execute["label"] = $label;
}
if($isInternal != null){
$req .= "isInternal=:isInternal,";
$execute["isInternal"] = $isInternal?1:0;
}
$req = rtrim($req,",");
$execute["idFormation"] = $idFormation;
$st = $this->pdo->prepare("UPDATE `Formation` SET $req WHERE idFormation=:idFormation");
return $st->execute($execute);
}
/* (2) Check if a formation exists (by its label)
*
* @label<String> The formation label
*
* @return form_id<int> The formation UID (or NULL on error)
*
---------------------------------------------------------*/
public function exists(string $label) : ?int{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT `idFormation` FROM `Formation` WHERE `labelFormation` = :label");
/* (2) Bind params and execute statement */
if( is_bool($st) ) return NULL;
$success = $st->execute([ ':label' => $label ]);
/* (3) Manage error */
if( !$success )
return NULL;
/* (4) Return if we have a result */
return $st->fetch()['idFormation'] ?: 0;
}
/* (3) Deletes a formation
*
* @return deleted<bool> Whether the formation have been deleeted successfully
*
---------------------------------------------------------*/
public function delete(int $id) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare("DELETE FROM `Formation` WHERE `idFormation` = :id");
/* (2) Bind params and execute request */
if( is_bool($st) ) return false;
/* (3) Dispatch the execution status */
return $st->execute([ ':id' => $id ]);
}
/* (4) Gets a formation by its ID || getAll
*
* @form_id<int> [OPT] The formation id, if not set, getAll()
*
* @return formations<array> The formations matching id
*
---------------------------------------------------------*/
public function get(?int $form_id) : array{
/* (1) Manage if no id given */
$cond = is_null($form_id) ? '' : 'WHERE Form.idFormation = :form_id';
$parm = is_null($form_id) ? [] : [ ':form_id' => $form_id ];
/* (2) Prepare statement */
$st = $this->pdo->prepare("SELECT IFNULL(VHCours,0) VHCours, IFNULL(VHTd,0) VHTd, IFNULL(VHTp,0) VHTp, (IFNULL(VHCours,0) + IFNULL(VHTd,0) + IFNULL(VHTp,0)) VHTotal, Form.isInternal isInternal, Form.idFormation idForm, Form.labelFormation labelForm
FROM Formation Form
LEFT JOIN (SELECT IFNULL(SUM(C.volume),0) VHCours, GC.Formation_idFormation idForm FROM GroupeCours GC LEFT JOIN Cours C ON GC.Cours_idCours = C.idCours GROUP BY GC.Formation_idFormation) VHCours ON VHCours.idForm = Form.idFormation
LEFT JOIN (SELECT IFNULL(SUM(T.volume),0) VHTd, GTD.Formation_idFormation idForm FROM GroupeTD GTD LEFT JOIN TD T ON GTD.TD_idTD = T.idTD GROUP BY GTD.Formation_idFormation) VHTd ON VHTd.idForm = Form.idFormation
LEFT JOIN (SELECT IFNULL(SUM(T2.volume),0) VHTp, GTP.Formation_idFormation idForm FROM GroupeTP GTP LEFT JOIN TP T2 ON GTP.TP_idTP = T2.idTP GROUP BY GTP.Formation_idFormation) VHTp ON VHTp.idForm = Form.idFormation
$cond;");
/* (3) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute($parm);
/* (4) Manage error */
if( !$success )
return [];
/* (5) Get data */
$fetched = $st->fetchAll();
/* (6) Return [] on no result */
if( $fetched === false )
return [];
/* (7) Return data */
return $fetched;
}
/* (5) Gets all professors who teaches a formation by ids (array)
*
* @form_id<int> The formation id
*
* @return professors<array> The professors' UID matching the @form_id formation
*
---------------------------------------------------------*/
public function getProfessors(int $form_id) : array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT p.idProfesseur
FROM Professeur p, Formation f
WHERE (
p.idProfesseur IN ( SELECT p_cr.idProfesseur FROM Professeur p_cr, UE ue, Cours c WHERE c.Professeur_idProfesseur = p_cr.idProfesseur AND c.UE_code = ue.code AND ue.Formation_idFormation = f.idFormation )
OR p.idProfesseur IN ( SELECT p_td.idProfesseur FROM Professeur p_td, UE ue, TD t WHERE t.Professeur_idProfesseur = p_td.idProfesseur AND t.UE_code = ue.code AND ue.Formation_idFormation = f.idFormation )
OR p.idProfesseur IN ( SELECT p_tp.idProfesseur FROM Professeur p_tp, UE ue, TP t WHERE t.Professeur_idProfesseur = p_tp.idProfesseur AND t.UE_code = ue.code AND ue.Formation_idFormation = f.idFormation )
)
AND f.idFormation = :form_id;");
/* (2) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute([ ':form_id' => $form_id ]);
/* (3) Manage error */
if( !$success )
return [];
/* (4) Get data */
$fetched = $st->fetchAll();
/* (5) Return [] on no result */
if( $fetched === false )
return [];
/* (6) Return data */
return $fetched;
}
}

View File

@ -0,0 +1,351 @@
<?php
namespace database\repo;
use database\core\Repo_i;
class meta extends Repo_i {
/* (1) Creates a new professor
*
* @casLogin<String> The professor's cas login
* @firstName<String> [OPT] The professor's firstName
* @lastName<String> [OPT] The professor's lastName
*
* @return created<bool> Whether the professor has been created
*
---------------------------------------------------------*/
public function create_prof(String $casLogin, ?String $firstName, ?String $lastName) : bool{
/* (1) Create user in meta database
---------------------------------------------------------*/
/* (1) Try to insert user */
$st = $this->pdo->prepare("INSERT INTO
meta_vhost.casUser(casLogin, firstName, lastName)
VALUES(:cas_login, :first_name, :last_name)");
/* (2) Manage statement error */
if( is_bool($st) )
return FALSE;
/* (3) Try to execute */
$success = $st->execute([
':cas_login' => $casLogin,
':first_name' => $firstName,
':last_name' => $lastName
]);
/* (4) Dispatch execution error */
return $success;
}
/* (2) Check if a professor exists (by its casLogin)
*
* @casLogin<String> The professor's cas login
*
* @return exists<bool> Whether the professor exists
*
---------------------------------------------------------*/
public function prof_exists(String $casLogin) : bool{
/* (1) Prepare Statement */
$st = $this->pdo->prepare("SELECT casLogin
FROM meta_vhost.casUser
WHERE casLogin = :cas_login;");
/* (2) Statement eror */
if( is_bool($st) )
return FALSE;
/* (3) Bind params and execute */
$success = $st->execute([ ':cas_login' => $casLogin ]);
/* (4) Manage execution error */
if( !$success )
return FALSE;
/* (7) Return That it exists */
return is_array( $st->fetch() );
}
/* (3) Get available departments for a CAS login
*
* @casLogin<String> The professor's CAS username
*
* @return departments<array> The list of available departments (empty on error)
*
---------------------------------------------------------*/
public function get_prof_departments(String $casLogin) : array{
/* (1) Prepare Statement */
$st = $this->pdo->prepare("SELECT d2.iddepartement idDep, d2.label labelDep
FROM meta_vhost.casUser
JOIN meta_vhost.linkedDep D ON casUser.casLogin = D.casUser_casLogin
JOIN meta_vhost.departement d2 ON D.departement_iddepartement = d2.iddepartement
WHERE casLogin = :cas_login");
/* (2) Check if statement error */
if( is_bool($st) )
return [];
/* (3) Bind params and execute sstatement */
$success = $st->execute([ ':cas_login' => $casLogin ]);
/* (4) Manage error */
if( !$success )
return [];
/* (5) Get data */
$fetched = $st->fetchAll();
/* (6) Return [] on no result */
if( $fetched === false )
return [];
/* (7) Add all possible databases to the department */
foreach ($fetched as &$dep){
$st = $this->pdo->prepare("SELECT *
FROM meta_vhost.`databases`
WHERE departement_iddepartement = :idDep
ORDER BY meta_vhost.`databases`.`default` DESC ");
$st->execute(["idDep" => $dep["idDep"]]);
$dep["versions"] = $st->fetchAll();
}
/* (8) Return data */
return $fetched;
}
/* (4) Deletes a professor
*
* @casLogin<String> The professor's CAS username
*
* @return deleted<bool> Whether the professor have been deleeted successfully
*
---------------------------------------------------------*/
public function delete_prof(String $casLogin) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare('DELETE FROM meta_vhost.casUser
WHERE casLogin = :cas_login');
/* (2) Manage statement error */
if( is_bool($st) )
return FALSE;
/* (3) Try to execute */
$success = $st->execute([ ':cas_login' => $casLogin ]);
/* (4) Dispatch execution error */
return $success;
}
/* (5) Check if a link exists
*
* @casLogin<String> The professor's cas login
* @idDep<int> The department id
*
* @return exists<bool> Whether the professor exists
*
---------------------------------------------------------*/
public function link_exists(String $casLogin, int $idDep) : bool{
/* (1) Prepare Statement */
$st = $this->pdo->prepare("SELECT *
FROM meta_vhost.linkedDep
WHERE departement_iddepartement = :id_dep
AND casUser_casLogin = :cas_login");
/* (2) Statement eror */
if( is_bool($st) )
return FALSE;
/* (3) Bind params and execute */
$success = $st->execute([
':id_dep' => $idDep,
':cas_login' => $casLogin
]);
/* (4) Manage execution error */
if( !$success )
return FALSE;
/* (7) Return That it exists */
return is_array( $st->fetch() );
}
/* (6) Associates a professor to a department
*
* @casLogin<String> The professor's CAS username
* @idDep<int> The department id
*
* @return linked<bool> Whether the link have been created
*
---------------------------------------------------------*/
public function link(String $casLogin, int $idDep) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare("INSERT INTO meta_vhost.linkedDep(departement_iddepartement, casUser_casLogin)
VALUES(:id_dep, :cas_login);");
/* (2) Manage statement error */
if( is_bool($st) )
return FALSE;
/* (3) Try to execute request */
$success = $st->execute([
':id_dep' => $idDep,
':cas_login' => $casLogin
]);
/* (4) Dispatch execution error */
return $success;
}
/* (7) Remove a department from a professor
*
* @casLogin<String> The professor's CAS username
* @idDep<int> The department id
*
* @return unlinked<bool> Whether the link have been removed
*
---------------------------------------------------------*/
public function unlink(String $casLogin, int $idDep) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare("DELETE FROM meta_vhost.linkedDep
WHERE departement_iddepartement = :id_dep
AND casUser_casLogin = :cas_login;");
/* (2) Manage statement error */
if( is_bool($st) )
return FALSE;
/* (3) Try to execute request */
$success = $st->execute([
':id_dep' => $idDep,
':cas_login' => $casLogin
]);
/* (4) Dispatch execution error */
return $success;
}
public function deleteVersion(int $version) : bool{
//get version data
$st = $this->pdo->prepare("SELECT * FROM meta_vhost.`databases` WHERE iddatabase = :id");
$st->execute(["id" => $version]);
$versionData = $st->fetch();
if( !is_array($versionData) || $versionData["default"] == 1){
return false;
}
//delete database
$versionDatabase = $versionData['dbName'];
$this->pdo->exec("DROP DATABASE $versionDatabase;");
//remove from meta
$st = $this->pdo->prepare("DELETE FROM meta_vhost.`databases` WHERE iddatabase = :id");
return $st->execute(["id" => $version]);
}
public function createVersion(String $label, String $dbName, int $depId, bool $isDefault = false) : int{
$st = $this->pdo->prepare("INSERT INTO meta_vhost.`databases`(label, dbName, `default`, departement_iddepartement)
VALUE (:label,:dbName,:default,:depId)");
$st->execute([
"label" => $label,
"dbName" => $dbName,
"default" => $isDefault? 1 : 0,
"depId" => $depId
]);
return $this->pdo->lastInsertId();
}
public function getVersionById(int $id) : array{
$st = $this->pdo->prepare("SELECT * FROM meta_vhost.`databases` WHERE iddatabase = :idVersion");
$st->execute(["idVersion" => $id]);
$fetched = $st->fetch();
return $fetched == false ? [] : $fetched;
}
public function getAllVersions(int $idDep) : array {
$st = $this->pdo->prepare("SELECT * FROM meta_vhost.`databases` WHERE departement_iddepartement = :idDep");
$st->execute(["idDep" => $idDep]);
return $st->fetchAll();
}
public function updateVersion(int $version, ?String $label, ?bool $default) : bool{
//you can't un-default a version, you have to choose another version to be the default one
if($default == false){
return false;
}
$set = "";
$execute = [];
if($label != null){
$set .= "label=:label,";
$execute["label"] = $label;
}
if($default != null){
$set .= "`default`=:default,";
$execute["default"] = $default?1:0;
//if default = true, set previous default version to non-default
if($default == true){
$req = $this->pdo->prepare("UPDATE meta_vhost.`databases` SET `default`=0 WHERE departement_iddepartement=:idDep");
$req->execute(["idDep" => $_SESSION['CurrentDepartmentId']]);
}
}
$set = rtrim($set,",");
$execute["idVersion"] = $version;
$st = $this->pdo->prepare("UPDATE meta_vhost.`databases` SET $set WHERE iddatabase=:idVersion");
return $st->execute($execute);
}
public function createDepartment(String $name) : int{
$st = $this->pdo->prepare("INSERT INTO meta_vhost.departement(label) VALUE (:label)");
$st->execute(["label" => $name]);
return $this->pdo->lastInsertId();
}
}

View File

@ -0,0 +1,570 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 20/02/18
* Time: 20:31
*/
namespace database\repo;
use database\core\Repo_i;
use database\core\Repo;
class professor extends Repo_i {
/* (1) Creates a new professor
*
* @lastName<String> The professor's lastName
* @firstName<String> The professor's firstName
* @category<int> The professor's category ID
* @hoursToDo<int> The professor's number of hours to do
* @initials<int> The professor's initials
* @isAdmin<bool> Whether the professor is an admin
* @casLogin<String> The professor's CAS username
*
* @return prof_id<int> The professor's UID (or -1 on error)
*
---------------------------------------------------------*/
public function create(string $lastName, string $firstName, int $category, int $hoursToDo = 0, ?string $initials = null , bool $isAdmin = false , ?string $casLogin = null ) : ?int{
/* (1) Create professor into local database
---------------------------------------------------------*/
/* (1) Prepare Statement */
$st = $this->pdo->prepare("INSERT INTO
Professeur(`casLogin`, `lastName`, `firstName`, `abreviation`, `admin`, `hoursToDo`, `Categorie_idCategorie`)
VALUE (:casLogin, :lastName, :firstName, :abrev, :is_admin, :hoursToDo, :cat);");
/* (2) Manage statement error */
if( is_bool($st) )
return NULL;
/* (3) Bind params and execute */
$success = $st->execute([
':casLogin' => $casLogin,
':lastName' => $lastName,
':firstName' => $firstName,
':abrev' => $initials,
':is_admin' => $isAdmin ? 1 : 0,
':hoursToDo' => $hoursToDo,
':cat' => $category
]);
/* (4) If execution error -> dispatch */
if( !$success )
return NULL;
/* (5) Store id */
$id_prof = $this->pdo->lastInsertId();
/* (6) Exit now if no meta database to udpate */
if( is_null($casLogin) )
return $id_prof;
/* (2) Synchronize meta database
---------------------------------------------------------*/
/** @var meta $meta_repo */
$meta_repo = Repo::getRepo('meta');
/* (1) If user does not exist */
if( !$meta_repo->prof_exists($casLogin) ){
/* (2) Try to create -> dispatch error */
if( !$meta_repo->create_prof($casLogin, $firstName, $lastName) )
return NULL;
}
/* (3) If link already exists -> done */
if( $meta_repo->link_exists($casLogin, $_SESSION['CurrentDepartmentId']) )
return $id_prof;
/* (4) Else: try to link prof to dep -> dispatch error */
if( !$meta_repo->link($casLogin, $_SESSION['CurrentDepartmentId']) )
return NULL;
/* (5) If reached here -> Success */
return $id_prof;
}
/* (2) Check if a professor exists (by its names)
*
* @lastName<String> The professor's lastName
* @firstName<String> The professor's firstName
*
* @return prof_id<int> The professor's UID (or NULL on error)
*
---------------------------------------------------------*/
public function exists(string $lastName, string $firstName, ?string $casLogin = null) : ?int{
/* (1) Manage if @casLogin given/ignored */
$cond = is_null($casLogin) ? '' : 'OR `casLogin` = :casLogin';
$parm = is_null($casLogin) ? [] : [':casLogin' => $casLogin];
/* (2) Prepare Statement */
$st = $this->pdo->prepare("SELECT idProfesseur
FROM Professeur
WHERE ( firstName = :firstName AND lastName = :lastName )
$cond;");
/* (3) Statement eror */
if( is_bool($st) )
return NULL;
/* (4) Bind params and execute */
$params = array_merge([
':firstName' => $firstName,
':lastName' => $lastName
], $parm);
$success = $st->execute($params);
/* (5) Return NULL on error */
if( !$success )
return NULL;
/* (7) Return @prof_id or NULL if nothing found */
return $st->fetch()['idProfesseur'] ?: NULL;
}
/* (3) Updates a professor's data
*
* @idProf<int> The professor's UID
* @lastName<String> [OPT] The professor's new lastName
* @firstName<String> [OPT] The professor's new firstName
* @category<int> [OPT] The professor's new category ID
* @hoursToDo<int> [OPT] The professor's new number of hours to do
* @initials<int> [OPT] The professor's new initials
* @isAdmin<bool> [OPT] Whether the professor is an admin
* @casLogin<String> [OPT] The professor's new CAS username
*
* @return updated<bool> Whether the updated have been successful
*
---------------------------------------------------------*/
public function update(int $id, ?String $lastName, ?String $firstName, ?int $category, ?int $hoursToDo, ?String $initials, ?bool $isAdmin, ?String $casLogin) : bool{
/* (1) Check professor data
---------------------------------------------------------*/
/* (1) Try to fetch professor's data */
$prof = $this->get($id);
/* (2) Error: no professor found */
if( count($prof) === 0 )
return FALSE;
/* (3) Take first matching professor */
$prof = $prof[0];
/* (4) Extract old CAS login */
$oldCasLogin = $prof['casLogin'];
/* (2) Update current database
---------------------------------------------------------*/
/* (1) Build request */
$build_rq = [];
$bind_param = [ ':idProfesseur' => $id ];
if( !is_null($lastName) ){ $build_rq[] = '`lastName` = :lastName'; $bind_param[':lastName'] = $lastName; }
if( !is_null($firstName) ){ $build_rq[] = '`firstName` = :firstName'; $bind_param[':firstName'] = $firstName; }
if( !is_null($category) ){ $build_rq[] = '`Categorie_idCategorie` = :category'; $bind_param[':category'] = $category; }
if( !is_null($hoursToDo) ){ $build_rq[] = '`hoursToDo` = :hoursToDo'; $bind_param[':hoursToDo'] = $hoursToDo; }
if( !is_null($initials) ){ $build_rq[] = '`abreviation` = :initials'; $bind_param[':initials'] = $initials; }
if( !is_null($isAdmin) ){ $build_rq[] = '`admin` = :isAdmin'; $bind_param[':isAdmin'] = $isAdmin?1:0; }
if( !is_null($casLogin) ){ $build_rq[] = '`casLogin` = :casLogin'; $bind_param[':casLogin'] = $casLogin; }
/* (2) ERROR if no updated field */
if( count($build_rq) <= 0 || count($bind_param) <= 1 )
return FALSE;
/* (3) Build request */
$sql_rq = "UPDATE `Professeur` SET ".implode(', ', $build_rq)." WHERE `idProfesseur` = :idProfesseur";
/* (4) Prepare statement */
$st = $this->pdo->prepare($sql_rq);
/* (5) Return execution success */
$success = $st->execute($bind_param);
/* (6) Manage execution error */
if( !$success )
return FALSE;
/* (7) If do not have to update 'meta' database -> success */
if( is_null($casLogin) )
return TRUE;
/** @var meta $meta_repo */
$meta_repo = Repo::getRepo('meta');
/* (3) Synchronize meta database -> remove old value
---------------------------------------------------------*/
if( !is_null($oldCasLogin) && strlen($oldCasLogin) > 0 ){
/* Proccess only if professor exists */
if( $meta_repo->prof_exists($oldCasLogin) ){
/* (1) If link exists -> remove it */
if( $meta_repo->link_exists($oldCasLogin, $_SESSION['CurrentDepartmentId']) ){
/* (2) Try to unlink-> ignore error */
$meta_repo->unlink($oldCasLogin, $_SESSION['CurrentDepartmentId']);
}
/* (3) If has no more department -> remove professor */
if( count( $meta_repo->get_prof_departments($oldCasLogin) ) == 0 ){
/* (4) Try to remove professor -> dispatch error */
if( !$meta_repo->delete_prof($oldCasLogin) )
return FALSE;
}
}
}
/* (4) Synchronize meta database -> create new
---------------------------------------------------------*/
if( !is_null($casLogin) && strlen($casLogin) > 0 ){
/* (1) If user does not exist */
if( !$meta_repo->prof_exists($casLogin) ){
/* (2) Try to create -> dispatch error */
if( !$meta_repo->create_prof($casLogin, $prof['firstName'], $prof['lastName']) )
return FALSE;
}
/* (3) If link already exists -> done */
if( $meta_repo->link_exists($casLogin, $_SESSION['CurrentDepartmentId']) )
return TRUE;
/* (4) Else: try to link prof to dep -> dispatch error */
if( !$meta_repo->link($casLogin, $_SESSION['CurrentDepartmentId']) )
return FALSE;
}
/* (5) If reached here -> Success */
return TRUE;
}
/* (4) Return whether a professor is an admin
*
* @idProf<int> The professor's UID
*
* @return is_admin<bool> Whether the professor is an admin (FALSE if does not exist)
*
---------------------------------------------------------*/
public function isAdmin(int $id) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT `admin` FROM `Professeur` WHERE `idProfesseur` = :id AND `admin` = 1");
/* (2) Bind params and execute statement */
$success = $st->execute([ ':id' => $id ]);
/* (3) FALSE on error */
if( !$success )
return FALSE;
/* (4) Return whether we have a result or not */
return $st->fetch() == 1;
}
/* (5) Gets a professor by its UID ||| getAll
*
* @prof_id<int> [OPT] The professor's UID, if not set, getAll()
*
* @return teachers<array> The professors matching id (NULL on error)
*
---------------------------------------------------------*/
public function get(?int $prof_id=null) : array{
/* (1) Manage if no id given */
$cond = is_null($prof_id) ? '' : ' WHERE `idProfesseur` = :id';
$parm = is_null($prof_id) ? [] : [':id' => $prof_id];
/* (2) Prepare Statement */
$st = $this->pdo->prepare("SELECT * FROM `Professeur`$cond ORDER BY firstName, lastName ASC");
/* (3) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute($parm);
/* (4) Manage error */
if( !$success )
return [];
/* (5) Get data */
$fetched = $st->fetchAll();
/* (6) Return [] on no result */
if( $fetched === false )
return [];
/* (7) Return data */
return $fetched;
}
/* (6) Gets a professor by its CAS login
*
* @cas_login<String> The professor's CAS login
*
* @return teacher<array> The professor's data (NULL on error / not found)
*
---------------------------------------------------------*/
public function getByLogin(String $cas_login) : ?array{
/* (1) Prepare Statement */
$st = $this->pdo->prepare("SELECT * FROM `Professeur` WHERE `casLogin` = :cas_login");
/* (2) Check if statement error */
if( is_bool($st) )
return NULL;
/* (3) Bind params and execute statement */
$success = $st->execute([ ':cas_login' => $cas_login ]);
/* (4) Manage error */
if( !$success )
return NULL;
/* (5) Get data */
$fetched = $st->fetch();
/* (6) Return NULL on no result */
if( $fetched === false )
return NULL;
/* (7) Return data */
return $fetched;
}
/* (7) Gets a professor by its UID ||| getAll
*
* @prof_id<int> [OPT] The professor's UID, if not set, getAll()
*
* @return teachers<array> The professors matching id (NULL on error)
*
---------------------------------------------------------*/
public function getWithVH(?int $prof_id=null) : array{
/* (1) Manage if no id given */
$cond = is_null($prof_id) ? '' : 'Prof.idProfesseur = :id AND';
$parm = is_null($prof_id) ? [] : [':id' => $prof_id];
/* (2) Prepare Statement */
$st = $this->pdo->prepare("SELECT
Prof.idProfesseur, Prof.firstName, Prof.lastName, Prof.casLogin, Prof.abreviation, Prof.admin, Prof.hoursToDo,
VHCours, VHTd, VHTp,
Cat.idCategorie idCat,
Cat.labelCategorie categorie
FROM
Professeur Prof,
Categorie Cat,
(SELECT IFNULL(SUM(Cours.volume),0) VHCours, Prof.idProfesseur idProf
FROM Professeur Prof
LEFT JOIN Cours ON Prof.idProfesseur = Cours.Professeur_idProfesseur
LEFT JOIN UE U ON Cours.UE_code = U.code
GROUP BY Prof.idProfesseur, U.disabled
HAVING (U.disabled = 0 OR U.disabled IS NULL)) VHCours,
(SELECT IFNULL(SUM(TD.volume),0) VHTd , Prof.idProfesseur idProf
FROM Professeur Prof
LEFT JOIN TD ON TD.Professeur_idProfesseur = Prof.idProfesseur
LEFT JOIN UE U2 ON TD.UE_code = U2.code
GROUP BY Prof.idProfesseur, U2.disabled
HAVING (U2.disabled = 0 OR U2.disabled IS NULL)) VHTd,
(SELECT IFNULL(SUM(TP.volume),0) VHTp, Prof.idProfesseur idProf
FROM Professeur Prof
LEFT JOIN TP ON TP.Professeur_idProfesseur = Prof.idProfesseur
LEFT JOIN UE U3 ON TP.UE_code = U3.code
GROUP BY Prof.idProfesseur, U3.disabled
HAVING (U3.disabled = 0 OR U3.disabled IS NULL)) VHTp
WHERE $cond Prof.Categorie_idCategorie = Cat.idCategorie
AND VHCours.idProf = Prof.idProfesseur
AND VHTp.idProf = Prof.idProfesseur
AND VHTd.idProf = Prof.idProfesseur
GROUP BY
Prof.idProfesseur
ORDER BY Prof.firstName, Prof.lastName ASC;");
/* (3) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute($parm);
/* (4) Manage error */
if( !$success )
return [];
/* (5) Get data */
$fetched = $st->fetchAll();
/* (6) Return [] on no result */
if( $fetched === false )
return [];
/* (7) Compute additional data */
foreach ($fetched as &$prof){
/* (1) If not in category 1 nor 3 -> equivalentTD = TD + 2/3.TP + 1.5.COURS */
if(in_array($prof["idCat"],[1,3])){
$prof["equiTD"] = $prof["VHTd"] + $prof["VHTp"] + 1.5*$prof["VHCours"];
if($prof["equiTD"] > $prof["hoursToDo"]){
$partTP = $prof["VHTp"] / $prof["equiTD"];
$valReelleTP = $partTP * $prof["hoursToDo"];
$prof["equiTD"] = round(1.5*$prof["VHCours"] + $prof["VHTd"] + $valReelleTP + ($prof["VHTp"] - $valReelleTP)*(2/3),2);
}
$prof['VHComp'] = round($prof['equiTD'] - $prof['hoursToDo'], 2);
$prof['VHComp'] = ( $prof['VHComp'] < 0 ) ? 0 : $prof['VHComp'];
}else{
$prof["equiTD"] = $prof["VHTd"] + (2/3)*$prof["VHTp"] + 1.5*$prof["VHCours"];
if(is_numeric($prof["hoursToDo"]) and $prof["hoursToDo"] > 0){
$prof['VHComp'] = round($prof['equiTD'] - $prof['hoursToDo'], 2);
$prof['VHComp'] = ( $prof['VHComp'] < 0 ) ? 0 : $prof['VHComp'];
}else{
$prof['VHComp'] = 0;
}
}
}
/* (8) Return data */
return $fetched;
}
/* (8) Deletes a professor
*
* @return deleted<bool> Whether the professor have been deleeted successfully
*
---------------------------------------------------------*/
public function delete(int $id) : bool{
/** @var meta $meta_repo */
$meta_repo = Repo::getRepo('meta');
/* (1) Try to fetch professor data
---------------------------------------------------------*/
/* (1) Try to fetch */
$prof = $this->get($id);
/* (2) Error: if not found */
if( count($prof) === 0 )
return false;
/* (3) Take first matching professor */
$prof = $prof[0];
/* (4) Extract @casLogin */
$casLogin = $prof['casLogin'];
/* (2) Remove professor from current database
---------------------------------------------------------*/
/* (1) Prepare statement */
$st = $this->pdo->prepare("DELETE FROM `Professeur` WHERE `idProfesseur` = :id");
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Return the execution status */
$success = $st->execute([ ':id' => $id ]);
/* (4) Error: on execution error */
if( !$success )
return false;
/* (5) Success if no @casLogin to update in meta */
if( !$meta_repo->prof_exists($casLogin) )
return TRUE;
/* (3) Synchronize meta database
---------------------------------------------------------*/
/* Proccess only if professor exists */
if( $meta_repo->prof_exists($casLogin) ){
/* (1) If link exists -> remove it */
if( $meta_repo->link_exists($casLogin, $_SESSION['CurrentDepartmentId']) ){
/* (2) Try to unlink-> ignore error */
$meta_repo->unlink($casLogin, $_SESSION['CurrentDepartmentId']);
}
/* (3) If has no more department -> remove professor */
if( count( $meta_repo->get_prof_departments($casLogin) ) == 0 ){
/* (4) Try to remove professor -> dispatch error */
if( !$meta_repo->delete_prof($casLogin) )
return FALSE;
}
}
return TRUE;
}
}

294
build/database/repo/td.php Normal file
View File

@ -0,0 +1,294 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 22/02/18
* Time: 13:27
*/
namespace database\repo;
use database\core\Repo_i;
class td extends Repo_i {
/* (1) Create a new TD
*
* @code<String> The code of the UE containing the TD
* @idProf<String> [OPT] The ID of the prof who teaches the TD
* @volume<float> The number of hours (float)
* @formations<array> The list of formations for that TD (list of int)
* @return created_code<String> Code of the created UE (NULL on error)
*
* @return created_id<int> UID of the created TD (NULL on error)
*
---------------------------------------------------------*/
public function create(string $code, ?int $idProf, float $volume, array $formations) : ?int{
/* (1) Prepare statement */
$st = $this->pdo->prepare('INSERT INTO TD(UE_code, Professeur_idProfesseur, volume)
VALUE(:UE, :idProf, :vol)');
/* (2) Manage statement error */
if( is_bool($st) )
return NULL;
/* (3) Try to execute request */
$success = $st->execute([
':UE' => $code,
':idProf' => $idProf,
':vol' => $volume
]);
/* (4) Manage error */
if( !$success )
return NULL;
/* (5) Store @created_id */
$created_id = (int) $this->pdo->lastInsertId();
/* (6) We are done if there is no formations */
if( count($formations) <= 0)
return $created_id;
/* (7) Else -> create each formation */
foreach($formations as $form_id){
// 1. Ignore if wrong format
if( !is_int($form_id) || $form_id < 0 )
continue;
// 2. Link formation to created TD
$this->linkFormation($form_id, $created_id);
}
/* (7) Return @created_id */
return $created_id;
}
/* (2) Unlink a formation from a TD
*
* @idFormation<int> Id of the formation
* @idTD<int> Id of the TD
*
* @return unlinked<bool> Whether it has been unlinked
*
---------------------------------------------------------*/
public function unlinkFormation(int $idFormation, int $idTD) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare('DELETE FROM GroupeTD WHERE TD_idTD = :td AND Formation_idFormation = :form');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) EXecute and dispatch status */
return $st->execute([
':td' => $idTD,
':form' => $idFormation
]);
}
/* (3) Link a formation to a TD
*
* @idFormation<int> Id of the formation
* @idTD<int> Id of the TD
*
* @return linked<bool> Whether it has been linked
*
---------------------------------------------------------*/
public function linkFormation(int $idFormation, int $idTD) : bool{
/* (1) Try to remove first if it already exists */
$this->unlinkFormation($idFormation, $idTD);
/* (2) Prepare statement */
$st = $this->pdo->prepare('INSERT INTO GroupeTD(TD_idTD,Formation_idFormation)
VALUE(:td, :form)');
/* (3) Manage statement error */
if( is_bool($st) )
return false;
/* (4) EXecute and dispatch status */
return $st->execute([
':td' => $idTD,
':form' => $idFormation
]);
}
/* (4.1) Updates an existing TD
*
* @idTD<int> Id of the TD
* @idProf<int> [OPT] Id of the prof (NULL to set to NULL)
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public function updateProf(int $idTD, ?int $idProf) : bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare('UPDATE TD
SET Professeur_idProfesseur = :idProf
WHERE idTD = :idTD');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':idTD' => $idTD, ':idProf' => $idProf ]);
}
/* (4.2) Updates an existing TD
*
* @idTD<int> Id of the TD
* @volume<float> [OPT] The new number of hours
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public function updateVolume(int $idTD, float $volume) : bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare('UPDATE TD
SET volume = :volume
WHERE idTD = :idTD');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':idTD' => $idTD, ':volume' => $volume ]);
}
/* (5) Deletes an existing td
*
* @idTD<int> Id of the TD
*
* @return deleted<bool> Whether it has been deleted
*
---------------------------------------------------------*/
public function delete(int $id) :bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare("DELETE FROM TD WHERE idTD = :id");
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':id' => $id ]);
}
/* (x) Get groups for a specific UE
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
* NULL on error
*
---------------------------------------------------------*/
public function getGroups(String $code) : ?array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT
c.UE_code code,
c.idTD,
p.idProfesseur idProf,
p.firstName,
p.lastName,
IFNULL(lform.flist, '[]') formations,
c.volume
FROM TD c
LEFT JOIN ( SELECT gc.TD_idTD idTD, CONCAT('[', GROUP_CONCAT(DISTINCT gc.Formation_idFormation),']') flist
FROM GroupeTD gc
GROUP BY gc.TD_idTD
ORDER BY gc.Formation_idFormation DESC
) lform ON c.idTD = lform.idTD
LEFT JOIN Professeur p ON p.idProfesseur = c.Professeur_idProfesseur
WHERE c.UE_code = :code;");
/* (2) Check statement */
if( is_bool($st) )
return NULL;
/* (3) Execute statement */
$success = $st->execute([':code' => $code]);
/* (4) Check error */
if( !$success )
return NULL;
/* (5) Dispatch fetch result */
return $st->fetchAll();
}
/* (7) Get groups for a specific Professor
*
* @prof_id<int> Professor ID
*
* @return groups<array> The list of groups for this Professor
* NULL on error
*
---------------------------------------------------------*/
public function getForProfessor(int $prof_id) : ?array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT
td.UE_code code,
ue.label label,
td.idTD,
IFNULL(lform.flist, '[]') formations,
td.volume
FROM TD td
LEFT JOIN ( SELECT gtd.TD_idTD idTD, CONCAT('[', GROUP_CONCAT(DISTINCT gtd.Formation_idFormation),']') flist
FROM GroupeTD gtd
GROUP BY gtd.TD_idTD
ORDER BY gtd.Formation_idFormation DESC
) lform ON td.idTD = lform.idTD
JOIN UE ue ON ue.code = td.UE_code
WHERE td.Professeur_idProfesseur = :prof_id;");
/* (2) Check statement */
if( is_bool($st) )
return NULL;
/* (3) Execute statement */
$success = $st->execute([':prof_id' => $prof_id]);
/* (4) Check error */
if( !$success )
return NULL;
/* (5) Dispatch fetch result */
return $st->fetchAll();
}
}

294
build/database/repo/tp.php Normal file
View File

@ -0,0 +1,294 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 22/02/18
* Time: 13:27
*/
namespace database\repo;
use database\core\Repo_i;
class tp extends Repo_i {
/* (1) Create a new TP
*
* @code<String> The code of the UE containing the TP
* @idProf<String> [OPT] The ID of the prof who teaches the TP
* @volume<float> The number of hours (float)
* @formations<array> The list of formations for that TP (list of int)
* @return created_code<String> Code of the created UE (NULL on error)
*
* @return created_id<int> UID of the created TP (NULL on error)
*
---------------------------------------------------------*/
public function create(string $code, ?int $idProf, float $volume, array $formations) : ?int{
/* (1) Prepare statement */
$st = $this->pdo->prepare('INSERT INTO TP(UE_code, Professeur_idProfesseur, volume)
VALUE(:UE, :idProf, :vol)');
/* (2) Manage statement error */
if( is_bool($st) )
return NULL;
/* (3) Try to execute request */
$success = $st->execute([
':UE' => $code,
':idProf' => $idProf,
':vol' => $volume
]);
/* (4) Manage error */
if( !$success )
return NULL;
/* (5) Store @created_id */
$created_id = (int) $this->pdo->lastInsertId();
/* (6) We are done if there is no formations */
if( count($formations) <= 0)
return $created_id;
/* (7) Else -> create each formation */
foreach($formations as $form_id){
// 1. Ignore if wrong format
if( !is_int($form_id) || $form_id < 0 )
continue;
// 2. Link formation to created TP
$this->linkFormation($form_id, $created_id);
}
/* (7) Return @created_id */
return $created_id;
}
/* (2) Unlink a formation from a TP
*
* @idFormation<int> Id of the formation
* @idTP<int> Id of the TP
*
* @return unlinked<bool> Whether it has been unlinked
*
---------------------------------------------------------*/
public function unlinkFormation(int $idFormation, int $idTP) : bool{
/* (1) Prepare statement */
$st = $this->pdo->prepare('DELETE FROM GroupeTP WHERE TP_idTP = :tp AND Formation_idFormation = :form');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) EXecute and dispatch status */
return $st->execute([
':tp' => $idTP,
':form' => $idFormation
]);
}
/* (3) Link a formation to a TP
*
* @idFormation<int> Id of the formation
* @idTP<int> Id of the TP
*
* @return linked<bool> Whether it has been linked
*
---------------------------------------------------------*/
public function linkFormation(int $idFormation, int $idTP) : bool{
/* (1) Try to remove first if it already exists */
$this->unlinkFormation($idFormation, $idTP);
/* (2) Prepare statement */
$st = $this->pdo->prepare('INSERT INTO GroupeTP(TP_idTP,Formation_idFormation)
VALUE(:tp, :form)');
/* (3) Manage statement error */
if( is_bool($st) )
return false;
/* (4) EXecute and dispatch status */
return $st->execute([
':tp' => $idTP,
':form' => $idFormation
]);
}
/* (4.1) Updates an existing TP
*
* @idTP<int> Id of the TP
* @idProf<int> [OPT] Id of the prof (NULL to set to NULL)
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public function updateProf(int $idTP, ?int $idProf) : bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare('UPDATE TP
SET Professeur_idProfesseur = :idProf
WHERE idTP = :idTP');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':idTP' => $idTP, ':idProf' => $idProf ]);
}
/* (4.2) Updates an existing TP
*
* @idTP<int> Id of the TP
* @volume<float> [OPT] The new number of hours
*
* @return updated<bool> Whether it has been updated
*
---------------------------------------------------------*/
public function updateVolume(int $idTP, float $volume) : bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare('UPDATE TP
SET volume = :volume
WHERE idTP = :idTP');
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':idTP' => $idTP, ':volume' => $volume ]);
}
/* (5) Deletes an existing tp
*
* @idTP<int> Id of the TP
*
* @return deleted<bool> Whether it has been deleted
*
---------------------------------------------------------*/
public function delete(int $id) :bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare("DELETE FROM TP WHERE idTP = :id");
/* (2) Manage statement error */
if( is_bool($st) )
return false;
/* (3) Execute and dispatch status */
return $st->execute([ ':id' => $id ]);
}
/* (x) Get groups for a specific UE
*
* @code<String> UE code
*
* @return groups<array> The list of groups for this UE
* NULL on error
*
---------------------------------------------------------*/
public function getGroups(String $code) : ?array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT
c.UE_code code,
c.idTP,
p.idProfesseur idProf,
p.firstName,
p.lastName,
IFNULL(lform.flist, '[]') formations,
c.volume
FROM TP c
LEFT JOIN ( SELECT gc.TP_idTP idTP, CONCAT('[', GROUP_CONCAT(DISTINCT gc.Formation_idFormation),']') flist
FROM GroupeTP gc
GROUP BY gc.TP_idTP
ORDER BY gc.Formation_idFormation DESC
) lform ON c.idTP = lform.idTP
LEFT JOIN Professeur p ON p.idProfesseur = c.Professeur_idProfesseur
WHERE c.UE_code = :code;");
/* (2) Check statement */
if( is_bool($st) )
return NULL;
/* (3) Execute statement */
$success = $st->execute([':code' => $code]);
/* (4) Check error */
if( !$success )
return NULL;
/* (5) Dispatch fetch result */
return $st->fetchAll();
}
/* (7) Get groups for a specific Professor
*
* @prof_id<int> Professor ID
*
* @return groups<array> The list of groups for this Professor
* NULL on error
*
---------------------------------------------------------*/
public function getForProfessor(int $prof_id) : ?array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT
tp.UE_code code,
ue.label label,
tp.idTP,
IFNULL(lform.flist, '[]') formations,
tp.volume
FROM TP tp
LEFT JOIN ( SELECT gtp.TP_idTP idTP, CONCAT('[', GROUP_CONCAT(DISTINCT gtp.Formation_idFormation),']') flist
FROM GroupeTP gtp
GROUP BY gtp.TP_idTP
ORDER BY gtp.Formation_idFormation DESC
) lform ON tp.idTP = lform.idTP
JOIN UE ue ON ue.code = tp.UE_code
WHERE tp.Professeur_idProfesseur = :prof_id;");
/* (2) Check statement */
if( is_bool($st) )
return NULL;
/* (3) Execute statement */
$success = $st->execute([':prof_id' => $prof_id]);
/* (4) Check error */
if( !$success )
return NULL;
/* (5) Dispatch fetch result */
return $st->fetchAll();
}
}

302
build/database/repo/ue.php Normal file
View File

@ -0,0 +1,302 @@
<?php
/**
* Created by PhpStorm.
* User: lucas
* Date: 20/02/18
* Time: 20:30
*/
namespace database\repo;
use database\core\Repo_i;
class ue extends Repo_i {
/* (1) Create a new UE
*
* @code<String> The code of the UE
* @label<String> The UE label (name)
* @required<bool> If the UE is required
* @volumeCours<float> The UE required volume of COURSES
* @volumeTD<float> The UE required volume of TD
* @volumeTP<float> The UE required volume of TP
* @disabled<bool> [OPT] If it is disabled
* @defaultFormation<int> [OPT] If there is a foreign key for a default formation (if only one formation)
*
* @return created_code<String> Code of the created UE (NULL on error)
*
---------------------------------------------------------*/
public function create(string $code, string $label, bool $required, float $volumeCours, float $volumeTD, float $volumeTP, bool $disabled = false, ?int $defaultFormation = null) : ?string {
/* (1) Prepare request */
$st = $this->pdo->prepare("INSERT INTO UE(`code`, `label`, `required`, `volumeCours`, `volumeTD`, `volumeTP`, `disabled`, `Formation_idFormation`)
VALUE(:code, :label, :required, :volCours, :volTD, :volTP, :disabled, :idFormation) ");
/* (2) Manage statement error */
if( $st === false )
return null;
/* (3) Bind params and execute request */
$success = $st->execute([
':code' => $code,
':label' => $label,
':required' => $required ? 1 : 0,
':volCours' => $volumeCours,
':volTD' => $volumeTD,
':volTP' => $volumeTP,
':disabled' => $disabled ? 1 : 0,
':idFormation' => $defaultFormation
]);
/* (4) Manage execution error */
if( !$success )
return null;
/* (5) Return insert id */
return $code;
}
/* (2) Updates an UE data
*
* @code<String> The UE code
* @new_code<String> [OPT] The new UE code
* @label<String> [OPT] The UE's new label
* @required<bool> [OPT] Whether the UE is required
* @volumeCours<float> [OPT] The UE's new volume of COURSES
* @volumeTD<float> [OPT] The UE's new volume of TD
* @volumeTP<float> [OPT] The UE's new volume of TP
* @disabled<bool> [OPT] Whether the UE is disabled
* @defaultFormation<int> [OPT] The default formation foreign key (-1 to unset)
*
* @return updated<bool> Whether the update have been successful
*
---------------------------------------------------------*/
public function update(string $code, ?String $new_code, ?String $label, ?bool $required, ?float $volumeCours, ?float $volumeTD, ?float $volumeTP, ?bool $disabled, ?int $defaultFormation) : bool{
/* (1) Build request */
$build_rq = [];
$bind_param = [ ':code' => $code ];
if( !is_null($new_code) ){ $build_rq[] = '`code` = :new_code'; $bind_param[':new_code'] = $new_code; }
if( !is_null($label) ){ $build_rq[] = '`label` = :label'; $bind_param[':label'] = $label; }
if( !is_null($required) ){ $build_rq[] = '`required` = :required'; $bind_param[':required'] = $required?1:0; }
if( !is_null($volumeCours) ){ $build_rq[] = '`volumeCours` = :volumeCours'; $bind_param[':volumeCours'] = $volumeCours; }
if( !is_null($volumeTD) ){ $build_rq[] = '`volumeTD` = :volumeTD'; $bind_param[':volumeTD'] = $volumeTD; }
if( !is_null($volumeTP) ){ $build_rq[] = '`volumeTP` = :volumeTP'; $bind_param[':volumeTP'] = $volumeTP; }
if( !is_null($disabled) ){ $build_rq[] = '`disabled` = :disabled'; $bind_param[':disabled'] = $disabled?1:0; }
// not null @defaultFormation -> set it
if( !is_null($defaultFormation) ){
// if @defaultFormation is (-1) -> unset
if( $defaultFormation < 0 ){ $build_rq[] = '`Formation_idFormation` = NULL'; }
// else -> set to new value
else{ $build_rq[] = '`Formation_idFormation` = :defaultFormation'; $bind_param[':defaultFormation'] = $defaultFormation; }
}
/* (2) ERROR if no updated field */
if( count($build_rq) <= 0 )
return FALSE;
/* (3) Build request */
$sql_rq = "UPDATE `UE` SET ".implode(', ', $build_rq)." WHERE `code` = :code";
/* (4) Prepare statement */
$st = $this->pdo->prepare($sql_rq);
/* (5) Return execution success */
return $st->execute($bind_param);
}
/* (3) Deletes an UE
*
* @code<String> The UE code
*
* @return deleted<bool> Whether the UE have been deleeted successfully
*
---------------------------------------------------------*/
public function delete(string $code) : bool {
/* (1) Prepare statement */
$st = $this->pdo->prepare('DELETE FROM UE WHERE code = :code');
/* (2) Manage error */
if( $st === false )
return false;
/* (3) Bind params and execute request */
return $st->execute([ ':code' => $code ]);
}
/* (4) Disables an UE
*
* @code<String> The UE code
*
* @return disabled<bool> Whether the UE have been disabled successfully
*
---------------------------------------------------------*/
public function disable(string $code) : bool {
return $this->update($code, null, null, null, null, null, true, null);
}
/* (5) Enables an UE
*
* @code<String> The UE code
*
* @return enabled<bool> Whether the UE have been enabled successfully
*
---------------------------------------------------------*/
public function enable(string $code) : bool {
return $this->update($code, null, null, null, null, null, false, null);
}
/* (6) Gets a UE by its code || getAll
*
* @code<String> [OPT] The UE code, if not set, getAll()
*
* @return ues<array> The UEs matching code (NULL on error)
*
---------------------------------------------------------*/
public function get(?String $code=null) : array{
/* (1) Manage if no id given */
$cond = is_null($code) ? '' : 'HAVING `ue`.`code` = :code';
$parm = is_null($code) ? [] : [':code' => $code];
/* (2) Prepare Statement */
$st = $this->pdo->prepare("
SELECT
ue.code,
ue.label,
ue.disabled,
ue.required,
ue.volumeCours,
ue.volumeTD,
ue.volumeTP,
IFNULL(ue.Formation_idFormation, -1) idForm,
fdef.labelFormation labelForm,
IFNULL(formlist.formations, '[]') formations,
IFNULL(formlist.nbrCours,0) nbrCours,
IFNULL(formlist.nbrTD,0) nbrTD,
IFNULL(formlist.nbrTP,0) nbrTP,
IFNULL(formlist.modCours,0) modCours,
IFNULL(formlist.modTD,0) modTD,
IFNULL(formlist.modTP,0) modTP,
IFNULL(formlist.nbrProfCours,0) nbrProfCours,
IFNULL(formlist.nbrProfTD,0) nbrProfTD,
IFNULL(formlist.nbrProfTP,0) nbrProfTP
FROM UE ue
LEFT JOIN Formation fdef ON ue.Formation_idFormation = fdef.idFormation
LEFT JOIN (
SELECT ue2.code code, CONCAT('[',GROUP_CONCAT(DISTINCT Formation.idFormation), ']') formations,
count(DISTINCT C.idCours) nbrCours, count(DISTINCT T.idTD) nbrTD, count(DISTINCT T2.idTP) nbrTP,
MOD(volC.vol,ue2.volumeCours) modCours,
MOD(volTD.vol,ue2.volumeTD) modTD,
MOD(volTP.vol,ue2.volumeTP) modTP,
count(DISTINCT C.Professeur_idProfesseur,C.idCours) nbrProfCours,
count(DISTINCT T.Professeur_idProfesseur,T.idTD) nbrProfTD,
count(DISTINCT T2.Professeur_idProfesseur,T2.idTP) nbrProfTP
FROM UE ue2
LEFT JOIN (SELECT sum(CO.volume) vol, CO.UE_code FROM Cours CO GROUP BY CO.UE_code) volC ON ue2.code = volC.UE_code
LEFT JOIN (SELECT sum(TD2.volume) vol, TD2.UE_code FROM TD TD2 GROUP BY TD2.UE_code) volTD ON ue2.code = volTD.UE_code
LEFT JOIN (SELECT sum(TP2.volume) vol, TP2.UE_code FROM TP TP2 GROUP BY TP2.UE_code) volTP ON ue2.code = volTP.UE_code
LEFT JOIN Cours C ON ue2.code = C.UE_code
LEFT JOIN TD T ON ue2.code = T.UE_code
LEFT JOIN TP T2 ON ue2.code = T2.UE_code
LEFT JOIN GroupeCours C2 ON C.idCours = C2.Cours_idCours
LEFT JOIN GroupeTD TD2 ON T.idTD = TD2.TD_idTD
LEFT JOIN GroupeTP TP2 ON T2.idTP = TP2.TP_idTP
JOIN Formation ON C2.Formation_idFormation = Formation.idFormation
OR TD2.Formation_idFormation = Formation.idFormation
OR TP2.Formation_idFormation = Formation.idFormation
GROUP BY `ue2`.`code`
) formlist ON formlist.code = ue.code
GROUP BY `ue`.`code`
$cond
ORDER BY `ue`.`label` ASC");
/* (3) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute($parm);
/* (4) Manage error */
if( !$success )
return [];
/* (5) Get data */
$fetched = $st->fetchAll();
/* (6) Return [] on no result */
if( $fetched === false )
return [];
/* (7) Return data */
return $fetched;
}
/* (7) Gets all professors who teaches a UE by code
*
* @code<String> The UE code
*
* @return professors<array> The professors' UID matching the @code of the UE
*
---------------------------------------------------------*/
public function getProfessors(String $code) : array{
/* (1) Prepare statement */
$st = $this->pdo->prepare("SELECT p.idProfesseur
FROM Professeur p, UE u
WHERE (
p.idProfesseur IN ( SELECT p_cr.idProfesseur FROM Professeur p_cr, Cours c WHERE c.Professeur_idProfesseur = p_cr.idProfesseur AND c.UE_code = u.code )
OR p.idProfesseur IN ( SELECT p_td.idProfesseur FROM Professeur p_td, TD t WHERE t.Professeur_idProfesseur = p_td.idProfesseur AND t.UE_code = u.code )
OR p.idProfesseur IN ( SELECT p_tp.idProfesseur FROM Professeur p_tp, TP t WHERE t.Professeur_idProfesseur = p_tp.idProfesseur AND t.UE_code = u.code )
)
AND u.code = :ue_code;");
/* (2) Bind params and execute statement */
if( is_bool($st) ) return [];
$success = $st->execute([ ':ue_code' => $code ]);
/* (3) Manage error */
if( !$success )
return [];
/* (4) Get data */
$fetched = $st->fetchAll();
/* (5) Return [] on no result */
if( $fetched === false )
return [];
/* (6) Return data */
return $fetched;
}
public function exportUE() : array{
$st = $this->pdo->prepare("SELECT * FROM UE
LEFT JOIN Formation
ON UE.Formation_idFormation = Formation.idFormation
ORDER BY Formation_idFormation IS NULL DESC, Formation_idFormation ASC");
$st->execute();
return $st->fetchAll();
}
}

View File

@ -1,250 +0,0 @@
<?php
namespace database\repo;
use \database\core\Repo_i;
class user extends Repo_i{
/* (1) Return all users in database
*
* @return users<array> The user list
* FALSE on error
*
---------------------------------------------------------*/
public function getAll(){
/* (1) Statement */
$st = $this->pdo->query("SELECT * FROM `user` ORDER BY `username` ASC");
/* (2) Fetched data */
return $st->fetchAll();
}
/* (2) Return a user by its `id_user`
*
* @id_user<int> The user UID
*
* @return user<array> The user if found
* FALSE on error
*
---------------------------------------------------------*/
public function getById(int $id_user){
/* (1) Prepare Statement */
$pst = $this->pdo->prepare("SELECT * FROM `user` WHERE `id_user` = :id_user LIMIT 1");
/* (2) Bind variables */
$pst->bindParam(':id_user', $id_user, \PDO::PARAM_INT);
/* (3) Execute */
if( !$pst->execute() ) return false; // if error -> send FALSE
/* (4) Fetched data */
return $pst->fetch();
}
/* (3) Return a user by its `mail`
*
* @mail<String> The user mail address
*
* @return user<array> The user if found
* FALSE on error
*
---------------------------------------------------------*/
public function getByMail(String $mail){
/* (1) Prepare Statement */
$pst = $this->pdo->prepare("SELECT * FROM `user` WHERE `mail` = :mail LIMIT 1");
/* (2) Bind variables */
$pst->bindParam(':mail', $mail, \PDO::PARAM_STR, 50);
/* (3) Execute */
if( !$pst->execute() ) return false; // if error -> send FALSE
/* (4) Fetched data */
return $pst->fetch();
}
/* (4) Return a user by its `username`
*
* @username<String> The user username
*
* @return user<array> The user if found
* FALSE on error
*
---------------------------------------------------------*/
public function getByUsername(String $username){
/* (1) Prepare Statement */
$pst = $this->pdo->prepare("SELECT * FROM `user` WHERE `username` = :username LIMIT 1");
/* (2) Bind variables */
$pst->bindParam(':username', $username, \PDO::PARAM_STR, 20);
/* (3) Execute */
if( !$pst->execute() ) return false; // if error -> send FALSE
/* (4) Fetched data */
return $pst->fetch();
}
/* (5) Return a user by its `token`
*
* @token<String> The user token
*
* @return user<array> The user if found
* FALSE on error
*
---------------------------------------------------------*/
public function getByToken(String $token){
/* (1) Prepare Statement */
$pst = $this->pdo->prepare("SELECT * FROM `user` WHERE `token` is not NULL AND `token` = :token LIMIT 1");
/* (2) Bind variables */
$pst->bindParam(':token', $token, \PDO::PARAM_STR, 128);
/* (3) Execute */
if( !$pst->execute() ) return false; // if error -> send FALSE
/* (4) Fetched data */
return $pst->fetch();
}
/* (6) Check the password of a user
*
* @id_user<String> The user UID
* @password<String> The password to test
*
* @return valid<bool> Whether the password is valid or not
*
---------------------------------------------------------*/
public function checkPassword(int $id_user, String $password){
/* (1) Hash the password */
$hash = \secure_hash($password, $id_user, 'user-pass');
/* (2) Prepare Statement */
$pst = $this->pdo->prepare("SELECT * FROM `user` WHERE `id_user` = :id_user AND `pass` = :pass LIMIT 1");
/* (3) Bind variables */
$pst->bindParam(':id_user', $id_user, \PDO::PARAM_INT);
$pst->bindParam(':pass', $hash, \PDO::PARAM_STR, 128);
/* (4) Execute */
if( !$pst->execute() ) return false; // if error -> send FALSE
/* (5) If no data -> means invalid password */
if( !is_array($pst->fetch()) )
return false;
/* (6) If here -> means password is ok */
return true;
}
/* (6) Set the password for a user
*
* @id_user<String> The user UID
* @password<String> The password to set
*
* @return set<bool> Whether the password has been set or not
*
---------------------------------------------------------*/
public function setPassword(int $id_user, String $password){
/* (1) Hash the password */
$hash = \secure_hash($password, $id_user, 'user-pass');
/* (2) Prepare Statement */
$pst = $this->pdo->prepare("UPDATE `user` SET `pass` = :pass WHERE `id_user` = :id_user");
/* (3) Bind variables */
$pst->bindParam(':pass', $hash, \PDO::PARAM_STR, 128);
$pst->bindParam(':id_user', $id_user, \PDO::PARAM_INT);
/* (4) Execute -> dispatch status */
return $pst->execute();
}
/* (7) Creates a new user
*
* @username<String> The username (must be unique)
* @mail<String> The mail address (must be unique)
* @password<String> The password
*
* @return id_created<int> UID of the created user
* FALSE on error
*
---------------------------------------------------------*/
public function create(String $username, String $mail, String $password){
/* (1) Check @username + @mail are unique
---------------------------------------------------------*/
/* (1) If @username already exists -> abort */
if( is_array($this->getByUsername($username)) )
return false;
/* (2) If @mail already exists -> abort */
if( is_array($this->getByMail($mail)) )
return false;
/* (2) Create the user (without password)
---------------------------------------------------------*/
/* (1) Create a random token */
$token = \secure_hash(uniqid(), 'user-token');
/* (2) Prepare Statement */
$pst = $this->pdo->prepare("INSERT INTO `user`(`id_user`, `username`, `mail`, `pass`, `token`) VALUES(DEFAULT, :username, :mail, NULL, :token)");
/* (3) Bind variables */
$pst->bindParam(':username', $username, \PDO::PARAM_STR, 20);
$pst->bindParam(':mail', $mail, \PDO::PARAM_STR, 50);
$pst->bindParam(':token', $token, \PDO::PARAM_STR, 128);
/* (4) Execute -> if error return FALSE */
if( !$pst->execute() ) return false;
/* (2) Set the password (needed @id_user)
---------------------------------------------------------*/
/* (1) Get last inserted id */
$fetch_user = $this->getByUsername($username);
/* (2) If nothing found -> error */
if( !is_array($fetch_user) || !isset($fetch_user['id_user']) || !is_numeric($fetch_user['id_user']) )
return false;
/* (3) Extract @id_user */
$id_user = intval($fetch_user['id_user']);
/* (4) Repo self call */
if( !$this->setPassword($id_user, $password) )
return false;
/* (5) Return @id_user */
return $id_user;
}
}

View File

@ -63,6 +63,17 @@
const WrongParam = 17;
/* (12) Erreur dans le traitement */
const ModuleError = 18;
/* (13) Erreur de format d'URI */
const InvalidURI = 30;
/* (14) Erreur de paramètre par défaut */
const WrongDefaultParam = 31;
/* (15) Erreur lorsque un download n'a pas de body */
const MissingBody = 32;
/* (16) Erreur lorsqu'un download n'a pas de headers */
const MissingHeaders = 33;
/* (17) Erreur lorsque la requete est null lors de la génération de documentation */
const NullRequest = 34;
/* [5] Database

View File

@ -21,6 +21,8 @@
*
*/
public function __construct($const){
//make the static analisis happy
$tmp = $const;
call_user_func_array([$this, 'set'], func_get_args());
}
@ -74,9 +76,10 @@
case Err::UncallableModule: return $this->UncallableModule(); break;
case Err::UncallableMethod: return $this->UncallableMethod(); break;
case Err::UnknownHttpMethod: return $this->UnknownHttpMethod(); break;
case Err::ConfigError: return $this->ConfigError(); break;
case Err::ConfigError: return $this->ConfigError(); break;
case Err::MissingParam: return $this->MissingParam(); break;
case Err::WrongParam: return $this->WrongParam(); break;
case Err::WrongDefaultParam: return $this->WrongDefaultParam(); break;
case Err::ModuleError: return $this->ModuleError(); break;
case Err::PDOConnection: return $this->PDOConnection(); break;
case Err::WrongPathRepo: return $this->WrongPathRepo(); break;
@ -85,6 +88,8 @@
case Err::UnknownTable: return $this->UnknownTable(); break;
case Err::NotAllowedSchema: return $this->NotAllowedSchema(); break;
case Err::NoMatchFound: return $this->NoMatchFound(); break;
case Err::MissingBody: return $this->MissingBody(); break;
case Err::MissingHeaders: return $this->MissingHeaders(); break;
case Err::UnknownTemplate: return $this->UnknownTemplate(); break;
case Err::UnknownAddress: return $this->UnknownAddress(); break;
case Err::UnknownError: return $this->UnknownError(); break;
@ -158,6 +163,14 @@
return 'wrong param \''.$this->arguments[0].'\'';
else
return 'wrong param';
}private function WrongDefaultParam(){
if( count($this->arguments) > 0 )
if( count($this->arguments) > 1 )
return 'wrong default param \''.$this->arguments[0].'\' expected to be of type \''.$this->arguments[1].'\'';
else
return 'wrong default param \''.$this->arguments[0].'\'';
else
return 'wrong param';
}private function ModuleError(){
return 'module error';
}private function PDOConnection(){
@ -182,6 +195,10 @@
return 'unknown error';
}private function AlreadyExists(){
return 'item already exists';
}private function MissingBody(){
return 'Missing HTTP body';
}private function MissingHeaders(){
return 'Missing HTTP headers';
}private function UnknownDebugError(){
return 'unknown debug error';
}

View File

@ -47,7 +47,14 @@
/* [3] Define default datasets (GET, POST)
=========================================================*/
/* (1) Add to $_GET legacy GET parameters */
parse_str(parse_url($this->uri)['query'], $legacy_get);
$_GET = array_merge($_GET, $legacy_get);
/* (2) Store GET parameters */
$this->getdata = $_GET;
/* (3) Store POST parameters */
$this->postdata = $_POST;

View File

@ -33,12 +33,15 @@
*/
public function call(){
header('Content-Type: application/json');
/* (1) Process response */
$this->response = $this->request->dispatch();
/* (2) Manages result */
if( $this->response instanceof Response )
if( $this->response instanceof Response ){
echo $this->response->serialize();
}
return true;

View File

@ -28,8 +28,11 @@
echo "window._SERVER = ".json_encode([
'session' => [
'name' => $_SESSION['NAME'],
'connected' => isset($_SESSION['USER']) ? count($_SESSION['USER']) > 0 : false
'name' => $_SESSION['CAS']['login'],
'connected' => isset($_SESSION['AUTH']) ? count($_SESSION['AUTH']) > 0 : false,
'departments' => array_map(function($d){ return [ 'id' => $d['idDep'], 'label' => $d['labelDep']]; }, $_SESSION['AvailableDepartments']),
'department_id' => $_SESSION['CurrentDepartmentId'],
'version' => $_SESSION['VERSION']
]
])."\n";

View File

@ -7,6 +7,7 @@
private $pagename;
private $uri;
/* PRE-CALL
*
@ -24,17 +25,51 @@
*/
public function load(){
/* (1) Build page file name */
/* (1) If not logged in -> login page*/
if( !isset($_SESSION['AUTH']) || !is_array($_SESSION['AUTH']) || count($_SESSION['AUTH']) < 1 ){
include __PUBLIC__."/page/login.php";
die();
}
/* (2) Only teacher */
if( !in_array('cas_admin', $_SESSION['AUTH']) ){
// redirection
if( $this->pagename != "fiche" ){
header('Location: /fiche/');
die();
}
// deconnection
if( $this->uri == 'logout' || $this->uri == 'logout/' ){
\session_destroy();
header('Location: /');
die();
}
// load page
include __PUBLIC__."/page/fiche.php";
die();
}
/* (3) Build page file name */
$page_fname = __PUBLIC__."/page/".$this->pagename.".php";
/* (2) If page does not exist -> 404 */
/* (4) If page does not exist -> 404 */
if( !file_exists($page_fname) )
include __PUBLIC__.'/page/404.php';
/* (3) Set URI arguments */
/* (5) Set URI arguments */
$_GET['uri'] = explode('/', $this->uri);
/* (4) Load page */
/* (6) Load page */
include __PUBLIC__."/page/".$this->pagename.".php";
}

View File

@ -5,6 +5,7 @@
class redirect{
private $url;
/* PRE-CALL
*
@ -12,6 +13,7 @@
*
*/
public function __construct($url){
$this->url = $url;
}

View File

@ -10,8 +10,6 @@
* https://xdrm.io/ *
**************************/
use router\core\ControllerFactory;
namespace router\core;
class Route{

View File

@ -10,8 +10,6 @@
* https://xdrm.io/ *
**************************/
use \router\core\ControllerFactory;
namespace router\core;
class Router{

View File

@ -25,6 +25,11 @@
"files": ["autoloader.php"]
},
"require": {
"phpoffice/phpspreadsheet": "^1.1"
"phpoffice/phpspreadsheet": "^1.1",
"phpstan/phpstan": "^0.9.2",
"ifsnop/mysqldump-php": "2.*",
"setasign/fpdf": "1.8.1",
"mpdf/mpdf": "^7.0",
"php" : ">= 7.1"
}
}

1235
composer.lock generated

File diff suppressed because it is too large Load Diff

BIN
composer.phar Normal file

Binary file not shown.

View File

@ -4,7 +4,8 @@
"host" : "mariadb",
"dbname" : "vhost",
"user" : "php",
"password" : "4JB1dtbrIC8pT935"
"password" : "4JB1dtbrIC8pT935",
"debug" : true
},
"remote": {
"host" : "db_remote_host",

View File

@ -1,48 +1,47 @@
{
"GET": {
"POST": {
"des": "Returns the API documentation",
"per": [],
"par": {
"URL0": { "des": "Method name", "typ": "varchar(1,30)", "ren": "method_name", "opt": true, "def": null }
"URL0": { "des": "Method name", "typ": "varchar(1,30)", "ren": "method_name", "opt": true, "def": null },
"mixed": { "des": "mixed type", "typ": "mixed", "opt": true },
"id": { "des": "id type", "typ": "id", "opt": true },
"text": { "des": "text type", "typ": "text", "opt": true },
"mail": { "des": "mail type", "typ": "mail", "opt": true },
"alphanumeric": { "des": "alphanumeric type", "typ": "alphanumeric", "opt": true },
"letters": { "des": "letters type", "typ": "letters", "opt": true },
"array": { "des": "array type", "typ": "array", "opt": true },
"array_id": { "des": "array<id> type", "typ": "array<id>", "opt": true },
"boolean": { "des": "boolean type", "typ": "boolean", "opt": true },
"object": { "des": "object type", "typ": "object", "opt": true },
"numeric": { "des": "numeric type", "typ": "numeric", "opt": true },
"float": { "des": "float type", "typ": "float", "opt": true }
}
},
"admin": {
"cas": {
"POST": {
"des": "Creates a new administrator",
"per": [["admin"]],
"GET": {
"des": "Authenticatation callback (used by third-party OAuth)",
"per": [],
"par": {
"username": { "des": "The new administrator username", "typ": "varchar(3,20,alphanumeric)" },
"mail": { "des": "The new administrator email address", "typ": "mail" },
"password": { "des": "The new administrator passowrd", "typ": "text" }
}
"URL0": { "des": "Whether to manage a popup", "typ": "id", "opt": true, "ren": "popup_mode", "def": 0 }
},
"opt": { "download": true }
},
"PUT": {
"des": "Updates an existing administrator's data",
"per": [["admin"]],
"par": {
"URL0": { "des": "The UID of the wanted administrator.", "typ": "id", "ren": "id_admin" },
"mail": { "des": "The new administrator email address", "typ": "mail", "opt": true },
"password": { "des": "The new administrator passowrd", "typ": "text", "opt": true }
}
"des": "Real logout to change login",
"per": [["cas_user"]],
"par": {}
},
"DELETE": {
"des": "Deletes an administrator",
"per": [["admin"]],
"par": {
"URL0": { "des": "The UID of the wanted administrator.", "typ": "id", "opt": true, "ren": "id_admin" }
}
},
"GET": {
"des": "Gets an administrator | Gets all administrators if no id defined",
"per": [["admin"]],
"par": {
"URL0": { "des": "The UID of the wanted administrator.", "typ": "id", "opt": true, "ren": "id_admin" }
}
"des": "Logout",
"per": [["cas_user"]],
"par": {}
}
},
@ -52,7 +51,7 @@
"GET": {
"des": "Pulls project from git branch.",
"per": [["admin"]],
"per": [[]],
"par": {
"URL0": { "des": "Name of the project to release", "typ": "alphanumeric", "ren": "project", "opt": true, "def": "self" },
"URL1": { "des": "Step to run, if not given, all steps will be run", "typ": "id", "ren": "step", "opt": true }
@ -61,55 +60,486 @@
}
},
"Excel":{
"excel":{
"POST": {
"des": "Import data from an Excel file",
"per": [],
"per": [["cas_admin"]],
"par": {
}
}
},
"a": {
"department":{
"b": {
"GET": {
"des": "Get one or all departments",
"per": [["cas_user"]],
"par": {
"URL0": { "des": "Optional department id.", "typ": "id", "ren": "id_dep", "opt": true }
},
"out": {
"departments": { "des": "department list", "typ": "array" }
}
},
"c": {
"PUT": {
"des": "PUT A/B/C.",
"per": [],
"par": {}
},
"DELETE": {
"des": "DELETE A/B/C.",
"per": [],
"par": {}
"POST": {
"des": "Create a new Department",
"per": [["cas_user"]],
"par": {
"name": { "des": "Name of the department", "typ": "text"}
}
},
"PUT":{
"des": "Switch the user on another department database",
"per": [["cas_user"]],
"par": {
"URL0": {"des": "Department id", "typ": "id", "ren": "department" }
},
"out": {
"switched": { "des": "Whether the department has been switched", "typ": "bool" }
}
},
"errors":{
"GET": {
"des": "Get the list of incoherence of the department",
"per": [["cas_admin"]],
"par": {
}
}
},
"stats":{
"GET": {
"des": "Get the statistics about the department",
"per": [["cas_admin"]],
"par": {
}
}
},
"export":{
"GET": {
"des": "Export the data of the current department and version to a Excel file",
"per": [["cas_admin"]],
"par": {},
"opt": { "download": true }
}
},
"version":{
"switch":{
"GET": {
"des": "Switch database version for the current session",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "The version id", "typ": "id", "ren": "version" }
},
"out": {
"sucess": { "des": "success of the operation", "typ": "bool" }
}
}
},
"GET": {
"des": "Get the list of the versions of the department",
"per": [["cas_admin"]],
"par": {},
"out": {
"versions": { "des": "List of available versions", "typ": "array" }
}
},
"POST": {
"des": "Create a backup if the name is empty, execute the backup if the name is set",
"per": [["cas_admin"]],
"par": {
"label": { "des": "Label of the version", "typ": "text" }
},
"out": {
"created_id": { "des": "The id of the created version", "typ": "varchar(10,10,alphanumeric)" }
}
},
"PUT": {
"des": "Update a version and switch to this version",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "id of the version", "typ": "id", "ren": "version" },
"label": { "des": "Label de la version", "typ": "text", "opt": true },
"default": { "des": "Whether this version should be used on login", "typ": "bool", "opt": true }
},
"out": {
"updated": { "des": "Whether the version has been switched|applied", "typ": "bool" }
}
},
"DELETE": {
"des": "Delete a backup",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "The version id", "typ": "id", "ren": "version" }
},
"out": {
"deleted": { "des": "Whether the version has been deleted", "typ": "bool" }
}
}
}
},
"professor":{
"POST": {
"des": "Creates a new professor",
"per": [["cas_admin"]],
"par": {
"firstName": { "des": "Professor last name.", "typ": "varchar(2,30,alphanumeric)" },
"lastName": { "des": "Professor first name.", "typ": "varchar(2,30,alphanumeric)" },
"category": { "des": "Professor category UID.", "typ": "id" },
"hoursToDo": { "des": "Number of hours professor have to do", "typ": "id" },
"initials": { "des": "Professor initials", "typ": "varchar(2,8,letters)" },
"isAdmin": { "des": "Whether professor is an admin", "typ": "boolean" },
"casLogin": { "des": "Optional CAS username", "typ": "varchar(6,16,letters)", "opt": true }
},
"out": {
"created_uid": { "des": "Created professor UID", "typ": "id" }
}
},
"GET": {
"des": "Get one or all professors",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Whether to return VH", "typ": "id", "ren": "with_vh" },
"URL1": { "des": "Optional professor UID.", "typ": "id", "ren": "prof_id", "opt": true }
},
"out": {
"professors": { "des": "Teacher list", "typ": "array" }
}
},
"DELETE": {
"des": "Deletes an existing professor",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Professor UID.", "typ": "id", "ren": "prof_id" }
},
"out": {
"deleted": { "des": "Whether it has been deleted", "typ": "boolean" }
}
},
"PUT": {
"des": "Edits an existing professor",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Optional professor UID.", "typ": "id", "ren": "prof_id" },
"firstName": { "des": "Professor last name.", "typ": "varchar(2,30,alphanumeric)", "opt": true },
"lastName": { "des": "Professor first name.", "typ": "varchar(2,30,alphanumeric)", "opt": true },
"category": { "des": "Professor category UID.", "typ": "id", "opt": true },
"hoursToDo": { "des": "Number of hours professor have to do", "typ": "id", "opt": true },
"initials": { "des": "Professor initials", "typ": "varchar(2,8,letters)", "opt": true },
"isAdmin": { "des": "Whether professor is an admin", "typ": "boolean", "opt": true },
"casLogin": { "des": "Optional CAS username", "typ": "varchar(6,16,letters)", "opt": true },
"remCas": { "des": "Unset CAS username", "typ": "boolean", "def": false, "opt": true }
},
"out": {
"updated": { "des": "Whether the professor has been updated", "typ": "boolean" }
}
},
"filter": {
"POST": {
"des": "Get matching professors (only ids) for a given filter",
"per": [["cas_admin"]],
"par": {
"categories": { "des": "Optional category ID list", "typ": "array<id>", "opt": true },
"formations": { "des": "Optional formation ID list", "typ": "array<id>", "opt": true },
"ues": { "des": "Optional UE code list", "typ": "array<varchar(2,30,alphanumeric)>", "opt": true }
},
"out": {
"matches": { "des": "Matching professor UID(s)", "typ": "array<id>" }
}
}
},
"pdf": {
"GET": {
"des": "Get a professor's fiche",
"per": [["cas_admin"], ["cas_user"]],
"par": {
"URL0": { "des": "Optional professor UID.", "typ": "id", "ren": "prof_id" }
},
"opt": { "download": true }
}
}
},
"ue":{
"POST": {
"des": "Creates a new UE",
"per": [["cas_admin"]],
"par": {
"code": { "des": "UE code.", "typ": "varchar(4,20,alphanumeric)" },
"label": { "des": "UE label", "typ": "varchar(4,30,alphanumeric)" },
"required": { "des": "If UE is required", "typ": "bool" },
"volumeCours": { "des": "Number of course hours for UE", "typ": "float" },
"volumeTD": { "des": "Number of TD hours for UE", "typ": "float" },
"volumeTP": { "des": "Number of TP hours for UE", "typ": "float" },
"disabled": { "des": "Whether UE is disabled", "typ": "boolean" },
"defaultFormation": { "des": "UID for optional default formation (-1 if none)", "typ": "int", "opt": true, "def": -1 }
},
"out": {
"created_code": { "des": "Created UE code", "typ": "varchar(4,20,alphanumeric)" }
}
},
"GET": {
"des": "Get one or all UE",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Optional UE code.", "typ": "varchar(4,20,alphanumeric)", "ren": "code", "opt": true }
},
"out": {
"ues": { "des": "UE list", "typ": "array" }
}
},
"DELETE": {
"des": "Deletes an existing UE",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "UE code.", "typ": "varchar(4,20,alphanumeric)", "ren": "code" }
},
"out": {
"deleted": { "des": "Whether it has been deleted", "typ": "boolean" }
}
},
"PUT": {
"des": "Edits an existing UE",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "UE code.", "typ": "varchar(4,20,alphanumeric)", "ren": "code" },
"new_code": { "des": "UE new code", "typ": "varchar(4,20,alphanumeric)", "opt": true },
"label": { "des": "UE label", "typ": "varchar(4,30,alphanumeric)", "opt": true },
"required": { "des": "If UE is required", "typ": "bool", "opt": true },
"volumeCours": { "des": "Number of course hours for UE", "typ": "float", "opt": true },
"volumeTD": { "des": "Number of TD hours for UE", "typ": "float", "opt": true },
"volumeTP": { "des": "Number of TP hours for UE", "typ": "float", "opt": true },
"disabled": { "des": "Whether UE is disabled", "typ": "boolean", "opt": true },
"defaultFormation": { "des": "UID for optional default formation (-1 for none)", "typ": "int", "opt": true }
},
"out": {
"updated": { "des": "Whether the UE has been updated", "typ": "boolean" }
}
},
"cours": {
"POST": {
"des" : "Creates a new Cours for an UE",
"per": [["cas_admin"]],
"par": {
"code": { "des": "Code of the UE", "typ": "varchar(4,20,alphanumeric)" },
"idProf": { "des": "Id of the professor", "typ": "id", "opt": true },
"volume": { "des": "Number of hours for Cours", "typ": "id", "opt": true, "def": 0 },
"formations": { "des": "List of formations (ids)", "typ": "array<id>", "opt": true, "def": [] }
},
"out": {
"created_id" : { "des": "The id of the created Cours", "typ": "id" },
"formations" : { "des": "The ids of the linked formations", "typ": "array<id>" }
}
},
"GET": {
"des" : "Get all cours data about a given UE",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Code of the UE", "typ": "varchar(4,20,alphanumeric)", "ren": "code" }
}
},
"PUT": {
"des": "PUT A/B.",
"per": [],
"par": {}
"des" : "Updates an existing Cours",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the Cours", "typ": "id", "ren": "idCours" },
"idProf": { "des": "Id of the professor (-1 to unset)", "typ": "int", "opt": true },
"volume": { "des": "Number of hours for Cours", "typ": "float", "opt": true },
"add_form": { "des": "Id of formations to add", "typ": "array<id>", "opt": true, "def": [] },
"rem_form": { "des": "Id of formations to remove", "typ": "array<id>", "opt": true, "def": [] }
},
"out": {
"updated" : { "des": "Whether it has been updated", "typ": "bool" }
}
},
"DELETE": {
"des": "DELETE A/B.",
"per": [],
"par": {}
"des" : "Deletes an existing Cours",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the Cours", "typ": "id", "ren": "idCours" }
},
"out": {
"deleted" : { "des": "Whether it has been deleted", "typ": "bool" }
}
}
},
"GET": {
"des": "GET A.",
"per": [],
"par": {}
"td": {
"POST": {
"des" : "Creates a new TD for an UE",
"per": [["cas_admin"]],
"par": {
"code": { "des": "Code of the UE", "typ": "varchar(4,20,alphanumeric)" },
"idProf": { "des": "Id of the professor", "typ": "id", "opt": true },
"volume": { "des": "Number of hours for TD", "typ": "id", "opt": true, "def": 0 },
"formations": { "des": "List of formations (ids)", "typ": "array<id>", "opt": true, "def": [] }
},
"out": {
"created_id" : { "des": "The id of the created TD", "typ": "id" },
"formations" : { "des": "The ids of the linked formations", "typ": "array<id>" }
}
},
"GET": {
"des" : "Get all TD data about a given UE",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Code of the UE", "typ": "varchar(4,20,alphanumeric)", "ren": "code" }
}
},
"PUT": {
"des" : "Updates an existing TD",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the TD", "typ": "id", "ren": "idTD" },
"idProf": { "des": "Id of the professor (-1 to unset)", "typ": "int", "opt": true },
"volume": { "des": "Number of hours for TD", "typ": "float", "opt": true },
"add_form": { "des": "Id of formations to add", "typ": "array<id>", "opt": true, "def": [] },
"rem_form": { "des": "Id of formations to remove", "typ": "array<id>", "opt": true, "def": [] }
},
"out": {
"updated" : { "des": "Whether it has been updated", "typ": "bool" }
}
},
"DELETE": {
"des" : "Deletes an existing TD",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the TD", "typ": "id", "ren": "idTD" }
},
"out": {
"deleted" : { "des": "Whether it has been deleted", "typ": "bool" }
}
}
},
"POST": {
"des": "POST A.",
"per": [],
"par": {}
"tp": {
"POST": {
"des" : "Creates a new TP for an UE",
"per": [["cas_admin"]],
"par": {
"code": { "des": "Code of the UE", "typ": "varchar(4,20,alphanumeric)" },
"idProf": { "des": "Id of the professor", "typ": "id", "opt": true },
"volume": { "des": "Number of hours for TP", "typ": "id", "opt": true, "def": 0 },
"formations": { "des": "List of formations (ids)", "typ": "array<id>", "opt": true, "def": [] }
},
"out": {
"created_id" : { "des": "The id of the created TP", "typ": "id" },
"formations" : { "des": "The ids of the linked formations", "typ": "array<id>" }
}
},
"GET": {
"des" : "Get all TP data about a given UE",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Code of the UE", "typ": "varchar(4,20,alphanumeric)", "ren": "code" }
}
},
"PUT": {
"des" : "Updates an existing TP",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the TP", "typ": "id", "ren": "idTP" },
"idProf": { "des": "Id of the professor (-1 to unset)", "typ": "int", "opt": true },
"volume": { "des": "Number of hours for TP", "typ": "float", "opt": true },
"add_form": { "des": "Id of formations to add", "typ": "array<id>", "opt": true, "def": [] },
"rem_form": { "des": "Id of formations to remove", "typ": "array<id>", "opt": true, "def": [] }
},
"out": {
"updated" : { "des": "Whether it has been updated", "typ": "bool" }
}
},
"DELETE": {
"des" : "Deletes an existing TP",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the TP", "typ": "id", "ren": "idTP" }
},
"out": {
"deleted" : { "des": "Whether it has been deleted", "typ": "bool" }
}
}
}
},
"formation": {
"GET":{
"des": "Get all data about a formation",
"per": [["cas_admin"]],
"par": {
"URL0":{"des" : "Id of the formation", "typ": "id", "ren": "form_id", "opt" : true }
}
},
"POST":{
"des": "Create a new formation",
"per": [["cas_admin"]],
"par": {
"label":{"des" : "name of the formation", "typ": "text" },
"isInternal":{"des" : "is this formation internal to the department", "typ": "bool" }
}
},
"PUT":{
"des": "Update a formation",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the formation", "typ": "id", "ren": "idFormation" },
"label":{"des" : "name of the formation", "typ": "text", "opt":true },
"isInternal":{"des" : "is this formation internal to the department", "typ": "bool", "opt":true }
}
},
"DELETE":{
"des": "Delete a formation",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the formation", "typ": "id", "ren": "idFormation" }
}
}
},
"category": {
"GET": {
"des" : "Get all data about a given category | all",
"per": [["cas_admin"]],
"par": {
"URL0": { "des": "Id of the category", "typ": "id", "ren": "cat_id", "opt": true }
}
}
}
}

9422
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -6,16 +6,19 @@
"license": "MIT",
"private": true,
"scripts": {
"build:clean": "rm ./public_html/js/bundle/*.js*; exit 0",
"build:bundle": "cross-env NODE_ENV=production webpack --progress --hide-modules",
"build:dev": "cross-env NODE_ENV=development webpack --progress --hide-modules",
"bundle:clean": "rm ./public_html/js/bundle/*.js*; exit 0",
"bundle:prod": "cross-env NODE_ENV=production webpack --progress --hide-modules",
"bundle:dev": "cross-env NODE_ENV=development webpack --progress --hide-modules",
"bundle:watch": "cross-env NODE_ENV=development webpack --progress --watch --hide-modules",
"scss": "node-sass -r --output-style compressed --output ./public_html/css ./webpack/scss",
"watch": "node-sass -w -r --output-style compressed --output ./public_html/css ./webpack/scss",
"dev": "npm run build:clean; npm run build:dev; npm run watch",
"build": "npm run build:clean; npm run build:bundle; npm run scss"
"watch-css": "node-sass -w -r --output-style compressed --output ./public_html/css ./webpack/scss",
"dev": "npm run bundle:clean; npm run bundle:dev; npm run watch-css",
"devjs": "npm run bundle:clean; npm run bundle:watch",
"build": "npm run bundle:clean; npm run bundle:prod; npm run scss"
},
"dependencies": {
"vue": "^2.5.9"
"vue": "^2.5.9",
"vue-router": "^2.5.3"
},
"browserslist": [
"> 1%",
@ -34,7 +37,7 @@
"node-sass": "^4.7.2",
"sass-loader": "^6.0.6",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.5.9",
"vue-template-compiler": "^2.5.16",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.5"
}

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="17px"
version="1.1"
viewBox="0 0 14 17"
width="14px"
id="svg12"
sodipodi:docname="a.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview14"
showgrid="false"
inkscape:zoom="13.882353"
inkscape:cx="7"
inkscape:cy="8.5"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg12" />
<desc
id="desc4" />
<defs
id="defs6" />
<path
inkscape:connector-curvature="0"
id="fill-edit"
d="m 0,13.5 v 2 h 14 v -2 z M 4.5,9.3 h 5 l 0.9,2.2 h 2.1 L 7.8,0.5 H 6.3 l -4.8,11 H 3.6 Z M 7,2.5 8.9,7.5 H 5.2 Z"
style="fill:#000000;fill-rule:evenodd;stroke:none;stroke-width:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 44 43"
height="43px"
id="Layer_1"
version="1.1"
viewBox="0 0 44 43"
width="44px"
xml:space="preserve"
sodipodi:docname="admin-disabled.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="10.976744"
inkscape:cx="26.47426"
inkscape:cy="19.2405"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"
inkscape:snap-midpoints="true" /><path
style="fill:#231f20"
d="M 28.492188 0 C 24.532187 0.00675 20.571922 1.5262344 17.544922 4.5527344 C 16.198022 5.8996337 15.192784 7.4685221 14.484375 9.1425781 L 8.4960938 3.1542969 L 5.7675781 5.8847656 L 39.873047 39.990234 L 42.601562 37.259766 L 35.001953 29.660156 C 36.615245 28.891394 38.130701 27.834142 39.478516 26.486328 C 45.531516 20.433328 45.4915 10.578391 39.4375 4.5253906 C 36.4115 1.4988906 32.452188 -0.00675 28.492188 0 z M 33.714844 6.8730469 C 34.738469 6.8730469 35.761469 7.2634219 36.542969 8.0449219 C 38.105969 9.6079219 38.104969 12.138172 36.542969 13.701172 C 34.980969 15.264172 32.449719 15.264172 30.886719 13.701172 C 29.323719 12.139172 29.324719 9.6079219 30.886719 8.0449219 C 31.667719 7.2634219 32.691219 6.8730469 33.714844 6.8730469 z M 13.433594 18.46875 C 13.588826 19.402362 13.811332 20.312408 14.113281 21.173828 L 1.0644531 34.224609 C 1.0614531 34.228609 1.0615936 34.226469 1.0585938 34.230469 L 1 34.171875 C 0.327 34.913875 0.65429688 34.655578 0.65429688 34.767578 L 0.37109375 42.101562 C 0.37209375 42.702563 0.89804686 43.144531 1.4980469 43.144531 L 8.7695312 42.925781 C 8.8805313 42.925781 8.6437656 43.231594 9.3847656 42.558594 L 9.5429688 42.714844 L 9.5527344 42.705078 L 11.664062 40.59375 L 11.130859 36.380859 L 15.375 36.373047 L 15.357422 32.101562 L 19.441406 32.816406 L 19.550781 32.707031 L 22.453125 29.804688 C 23.563502 30.302632 24.697457 30.656819 25.839844 30.875 L 13.433594 18.46875 z "
id="fill-edit" /></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 44 43"
height="43px"
id="Layer_1"
version="1.1"
viewBox="0 0 44 43"
width="44px"
xml:space="preserve"
sodipodi:docname="admin.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="5.4883721"
inkscape:cx="22"
inkscape:cy="21.5"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="m 14.113324,21.173 c -1.835,-5.235 -1.049,-12.14 3.431,-16.62 6.054,-6.053 15.841,-6.08 21.893,-0.027 6.054,6.053 6.094,15.908 0.041,21.961 -4.615,4.615 -11.168,5.945 -17.026,3.318 l -2.902,2.902 -0.109,0.109 -4.084,-0.714 0.018,4.271 -4.244,0.008 0.532,4.213 -2.1109998,2.111 c -0.006,0.006 -0.006,0.006 -0.01,0.01 l -0.157,-0.156 c -0.741,0.673 -0.504,0.366 -0.615,0.366 l -7.272,0.22 c -0.6,0 -1.126,-0.443 -1.127,-1.044 l 0.283,-7.333 c 0,-0.112 -0.327,0.146 0.346,-0.596 l 0.058,0.059 c 0.003,-0.004 0.003,-0.003 0.006,-0.007 z m 16.773,-7.471 c 1.563,1.563 4.095,1.563 5.657,0 1.562,-1.563 1.563,-4.094 0,-5.657 -1.563,-1.563 -4.095,-1.563 -5.657,0 -1.562,1.563 -1.563,4.095 0,5.657 z"
id="fill-edit"
inkscape:connector-curvature="0"
style="fill:#231f20" /></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="32px"
id="Layer_1"
style="enable-background:new 0 0 32 32;"
version="1.1"
viewBox="0 0 32 32"
width="32px"
xml:space="preserve"
sodipodi:docname="back.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="7.375"
inkscape:cx="16"
inkscape:cy="16"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="M 12,6 C 11.469,6 11.005141,6.1930781 10.619141,6.5800781 L 2.6621094,14.537109 C 2.3341094,14.865109 2,15.271 2,16 c 0,0.729 0.2794844,1.080266 0.6464844,1.447266 l 7.9726566,7.972656 C 11.005141,25.806922 11.469,26 12,26 c 1.188,0 2,-1.016 2,-2 0,-0.516 -0.186078,-0.986859 -0.580078,-1.380859 L 8.8007812,18 H 28 c 1.104,0 2,-0.896 2,-2 0,-1.104 -0.896,-2 -2,-2 H 8.8007812 L 13.419922,9.3808594 C 13.813922,8.9868594 14,8.516 14,8 14,7.016 13.187,6 12,6 Z"
id="fill-edit"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 49 49"
height="49px"
id="Layer_1"
version="1.1"
viewBox="0 0 49 49"
width="49px"
xml:space="preserve"
sodipodi:docname="bell-disabled.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview11"
showgrid="false"
inkscape:zoom="4.8163265"
inkscape:cx="24.5"
inkscape:cy="24.5"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
inkscape:connector-curvature="0"
id="fill-edit"
d="M 45.771484,-0.05664062 37.193359,8.5214844 c -1.615,-1.068 -3.436625,-1.8444688 -5.390625,-2.2304688 C 31.455734,3.8680156 29.3295,2 26.8125,2 24.2945,2 22.326516,3.8680156 21.978516,6.2910156 15.096516,7.6530156 10,13.719 10,21 V 32 H 8.75 c -2.209,0 -4,1.791 -4,4 0,1.352 0.6732187,2.541625 1.6992188,3.265625 L 0.19335938,45.521484 3.7285156,49.056641 49.306641,3.4785156 Z M 42.416016,14.369141 16.785156,40 H 44.75 c 2.209,0 4,-1.791 4,-4 0,-2.209 -1.791,-4 -4,-4 H 44 V 21 c 0,-2.383 -0.577984,-4.630859 -1.583984,-6.630859 z M 22,42 c 0,2.762 2.239,5 5,5 2.762,0 5,-2.238 5,-5 z" /></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 49 49"
height="49px"
id="Layer_1"
version="1.1"
viewBox="0 0 49 49"
width="49px"
xml:space="preserve"
sodipodi:docname="bell.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata15"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs13" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview11"
showgrid="false"
inkscape:zoom="13.622629"
inkscape:cx="18.4695"
inkscape:cy="26.961408"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
style="fill:#231f20"
d="m 27.025617,2.0000004 c -2.518,0 -4.581688,1.8680156 -4.929688,4.2910156 C 15.214929,7.653016 10.025627,13.719 10.025627,21 V 32 H 9.0256266 c -2.209,0 -4.0000002,1.791 -4.0000002,4 0,2.209 1.7910002,4 4.0000002,4 H 45.025617 c 2.209,0 4,-1.791 4,-4 0,-2.209 -1.791,-4 -4,-4 h -1 V 21 c 0,-7.281 -5.188312,-13.346984 -12.070312,-14.708984 -0.348,-2.423 -2.411688,-4.2910156 -4.929688,-4.2910156 z M 22.025617,42 c 0,2.762 2.239,5 5,5 2.762,0 5,-2.238 5,-5 z"
id="fill-edit"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="1024"
width="768"
version="1.1"
id="svg4"
sodipodi:docname="checkbox.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview6"
showgrid="false"
inkscape:zoom="0.23046875"
inkscape:cx="384"
inkscape:cy="512"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="M 640,192 256,576 128,448 0,576 256,832 768,320 Z"
id="fill-edit"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 128 128"
height="128px"
id="Слой_1"
version="1.1"
viewBox="0 0 128 128"
width="128px"
xml:space="preserve"
sodipodi:docname="course.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata11"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs9" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1280"
inkscape:window-height="684"
id="namedview7"
showgrid="false"
inkscape:zoom="1.84375"
inkscape:cx="64"
inkscape:cy="64"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Слой_1" /><path
style="fill:#373737"
inkscape:connector-curvature="0"
id="fill-edit"
d="M 120.99512,7.4003906 C 119.4502,7.4003906 84.976562,7.6142578 64,24.602051 43.024902,7.6142578 8.5498047,7.4003906 7.0048828,7.4003906 H 1.7275391 V 112.94727 h 5.2773438 c 27.5346681,0 44.7817381,5.17187 51.4726561,7.65234 h 10.999024 c 6.597656,-2.47363 23.719726,-7.65234 51.518557,-7.65234 h 5.27734 V 7.4003906 Z M 58.722656,109.49316 C 50.262695,106.7334 34.794434,102.97168 12.282227,102.4541 V 18.204102 C 22.523926,18.95459 45.25,21.956055 58.722656,33.950684 Z m 56.995114,-7.03906 c -22.511715,0.51758 -37.980465,4.2793 -46.440426,7.03906 V 33.950684 C 82.750976,21.955078 105.47852,18.954102 115.71777,18.204102 Z" /></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 24 24"
height="24px"
id="Layer_1"
version="1.1"
viewBox="0 0 24 24"
width="24px"
xml:space="preserve"
sodipodi:docname="cross.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="m 22.245,4.015 c 0.313,0.313 0.313,0.826 0,1.139 l -6.276,6.27 c -0.313,0.312 -0.313,0.826 0,1.14 l 6.273,6.272 c 0.313,0.313 0.313,0.826 0,1.14 l -2.285,2.277 c -0.314,0.312 -0.828,0.312 -1.142,0 l -6.271,-6.271 c -0.313,-0.313 -0.828,-0.313 -1.141,0 l -6.276,6.267 c -0.313,0.313 -0.828,0.313 -1.141,0 l -2.282,-2.28 c -0.313,-0.313 -0.313,-0.826 0,-1.14 L 7.982,12.56 c 0.313,-0.312 0.313,-0.826 0,-1.14 L 1.709,5.147 C 1.395,4.834 1.395,4.32 1.709,4.007 L 3.993,1.729 C 4.308,1.417 4.821,1.417 5.135,1.73 L 11.405,8 c 0.314,0.314 0.828,0.314 1.141,10e-4 l 6.276,-6.267 c 0.312,-0.312 0.826,-0.312 1.141,0 z"
id="fill-edit"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="48"
viewBox="0 0 48 48"
width="48"
version="1.1"
id="svg6"
sodipodi:docname="down_arrow.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview8"
showgrid="false"
inkscape:zoom="4.9166667"
inkscape:cx="24"
inkscape:cy="24"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="m 14.83,16.42 9.17,9.17 9.17,-9.17 2.83,2.83 -12,12 -12,-12 z"
id="fill-edit"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -7,25 +7,19 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="32px"
enable-background="new 0 0 30 30"
height="30px"
id="Layer_1"
version="1.1"
viewBox="0 0 32 32"
width="32px"
id="svg11"
viewBox="0 0 30 30"
width="30px"
xml:space="preserve"
sodipodi:docname="fiche.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata15">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs11" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
@ -34,34 +28,17 @@
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview13"
inkscape:window-width="812"
inkscape:window-height="480"
id="namedview9"
showgrid="false"
inkscape:zoom="7.375"
inkscape:cx="-17.711864"
inkscape:cy="14"
inkscape:zoom="7.8666667"
inkscape:cx="15"
inkscape:cy="15"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg11" />
<title
id="title2" />
<desc
id="desc4" />
<defs
id="defs6" />
<g
id="Page-1"
transform="matrix(1.1004394,0,0,1.1004394,-1.6572505,-1.6572505)"
style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1">
<g
id="icon-55-document-text"
style="fill:#157efb">
<path
d="M 19,3 H 9.00853 C 7.89925,3 7,3.8983383 7,5.0073299 V 27.99267 C 7,29.101288 7.890925,30 8.997422,30 H 24.002578 C 25.105724,30 26,29.109075 26,28.002578 V 11 H 21.005919 C 19.898081,11 19,10.113294 19,9.0018986 Z m 1,0 V 8.9970707 C 20,9.5509732 20.450975,10 20.990778,10 H 26 Z m -10,7 v 1 h 7 v -1 z m 0,-3 v 1 h 7 V 7 Z m 0,6 v 1 h 13 v -1 z m 0,3 v 1 h 13 v -1 z m 0,3 v 1 h 13 v -1 z m 0,3 v 1 h 13 v -1 z m 0,3 v 1 h 13 v -1 z"
id="fill-edit"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="Layer_1" /><path
inkscape:connector-curvature="0"
id="fill-edit"
d="M 0,0 V 28.667969 H 30.015625 V 0 Z M 2.8847656,2.8867188 H 27.128906 V 25.783203 H 2.8847656 Z M 14.693359,3.3671875 c -0.126825,0.00587 -0.212904,0.024811 -0.216797,0.025391 -0.02922,0.00346 -0.254494,0.02147 -0.501953,0.1132813 -0.254285,0.093345 -0.638411,0.2902809 -0.919921,0.7089844 -0.275431,0.4105138 -0.373082,0.8624201 -0.44336,1.3867187 -0.07145,0.5199936 -0.10449,1.1622768 -0.03516,1.8886719 0.06961,0.7270467 0.23849,1.4961703 0.453125,2.2578125 0.116225,0.4135577 0.360097,0.9067637 0.539062,1.3593747 -0.124674,0.387256 -0.100594,0.614105 -0.248047,1.001953 -0.811007,2.133537 -2.00986,4.172291 -3.09375,5.833984 C 9.6076126,18.178918 8.9767686,18.349 8.4238281,18.617188 a 0.78507853,0.78507853 0 0 0 0,0.002 c -1.300128,0.633746 -2.2463357,1.311179 -2.8652343,1.914062 a 0.78507853,0.78507853 0 0 0 -0.00195,0.002 c -0.6150377,0.601268 -0.9099617,1.185535 -1.0195312,1.671875 -0.1131555,0.488823 -0.1123117,0.936293 0.1191406,1.367188 0.1160628,0.216074 0.3805554,0.464839 0.6640625,0.552734 0.2835071,0.08789 0.5249406,0.06426 0.7617187,0.02344 0.4698185,-0.08052 1.178971,-0.338041 2.0390626,-1.066407 a 0.78507853,0.78507853 0 0 0 0,-0.002 c 0.8555498,-0.728269 1.90404,-1.916204 3.117187,-3.71289 0.02965,-0.04389 0.05609,-0.119449 0.08594,-0.164063 0.619009,-0.221835 1.214261,-0.497822 1.777343,-0.662109 a 0.78507853,0.78507853 0 0 0 0.002,0 c 1.265958,-0.371309 2.241194,-0.568723 3.115234,-0.726563 0.69415,-0.125854 1.259949,-0.195883 1.830078,-0.257812 0.280443,0.299404 0.577624,0.678166 0.833984,0.933594 0.847119,0.844028 1.521046,1.404319 2.158204,1.853515 0.639412,0.45379 1.260701,0.816016 1.892578,1.003906 0.632499,0.188075 1.236796,0.152309 1.728515,-0.0059 h 0.002 c 0.492648,-0.156837 1.028923,-0.480429 1.306641,-1.068359 0.27926,-0.590135 0.254806,-1.263258 -0.02539,-1.884766 v -0.002 c -0.277429,-0.621438 -0.76698,-1.082945 -1.310546,-1.423828 -0.545569,-0.343597 -1.140709,-0.544023 -1.783204,-0.701172 a 0.78507853,0.78507853 0 0 0 -0.0039,0 c -0.641765,-0.153512 -1.373079,-0.276321 -2.128906,-0.337891 -0.662834,-0.05576 -1.341913,-0.04182 -2.027344,0 -0.458509,-0.510303 -0.908866,-0.959651 -1.328125,-1.490234 l -0.002,-0.002 C 16.533137,13.38291 15.857131,12.360517 15.412167,11.525305 l -0.002,-0.002 C 15.30273,11.320658 15.286009,11.175405 15.201172,10.990234 15.728256,9.2036124 16.257,7.3109218 16.369141,6.2539062 v -0.00195 C 16.437195,5.6152818 16.507219,5.2447694 16.488281,4.8339844 16.478799,4.6283109 16.434973,4.3732314 16.279297,4.140625 16.12631,3.9120375 15.904494,3.7749474 15.724609,3.6953125 15.596242,3.6171662 15.446816,3.504955 15.154297,3.4179688 c 0,0 -0.002,0 -0.002,0 -0.16459,-0.04944 -0.33216,-0.056649 -0.458985,-0.050781 z m 0.04297,1.5722656 c 0.007,0.00843 0.08535,0.049224 0.171875,0.09375 -0.0054,0.1485996 -0.03637,0.4604185 -0.09961,1.0527344 a 0.78507853,0.78507853 0 0 0 0,0.00195 C 14.762766,6.5198864 14.427443,7.4892563 14.300781,8.140625 14.251121,7.875652 14.161416,7.5793427 14.138672,7.3417969 14.082081,6.7489429 14.109623,6.2222248 14.166016,5.8125 a 0.78507853,0.78507853 0 0 0 0.002,-0.00195 c 0.05572,-0.4157015 0.150883,-0.6632171 0.189453,-0.7207031 0.03449,-0.051297 0.09649,-0.088673 0.158203,-0.1113282 a 0.78507853,0.78507853 0 0 0 0.0078,-0.00195 c 0.05934,-0.022535 0.01189,-0.00636 0.177734,-0.029297 a 0.78507853,0.78507853 0 0 0 0.0078,-0.00195 c 0.03223,-0.0048 0.01382,-0.00327 0.02734,-0.00586 z m -0.166016,8.1367189 c 0.45422,0.749165 0.907843,1.504827 1.558594,2.330078 a 0.78507853,0.78507853 0 0 0 0.002,0.002 c 0.212041,0.268402 0.439315,0.478063 0.664063,0.744141 -0.289041,0.04582 -0.543783,0.06263 -0.855469,0.11914 -0.897959,0.16216 -1.947255,0.372981 -3.279297,0.763672 -0.07324,0.02137 -0.157644,0.06549 -0.232422,0.08789 0.761585,-1.29696 1.538661,-2.547287 2.142578,-4.046875 z m 5.546876,4.414062 c 0.155146,0.007 0.319437,-0.01291 0.472656,0 a 0.78507853,0.78507853 0 0 0 0.002,0 c 0.668173,0.05443 1.32839,0.166294 1.890625,0.300782 0.558006,0.136662 0.976583,0.287933 1.316406,0.501953 a 0.78507853,0.78507853 0 0 0 0.002,0.002 c 0.339545,0.212792 0.610464,0.510926 0.710938,0.736328 a 0.78507853,0.78507853 0 0 0 0.002,0.0039 c 0.102983,0.227958 0.07751,0.487105 0.03906,0.56836 a 0.78507853,0.78507853 0 0 0 -0.002,0.002 c -0.03798,0.08076 -0.1337,0.170789 -0.365234,0.24414 a 0.78507853,0.78507853 0 0 0 -0.0039,0 c -0.233981,0.07542 -0.451996,0.09789 -0.800782,-0.0059 -0.349344,-0.103878 -0.871888,-0.381873 -1.43164,-0.779297 a 0.78507853,0.78507853 0 0 0 -0.002,-0.002 c -0.526291,-0.371035 -1.10733,-0.864339 -1.830078,-1.572266 z m -12.0332036,3.21875 c -0.3048861,0.330032 -0.7412086,0.97407 -0.9804688,1.177735 -0.5050917,0.427165 -0.7097885,0.450846 -0.9414062,0.523437 0.057454,-0.191804 0.1098768,-0.378201 0.4921875,-0.751953 0.2695888,-0.262612 0.9183916,-0.618869 1.4296875,-0.949219 z" /></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,15 @@
<svg xmlns='http://www.w3.org/2000/svg' version='1.1'>
<defs>
<filter id='goo-menu'>
<feGaussianBlur in='SourceGraphic' stdDeviation='3' result='blur' />
<feColorMatrix in='blur' mode='matrix' values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 15 -5' result='goo' />
<feComposite in='SourceGraphic' in2='goo' operator='atop'/>
</filter>
<filter id='goo-rocket'>
<feGaussianBlur in='SourceGraphic' stdDeviation='13' result='blur' />
<feColorMatrix in='blur' mode='matrix' values='1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 20 -10' result='goo' />
<feComposite in='SourceGraphic' in2='goo' operator='atop'/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 645 B

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
width="36px"
viewBox="0 0 36 30"
version="1.1"
id="Layer_1"
height="30px"
enable-background="new 0 0 36 30"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><polygon
style="fill:#231f20"
id="fill-edit"
points="22,25 22,17 35.999,0 17.988,0 0,0 14,17 14,30 " /></svg>

After

Width:  |  Height:  |  Size: 823 B

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="64"
height="64"
viewBox="0 0 16.933333 16.933334"
version="1.1"
id="svg845"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="icon.svg">
<defs
id="defs839" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="38.000412"
inkscape:cy="14.377036"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-page="true"
inkscape:window-width="1920"
inkscape:window-height="1015"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1" />
<metadata
id="metadata842">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-280.06665)">
<g
id="g877"
transform="matrix(0.19411325,0,0,0.19411325,-3.8930111,276.16682)">
<path
id="path855"
d="m 55.300781,71.720703 c -1.125,1.025 -2.18789,2.106641 -3.15039,3.251953 -0.9625,1.145313 -1.825782,2.355469 -2.550782,3.636719 -0.725,1.28125 -1.312109,2.633594 -1.724609,4.066406 -0.4125,1.432813 -0.648828,2.944922 -0.673828,4.544922 0,1.75 0.21875,3.532032 0.640625,5.277344 0.421875,1.745312 1.046875,3.454297 1.859375,5.060547 0.8125,1.606249 1.8125,3.110546 2.984375,4.443356 1.171875,1.33282 2.515625,2.49493 4.015625,3.41993 0.925,0.575 1.8625,1.01347 2.794922,1.32421 0.932422,0.31075 1.858984,0.49297 2.763672,0.55469 0.904687,0.0617 1.787109,0.004 2.628906,-0.16797 0.841797,-0.17207 1.642969,-0.45898 2.386719,-0.84961 0.74375,-0.39062 1.430468,-0.88652 2.041015,-1.48047 0.610547,-0.59394 1.145703,-1.28437 1.587891,-2.0664 0.442187,-0.78203 0.790625,-1.65449 1.029297,-2.60938 0.238672,-0.954879 0.367187,-1.992966 0.367187,-3.105466 0.025,-1.85 -0.30664,-3.6625 -0.892578,-5.421875 -0.585937,-1.759375 -1.426172,-3.466015 -2.419922,-5.103515 -0.99375,-1.6375 -2.141406,-3.205078 -3.339843,-4.689453 C 64.45,80.322266 63.2,78.921094 62,77.621094 c -2,-2.2 -4.299219,-4.100391 -6.699219,-5.900391 z"
style="fill:#de5b0e;fill-opacity:1;stroke:none;stroke-width:13.06582642;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.83406115"
inkscape:connector-curvature="0" />
<path
id="path853"
d="m 57.630859,20.091797 c -2.096093,-0.02266 -4.229101,0.24668 -6.375,0.853515 -1.072949,0.303418 -2.149731,0.692505 -3.226562,1.169922 -1.076831,0.477417 -2.153516,1.044532 -3.228516,1.707032 -1.1125,0.7 -2.121093,1.527148 -3.021484,2.457031 -0.900391,0.929883 -1.692188,1.961328 -2.375,3.068359 -0.682813,1.107031 -1.257031,2.290039 -1.716797,3.521485 -0.459766,1.231445 -0.805859,2.511328 -1.037109,3.814453 -0.23125,1.303125 -0.346485,2.629101 -0.34375,3.951172 0.0027,1.32207 0.123047,2.641406 0.365234,3.929687 0.242187,1.288281 0.606641,2.546289 1.09375,3.748047 0.487109,1.201758 1.096484,2.345703 1.833984,3.408203 0.85,1.225 1.8375,2.344141 2.914063,3.384766 1.076562,1.040625 2.242969,2.003515 3.449219,2.916015 2.4125,1.825 4.98789,3.44961 7.33789,5.09961 2.25,1.6 4.45,3.251172 6.5625,5.013672 2.1125,1.7625 4.13711,3.6375 6.03711,5.6875 1.55,1.675 3.124609,3.48125 4.599609,5.398437 1.475,1.917188 2.85,3.94375 4,6.0625 1.15,2.11875 2.075391,4.329688 2.650391,6.609375 0.2875,1.139844 0.487109,2.296289 0.583984,3.46875 0.09687,1.172461 0.0918,2.360547 -0.0332,3.560547 1.7625,-1.8 3.349023,-3.737891 4.761719,-5.787109 1.412695,-2.049219 2.651562,-4.210157 3.714843,-6.457032 1.063282,-2.246875 1.951758,-4.579687 2.666016,-6.972656 0.714258,-2.392969 1.253516,-4.846484 1.619141,-7.333984 0.365625,-2.4875 0.556836,-5.008594 0.574218,-7.539063 0.01738,-2.530468 -0.138281,-5.069922 -0.46875,-7.591797 C 90.237891,54.718359 89.732617,52.213672 89.054688,49.751953 88.376758,47.290234 87.525,44.871484 86.5,42.521484 c -0.8375,-1.9375 -1.848242,-3.847461 -3.009766,-5.6875 -1.161523,-1.840039 -2.474218,-3.609765 -3.914062,-5.263672 -1.439844,-1.653906 -3.007227,-3.193164 -4.679688,-4.572265 -1.672461,-1.379102 -3.449218,-2.597656 -5.308593,-3.613281 -1.859375,-1.015625 -3.800196,-1.827149 -5.800782,-2.390625 -2.000586,-0.563477 -4.060156,-0.879688 -6.15625,-0.902344 z"
style="fill:#dd9d15;fill-opacity:1;stroke:none;stroke-width:13.06582642;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.83406115"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 500 500"
height="500px"
id="Layer_1"
version="1.1"
viewBox="0 0 500 500"
width="500px"
xml:space="preserve"
sodipodi:docname="manage.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="0.472"
inkscape:cx="-167.37288"
inkscape:cy="250"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="m 31.949,403.452 c 0,35.164 28.435,63.599 63.599,63.599 17.529,0 33.891,-6.637 45.426,-18.172 l 115.93,-116.018 31.072,31.071 c -4.182,15.265 -0.181,32.345 11.905,44.518 l 45.063,45.063 c 17.985,17.901 46.782,18.08 64.504,0.362 17.719,-17.721 17.539,-46.511 -0.366,-64.504 L 364.019,344.308 C 351.845,332.223 334.765,328.23 319.505,332.41 l -31.072,-30.991 19.983,-19.983 c 42.516,10.722 89.397,-0.459 122.563,-32.888 22.803,-22.35 35.352,-50.698 37.07,-80.04 v -1.543 c 0,-9.91 -8.181,-17.905 -18.26,-17.905 -5.001,0 -9.544,2.006 -12.907,5.181 l -5.353,5.271 -18.356,17.985 c -11.543,11.268 -27.984,17.896 -45.701,17.896 -17.622,0 -33.165,-7.718 -44.701,-19.076 -11.355,-11.533 -19.166,-27.167 -19.166,-44.788 0,-17.717 6.63,-34.159 17.897,-45.702 l 17.985,-18.358 5.269,-5.351 c 3.18,-3.363 5.181,-7.906 5.181,-12.91 0,-10.079 -7.992,-18.26 -17.904,-18.26 h -1.544 c -29.34,1.721 -57.687,14.268 -80.038,37.071 -32.43,33.165 -43.52,80.047 -32.802,122.477 L 197.58,210.565 113.717,126.622 V 103.634 L 59.205,76.376 31.949,103.632 59.205,158.145 h 22.891 l 83.951,83.863 -115.928,116.018 c -11.533,11.535 -18.17,27.897 -18.17,45.426 z m 45.426,-4.543 c 0,-12.536 10.177,-22.711 22.714,-22.711 12.538,0 22.713,10.175 22.713,22.711 0,12.536 -10.175,22.716 -22.713,22.716 -12.536,0 -22.714,-10.18 -22.714,-22.716 z"
id="fill-edit"
style="clip-rule:evenodd;fill:#f2f2f2;fill-rule:evenodd"
inkscape:connector-curvature="0" /></svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 500 500"
height="500px"
id="Layer_1"
version="1.1"
viewBox="0 0 500 500"
width="500px"
xml:space="preserve"
sodipodi:docname="pin-disabled.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="0.6675088"
inkscape:cx="186.10652"
inkscape:cy="69.51775"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"
inkscape:snap-page="true" /><path
style="clip-rule:evenodd;fill:#010101;fill-rule:evenodd"
d="M 463.1543 1 L 349.9375 114.2168 L 349.9375 77.375 L 363.56836 77.375 C 376.10336 77.375 386.2832 67.198109 386.2832 54.662109 C 386.2832 42.126109 376.10336 31.949219 363.56836 31.949219 L 136.43164 31.949219 C 123.89564 31.949219 113.71875 42.126109 113.71875 54.662109 C 113.71875 67.199109 123.89564 77.375 136.43164 77.375 L 150.06055 77.375 L 150.06055 232.73828 L 82.828125 300.60742 C 79.465125 303.87442 77.376953 308.50466 77.376953 313.59766 C 77.376953 323.58866 85.459234 331.77148 95.365234 331.77148 L 132.38281 331.77148 L 1 463.1543 L 36.845703 499 L 499 36.845703 L 463.1543 1 z M 213.6582 77.375 C 223.6532 77.375 231.83008 85.552828 231.83008 95.548828 L 231.83008 213.65625 C 231.83008 223.65225 223.6542 231.82812 213.6582 231.82812 C 203.6642 231.82812 195.48633 223.65225 195.48633 213.65625 L 195.48633 95.548828 C 195.48633 85.552828 203.6642 77.375 213.6582 77.375 z M 352.55469 235.29102 L 222.74414 365.10156 L 222.74414 445.33984 C 222.74414 457.87584 232.92103 468.05078 245.45703 468.05078 C 257.99403 468.05078 268.17188 457.87584 268.17188 445.33984 L 268.17188 331.77148 L 404.63281 331.77148 C 414.53181 331.77148 422.62305 323.58866 422.62305 313.59766 C 422.62305 308.60466 420.61847 304.06211 417.35547 300.78711 L 352.55469 235.29102 z "
id="fill-edit" /></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 500 500"
height="500px"
id="Layer_1"
version="1.1"
viewBox="0 0 500 500"
width="500px"
xml:space="preserve"
sodipodi:docname="pin.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="0.6675088"
inkscape:cx="186.10652"
inkscape:cy="69.51775"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1"
inkscape:snap-page="true" /><path
d="m 150.061,232.739 -67.232,67.868 c -3.363,3.267 -5.453,7.898 -5.453,12.991 0,9.991 8.083,18.173 17.989,18.173 H 222.744 V 445.34 c 0,12.536 10.177,22.711 22.713,22.711 12.537,0 22.715,-10.175 22.715,-22.711 V 331.771 h 136.46 c 9.899,0 17.992,-8.182 17.992,-18.173 0,-4.993 -2.006,-9.536 -5.269,-12.811 L 349.938,232.644 V 77.375 h 13.631 c 12.535,0 22.715,-10.177 22.715,-22.713 0,-12.536 -10.18,-22.713 -22.715,-22.713 H 136.432 c -12.536,0 -22.713,10.177 -22.713,22.713 0,12.537 10.177,22.713 22.713,22.713 h 13.629 V 232.739 Z M 231.83,95.548 v 118.109 c 0,9.996 -8.176,18.172 -18.172,18.172 -9.994,0 -18.171,-8.176 -18.171,-18.172 V 95.548 c 0,-9.996 8.177,-18.173 18.171,-18.173 9.995,0 18.172,8.177 18.172,18.173 z"
id="fill-edit"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill:#010101;fill-rule:evenodd" /></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
viewBox="0 0 512 512"
version="1.1"
style="enable-background:new 0 0 512 512;"
id="Layer_1"><metadata
id="metadata25"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs23" /><style
id="style2"
type="text/css">
.st0{fill:#5BB28E;stroke:#414042;stroke-width:20;stroke-miterlimit:10;}
.st1{fill:#AEDEEF;}
.st2{fill:#6DC5A5;}
.st3{fill:#F15A29;stroke:#414042;stroke-width:14;stroke-miterlimit:10;}
.st4{fill:#414042;}
.st5{fill:none;stroke:#414042;stroke-width:14;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
.st6{fill:#F9ED32;stroke:#414042;stroke-width:14;stroke-miterlimit:10;}
</style><circle
r="195.1"
id="XMLID_363_"
cy="247.6"
cx="256.9"
class="st0" /><path
id="XMLID_362_"
d="M439.6,249.7c0,97.4-54,167.5-151.1,181.3c-96.3,13.7-201.1-83.9-201.1-181.3 S166.2,63.5,263.5,63.5S439.6,152.3,439.6,249.7z"
class="st1" /><path
id="XMLID_361_"
d="M431,248.9c0,96.4-53.6,165.8-150,179.5c-95.6,13.5-199.6-83.1-199.6-179.5 S159.7,64.5,256.2,63.5C369.6,62.3,431,152.5,431,248.9z"
class="st2" /><circle
r="41.1"
id="XMLID_360_"
cy="260.5"
cx="205.6"
class="st3" /><circle
r="5"
id="XMLID_359_"
cy="41.8"
cx="103.9"
class="st4" /><circle
r="5"
id="XMLID_358_"
cy="310.2"
cx="239.3"
class="st4" /><circle
r="11.3"
id="XMLID_357_"
cy="422.7"
cx="120.2"
class="st4" /><circle
r="5"
id="XMLID_356_"
cy="470.5"
cx="334.5"
class="st4" /><circle
r="5"
id="XMLID_354_"
cy="160.7"
cx="254.2"
class="st4" /><circle
r="7.7"
id="XMLID_353_"
cy="160.7"
cx="279.6"
class="st4" /><path
id="XMLID_352_"
d="M274.1,394.2c7.9-5.6,17.6-8.8,28-8.8c27,0,48.9,21.9,48.9,48.9c0,9.6-2.8,18.6-7.6,26.2"
class="st5" /><circle
r="15.1"
id="XMLID_351_"
cy="82.1"
cx="81.4"
class="st6" /><circle
r="15.2"
id="XMLID_23_"
cy="300.2"
cx="287.3"
class="st3" /><circle
r="9.6"
id="XMLID_355_"
cy="324.6"
cx="189.6"
class="st4" /><circle
r="5"
id="XMLID_42_"
cy="442.6"
cx="164.6"
class="st4" /><circle
r="15.1"
id="XMLID_43_"
cy="445.3"
cx="389.5"
class="st6" /></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 24 24"
height="24px"
id="Layer_1"
version="1.1"
viewBox="0 0 24 24"
width="24px"
xml:space="preserve"
sodipodi:docname="plus.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview5"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="m 23.008475,14.610169 h -8.5 v 8.5 c 0,0.276 -0.224,0.5 -0.5,0.5 h -4 c -0.2760004,0 -0.5000004,-0.224 -0.5000004,-0.5 v -8.5 h -8.5 c -0.27600002,0 -0.50000002,-0.224 -0.50000002,-0.5 v -4 c 0,-0.2759995 0.224,-0.4999995 0.50000002,-0.4999995 h 8.5 v -8.5 c 0,-0.27600001 0.224,-0.50000001 0.5000004,-0.50000001 h 4 c 0.276,0 0.5,0.224 0.5,0.50000001 v 8.5 h 8.5 c 0.276,0 0.5,0.224 0.5,0.4999995 v 4 c 0,0.276 -0.224,0.5 -0.5,0.5 z"
id="fill-edit"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill-rule:evenodd" /></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="48"
viewBox="0 0 48 48"
width="48"
version="1.1"
id="svg6"
sodipodi:docname="remove.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1280"
inkscape:window-height="684"
id="namedview8"
showgrid="false"
inkscape:zoom="4.9166667"
inkscape:cx="24"
inkscape:cy="24"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="m 12,38 c 0,2.21 1.79,4 4,4 h 16 c 2.21,0 4,-1.79 4,-4 V 14 H 12 Z M 38,8 H 31 L 29,6 H 19 l -2,2 h -7 v 4 h 28 z"
id="fill-edit"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="32"
viewBox="0 0 32 32"
width="32"
version="1.1"
id="svg6"
sodipodi:docname="switch.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1022"
id="namedview8"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="4.9166667"
inkscape:cx="24"
inkscape:cy="29.898306"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="M 23.384615,24.615384 V 18.461538 H 8.615385 v 6.153846 L 0,15.999999 8.615385,7.3846151 v 6.1538459 h 14.76923 V 7.3846151 L 32,15.999999 Z"
id="fill-edit"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc"
style="stroke-width:1.23076928" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="16px"
version="1.1"
viewBox="0 0 16 16"
width="16px"
id="svg9"
sodipodi:docname="td.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata13">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1280"
inkscape:window-height="684"
id="namedview11"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="8"
inkscape:cy="8"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg9" />
<defs
id="defs4" />
<path
d="M 1,11.95081 5,16 H 1 Z M 8,4 12,8 5.97864,15.04419 2,11 Z m 2.08462,-2.2185 c 0.62484,-0.62484 1.82467,-0.43807 2.6799,0.41715 l 0.77426,0.77427 c 0.85523,0.85523 1.042,2.05506 0.41716,2.6799 L 12.72039,6.88836 8.84907,3.01704 Z m 0,0"
id="fill-edit"
inkscape:connector-curvature="0"
style="fill:#000000;fill-rule:evenodd;stroke:none;stroke-width:1" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 24 24"
id="Layer_1"
version="1.0"
viewBox="0 0 24 24"
xml:space="preserve"
sodipodi:docname="teacher.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs11" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1044"
id="namedview9"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="M 12,3 1,9 12,15 21,10.091797 V 17 h 2 V 9 Z m -7,9.800781 v 4.398438 L 12,21 19,17.199219 V 12.800781 L 12,17 Z"
id="fill-edit"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 24 24"
height="24px"
id="Layer_1"
version="1.1"
viewBox="0 0 24 24"
width="24px"
xml:space="preserve"
sodipodi:docname="time.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs11" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview9"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="m 12,2.0344069 c -5.5018378,0 -9.9631017,4.4620943 -9.9631017,9.9655931 0,5.503499 4.4612639,9.965593 9.9631017,9.965593 5.502668,0 9.963102,-4.462094 9.963102,-9.965593 0,-5.5034988 -4.460434,-9.9655931 -9.963102,-9.9655931 z m 3.664016,13.8762581 -0.290663,0.290663 c -0.241665,0.241666 -0.649424,0.253292 -0.903547,0.02408 l -3.753707,-3.28449 C 10.460316,12.71254 10.266817,12.244987 10.283427,11.902835 l 0.347965,-5.9245446 c 0.01827,-0.3429825 0.313086,-0.6220191 0.656068,-0.6220191 h 0.40942 c 0.342982,0 0.636967,0.2790366 0.653577,0.6211886 l 0.28485,4.9279861 c 0.01744,0.342982 0.217582,0.830466 0.444299,1.08708 l 2.610985,3.012931 c 0.226718,0.256614 0.215921,0.663542 -0.02657,0.905208 z"
id="fill-edit"
inkscape:connector-curvature="0"
style="clip-rule:evenodd;fill-rule:evenodd;stroke-width:0.83046609" /></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 64 64"
height="64px"
id="Layer_1"
version="1.1"
viewBox="0 0 64 64"
width="64px"
xml:space="preserve"
sodipodi:docname="tp.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata13"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs11" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview9"
showgrid="false"
inkscape:zoom="3.6875"
inkscape:cx="33.355932"
inkscape:cy="32"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
style="fill:#241f20"
d="m 9.6328125,7.9785156 c -1.758,0 -3.1816406,1.4256406 -3.1816406,3.1816404 v 36.519532 c 0,0 0.00895,0.197187 0.00195,0.492187 -0.001,0.01 0,0.01544 0,0.02344 0,0.319001 -0.030172,0.592844 -0.076172,0.839844 -0.003,0.019 -0.00677,0.03564 -0.00977,0.05664 -0.363,1.783 -1.7910156,1.769531 -1.7910156,1.769531 h -1.953125 c -1.425,0 -2.57812503,1.155078 -2.57812503,2.580078 0,1.424 1.15312503,2.578125 2.57812503,2.578125 H 61.376953 c 1.422,0 2.578125,-1.154125 2.578125,-2.578125 0,-1.424 -1.156125,-2.580078 -2.578125,-2.580078 h -2.005859 c -0.463,-0.012 -1.976891,-0.259734 -1.962891,-3.052734 0,-0.045 0.01172,-0.08691 0.01172,-0.128906 V 11.160156 c 0,-1.7559998 -1.425641,-3.1816404 -3.181641,-3.1816404 z m 3.4960935,2.9667964 h 37.779297 c 1.748,0 3.166016,1.407579 3.166016,3.142579 v 30.345703 c 0,1.735 -1.418016,3.142578 -3.166016,3.142578 H 13.128906 c -1.747,0 -3.1640622,-1.406578 -3.1640622,-3.142578 V 14.087891 c 0,-1.735 1.4160622,-3.142579 3.1640622,-3.142579 z m 3.464844,3.06836 c -1.657,0 -2.998047,1.373406 -2.998047,3.066406 v 24.16211 c 0,1.692999 1.342047,3.066406 2.998047,3.066406 h 31.089844 c 1.656,0 2.996094,-1.373407 2.996094,-3.066406 v -24.16211 c -10e-7,-1.693 -1.340094,-3.066406 -2.996094,-3.066406 z"
id="fill-edit"
inkscape:connector-curvature="0" /></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
enable-background="new 0 0 24 24"
height="24px"
id="Layer_1"
version="1.1"
viewBox="0 0 24 24"
width="24px"
xml:space="preserve"
sodipodi:docname="ue.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06"><metadata
id="metadata9"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs7" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1044"
id="namedview5"
showgrid="false"
inkscape:zoom="9.8333333"
inkscape:cx="12"
inkscape:cy="12"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><path
d="M 20.898304,1.4237288 H 3.2711866 c -0.5288136,0 -0.881356,0.3525424 -0.881356,0.8813559 V 21.694915 c 0,0.528814 0.3525424,0.881356 0.881356,0.881356 H 20.898304 c 0.528814,0 0.881356,-0.352542 0.881356,-0.881356 V 2.3050847 c 0,-0.5288135 -0.352542,-0.8813559 -0.881356,-0.8813559 z M 10.322033,2.3050847 V 13.938983 L 8.5593222,12.616949 6.7966103,13.938983 V 2.3050847 Z M 20.016948,20.813559 H 4.1525425 V 19.050847 H 20.016948 Z m 0,-2.644067 H 4.1525425 V 3.1864407 H 5.9152544 V 15.525424 l 2.6440678,-1.762712 2.6440668,1.762712 V 3.1864407 h 8.813559 z"
id="fill-edit"
inkscape:connector-curvature="0"
style="stroke-width:0.88135594" /></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="48"
viewBox="0 0 48 48"
width="48"
version="1.1"
id="svg6"
sodipodi:docname="up_arrow.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview8"
showgrid="false"
inkscape:zoom="4.9166667"
inkscape:cx="24"
inkscape:cy="24"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<path
d="M 33.17,31.25 24,22.08 14.83,31.25 12,28.42 l 12,-12 12,12 z"
id="fill-edit"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="1792"
viewBox="0 0 1792 1792"
width="1792"
version="1.1"
id="svg4"
sodipodi:docname="warning_radio.svg"
inkscape:version="0.92.2 5c3e80d, 2017-08-06">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview6"
showgrid="false"
inkscape:zoom="0.13169643"
inkscape:cx="896"
inkscape:cy="896"
inkscape:window-x="0"
inkscape:window-y="29"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<path
d="m 1024,1375 v -190 q 0,-14 -9.5,-23.5 Q 1005,1152 992,1152 H 800 q -13,0 -22.5,9.5 -9.5,9.5 -9.5,23.5 v 190 q 0,14 9.5,23.5 9.5,9.5 22.5,9.5 h 192 q 13,0 22.5,-9.5 9.5,-9.5 9.5,-23.5 z m -2,-374 18,-459 q 0,-12 -10,-19 -13,-11 -24,-11 H 786 q -11,0 -24,11 -10,7 -10,21 l 17,457 q 0,10 10,16.5 10,6.5 24,6.5 h 185 q 14,0 23.5,-6.5 9.5,-6.5 10.5,-16.5 z m -14,-934 768,1408 q 35,63 -2,126 -17,29 -46.5,46 -29.5,17 -63.5,17 H 128 Q 94,1664 64.5,1647 35,1630 18,1601 -19,1538 16,1475 L 784,67 q 17,-31 47,-49 30,-18 65,-18 35,0 65,18 30,18 47,49 z"
id="fill-edit"
inkscape:connector-curvature="0" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

View File

@ -1,15 +1,45 @@
<?php http_response_code(404); ?>
<!DOCTYPE html>
<html lang="en">
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=0.4">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Erreur 404 - Ressource introuvable</title>
<title>404 - Ressource introuvable</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/global.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
</head>
<body>
La ressource est introuvable.
<body class='body404'>
<div id='cont404'>
<p>Vous êtes sur la mauvaise planète</p>
<p></p>
<div id='rocket'>
<a href='/home/'><svg height="32" version="1.1" width="32" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"> <path d="m 16,0.15625 c -0.63709,0 -1.18409,0.28275 -1.5625,0.71875 -0.37841,0.436 -0.60769,1.00265 -0.78125,1.65625 -0.0912,0.3436 -0.15107,0.7323 -0.21875,1.125 l -0.0625,0.4375 c -0.15358,1.0022 -0.29194,2.0988 -0.46875,3.3125 -0.54801,3.7619 -1.62958,8.1588 -5.75,11.1875 L 6.9375,18.75 v 0.25 2.21875 0.5 h 0.5 5.03125 l 0.3125,1.53125 0.09375,0.40625 h 0.40625 5.4375 0.40625 l 0.09375,-0.40625 0.3125,-1.53125 h 5.03125 0.5 v -0.5 V 19 18.75 L 24.84375,18.59375 C 20.72415,15.56565 19.66719,11.17425 19.125,7.40625 18.85391,5.52235 18.7249,3.8066 18.375,2.5 18.20005,1.8467 17.97744,1.27705 17.59375,0.84375 17.21006,0.41035 16.64165,0.15295 16,0.15625 Z m 0,1 c 0.40043,0 0.62416,0.127 0.84375,0.375 0.21959,0.2481 0.40849,0.64365 0.5625,1.21875 0.0723,0.2699 0.16152,0.57915 0.21875,0.90625 h -3.1875 c 0.0575,-0.3123 0.1185,-0.6152 0.1875,-0.875 0.15316,-0.5768 0.34415,-0.9984 0.5625,-1.25 0.21835,-0.2515 0.41943,-0.3727 0.8125,-0.375 z m -1.6875,3.5 h 3.40625 c 0.30049,2.176 0.53332,5.0501 1.375,8 H 12.9375 c 0.84681,-2.9505 1.0731,-5.8244 1.375,-8 z M 16,5.21875 c -0.86882,0 -1.5625,0.72345 -1.5625,1.59375 0,0.8702 0.69368,1.59375 1.5625,1.59375 0.86882,0 1.59375,-0.72355 1.59375,-1.59375 0,-0.8703 -0.72493,-1.59375 -1.59375,-1.59375 z m 0,1 c 0.31568,0 0.59375,0.25145 0.59375,0.59375 0,0.3422 -0.27807,0.59375 -0.59375,0.59375 -0.31568,0 -0.5625,-0.25155 -0.5625,-0.59375 0,-0.3423 0.24682,-0.59375 0.5625,-0.59375 z m 0,2.875 c -0.77011,0 -1.375,0.6684 -1.375,1.4375 0,0.7692 0.60489,1.40625 1.375,1.40625 0.77011,0 1.40625,-0.63705 1.40625,-1.40625 0,-0.7691 -0.63614,-1.4375 -1.40625,-1.4375 z m 0,1 c 0.21697,0 0.40625,0.1963 0.40625,0.4375 0,0.2413 -0.18928,0.40625 -0.40625,0.40625 -0.21697,0 -0.375,-0.16495 -0.375,-0.40625 0,-0.2412 0.15803,-0.4375 0.375,-0.4375 z m -3.75,3.5625 h 0.03125 7.4375 0.03125 c 0.78472,1.7887 1.91786,3.5096 3.625,5 H 8.625 c 1.70708,-1.4891 2.8409,-3.2171 3.625,-5 z m 2.09375,1 a 0.50606671,0.50606671 0 0 0 0.15625,1 h 3 a 0.50005,0.50005 0 1 0 0,-1 h -3 a 0.50005,0.50005 0 0 0 -0.09375,0 0.50219246,0.50219246 0 0 0 -0.0625,0 z m 0,2 a 0.50606671,0.50606671 0 0 0 0.15625,1 h 3 a 0.50005,0.50005 0 1 0 0,-1 h -3 a 0.50005,0.50005 0 0 0 -0.09375,0 0.50219246,0.50219246 0 0 0 -0.0625,0 z m -6.40625,3 h 16.125 v 1.0625 H 19.15625 18.75 l -0.09375,0.40625 -0.3125,1.53125 h -4.6875 L 13.34375,21.125 13.25,20.71875 H 12.84375 7.9375 Z m 8.0625,4.5 c -0.3763,0 -0.84315,0.04905 -1.3125,0.28125 -0.46935,0.2323 -0.91591,0.67385 -1.21875,1.34375 -0.24027,0.5316 -0.11557,1.05775 0.0625,1.65625 0.17807,0.5985 0.45714,1.2666 0.75,1.875 0.58573,1.2167 1.25,2.25 1.25,2.25 L 15.9375,32.25 16.375,31.59375 c 0,0 0.6613,-1.0448 1.28125,-2.25 0.30998,-0.6027 0.62382,-1.23695 0.8125,-1.84375 0.18868,-0.6068 0.3003,-1.17495 0.0625,-1.71875 C 18.21583,25.06025 17.7915,24.597 17.3125,24.375 16.8335,24.153 16.3525,24.15625 16,24.15625 Z m 0,1.03125 c 0.1717,0 0.2622,-0.01 0.4375,0.3125 -0.0121,0 0.01545,0.11925 -0.03125,0.28125 -0.0624,0.2157 -0.18623,0.51305 -0.3125,0.78125 C 16.04765,26.6605 16.0464,26.6585 16,26.75 15.9556,26.657 15.95025,26.662 15.90625,26.5625 15.78596,26.2909 15.65322,25.99735 15.59375,25.78125 15.54915,25.61925 15.5775,25.4895 15.5625,25.5 15.72406,25.2305 15.86961,25.1887 16,25.1875 Z m 1.40625,0.59375 c 0.076,0.1154 0.14453,0.23655 0.21875,0.40625 0.0416,0.095 0.0348,0.486 -0.125,1 -0.15981,0.514 -0.42437,1.14655 -0.71875,1.71875 -0.38784,0.754 -0.57136,1.02295 -0.8125,1.40625 C 15.73976,29.9188 15.55484,29.6381 15.1875,28.875 14.90807,28.2945 14.65228,27.66815 14.5,27.15625 14.34772,26.64445 14.35161,26.2392 14.375,26.1875 c 0.0705,-0.156 0.14235,-0.2684 0.21875,-0.375 0.0202,0.073 0.0416,0.14285 0.0625,0.21875 0.0823,0.2991 0.18079,0.6401 0.3125,0.9375 0.26343,0.5947 0.5625,1.09375 0.5625,1.09375 l 0.4375,0.78125 0.4375,-0.75 c 0,0 0.31531,-0.5337 0.59375,-1.125 0.13922,-0.2957 0.25607,-0.60305 0.34375,-0.90625 0.0282,-0.098 0.0409,-0.18385 0.0625,-0.28125 z" id="fill-edit"></svg></a>
</div>
<p></p>
<p>Prenez la fusée pour retourner à l'accueil en un clic</p>
</div>
</body>
</html>

View File

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=.6">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Espace enseignant</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Fira+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<body>
<div id="WRAPPER" class='login'>
<div id='LOGIN_REDIRECT'>
<div class='icon'></div>
<div class='title'><b>P</b><i>lateforme</i> <b>A</b><i>ssistée de</i> <b>T</b><i>raitement</i> <b>A</b><i>dministratif des</i> <b>T</b><i>aches d'</i><b>E</b><i>nseignement</i></div>
<a href="/api/v/1.0/professor/pdf/<?php echo $_SESSION['CAS']["id"]; ?>"><button style='font-weight: normal; margin-bottom: 1em;'>Télécharger ma fiche</button></a>
<a href="/fiche/logout"><button style='font-weight: normal'>Me déconnecter</button></a>
</div>
</div>
</body>
</html>

View File

@ -3,29 +3,31 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=0.4">
<meta name="viewport" content="width=device-width, initial-scale=.6">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>PTUT web title</title>
<title>Connexion</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/global.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<link rel='stylesheet' type='text/css' href='/css/menu.css'>
<link rel='stylesheet' type='text/css' href='/css/header.css'>
<link rel='stylesheet' type='text/css' href='/css/container.css'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Fira+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/global.css'>
<link rel='stylesheet' type='text/css' href='/css/pop-up.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<link rel='stylesheet' type='text/css' href='/css/menu.css'>
<link rel='stylesheet' type='text/css' href='/css/header.css'>
<link rel='stylesheet' type='text/css' href='/css/container.css'>
<link rel='stylesheet' type='text/css' href='/css/container/svg.css'>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
</head>
<body>
<body class='loading'>
<div id='main-vue'></div>
@ -42,6 +44,7 @@
<!-- Main loop -->
<script type='text/javascript' src='/js/bundle@home.js'></script>
<script type='text/javascript' src='/js/bundle@home.js' onload="document.body.className=''"></script>
</body>
</html>

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=.6">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Connexion</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Fira+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/global.css'>
<link rel='stylesheet' type='text/css' href='/css/pop-up.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<link rel='stylesheet' type='text/css' href='/css/container-login.css'>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
</head>
<body class='loading'>
<div id='main-vue'></div>
<!-- POPUP WINDOW -->
<div id='POPUP'>
<div class='header'></div>
<div class='body'></div>
<div class='footer'></div>
</div>
<div id='POPUP-BG'></div>
<!-- Main loop -->
<script type='text/javascript' src='/js/bundle@login.js' onload="document.body.className=''"></script>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=.6">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Gestion des enseignants</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Fira+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/global.css'>
<link rel='stylesheet' type='text/css' href='/css/pop-up.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<link rel='stylesheet' type='text/css' href='/css/menu.css'>
<link rel='stylesheet' type='text/css' href='/css/header.css'>
<link rel='stylesheet' type='text/css' href='/css/container.css'>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
</head>
<body class='loading'>
<div id='main-vue'></div>
<!-- POPUP WINDOW -->
<div id='POPUP'>
<div class='header'></div>
<div class='body'></div>
<div class='footer'></div>
</div>
<div id='POPUP-BG'></div>
<!-- Main loop -->
<script type='text/javascript' src='/js/bundle@settings.js' onload="document.body.className=''"></script>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=.6">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Gestion des enseignants</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Fira+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/global.css'>
<link rel='stylesheet' type='text/css' href='/css/pop-up.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<link rel='stylesheet' type='text/css' href='/css/menu.css'>
<link rel='stylesheet' type='text/css' href='/css/header.css'>
<link rel='stylesheet' type='text/css' href='/css/container.css'>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
</head>
<body class='loading'>
<div id='main-vue'></div>
<!-- POPUP WINDOW -->
<div id='POPUP'>
<div class='header'></div>
<div class='body'></div>
<div class='footer'></div>
</div>
<div id='POPUP-BG'></div>
<!-- Main loop -->
<script type='text/javascript' src='/js/bundle@teacher.js' onload="document.body.className=''"></script>
</body>
</html>

48
public_html/page/ue.php Normal file
View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=.6">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Gestion des UEs</title>
<!-- Icon -->
<link rel='shortcut icon' href='/favicon.ico'>
<!-- CSS dependencies -->
<link href="https://fonts.googleapis.com/css?family=Fira+Sans" rel="stylesheet">
<link rel='stylesheet' type='text/css' href='/css/font-loader.css'>
<link rel='stylesheet' type='text/css' href='/css/global.css'>
<link rel='stylesheet' type='text/css' href='/css/pop-up.css'>
<link rel='stylesheet' type='text/css' href='/css/layout.css'>
<link rel='stylesheet' type='text/css' href='/css/menu.css'>
<link rel='stylesheet' type='text/css' href='/css/header.css'>
<link rel='stylesheet' type='text/css' href='/css/container.css'>
<!-- JS dependencies -->
<script type='text/javascript' src='/js/_SERVER.js'></script>
</head>
<body class='loading'>
<div id='main-vue'></div>
<!-- POPUP WINDOW -->
<div id='POPUP'>
<div class='header'></div>
<div class='body'></div>
<div class='footer'></div>
</div>
<div id='POPUP-BG'></div>
<!-- Main loop -->
<script type='text/javascript' src='/js/bundle@ue.js' onload="document.body.className=''"></script>
</body>
</html>

View File

@ -1,5 +1,5 @@
var path = require('path')
var webpack = require('webpack')
var path = require('path');
var webpack = require('webpack');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
@ -43,10 +43,46 @@ module.exports = [ {
output: {
path: path.resolve(__dirname, './public_html/js/bundle'),
publicPath: '/js/bundle/',
filename: 'home@[hash].js'
filename: 'home@0.js'
},
module: mod_common,
devtool: '#eval-source-map'
devtool: (process.env.NODE_ENV==='development') ? '#eval-source-map' : false
}, {
name: "teacher",
entry: './webpack/page/teacher.js',
output: {
path: path.resolve(__dirname, './public_html/js/bundle'),
publicPath: '/js/bundle/',
filename: 'teacher@0.js'
},
module: mod_common,
devtool: (process.env.NODE_ENV==='development') ? '#eval-source-map' : false
}, {
name: "ue",
entry: './webpack/page/ue.js',
output: {
path: path.resolve(__dirname, './public_html/js/bundle'),
publicPath: '/js/bundle/',
filename: 'ue@0.js'
},
module: mod_common,
devtool: (process.env.NODE_ENV==='development') ? '#eval-source-map' : false
}, {
name: "settings",
entry: './webpack/page/settings.js',
output: {
path: path.resolve(__dirname, './public_html/js/bundle'),
publicPath: '/js/bundle/',
filename: 'settings@0.js'
},
module: mod_common,
devtool: (process.env.NODE_ENV==='development') ? '#eval-source-map' : false
}, {
@ -55,17 +91,17 @@ module.exports = [ {
output: {
path: path.resolve(__dirname, './public_html/js/bundle'),
publicPath: '/js/bundle/',
filename: 'login@[hash].js'
filename: 'login@0.js'
},
module: mod_common,
devtool: '#eval-source-map'
devtool: (process.env.NODE_ENV==='development') ? '#eval-source-map' : false
} ]
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
@ -83,4 +119,5 @@ if (process.env.NODE_ENV === 'production') {
minimize: true
})
])
}

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