summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/classes/Registry.php14
-rw-r--r--core/classes/authentication/User.php5
-rw-r--r--docker-compose.yml4
-rw-r--r--public/app/config/setup_application.php5
-rw-r--r--public/app/controllers/Auth.php14
-rw-r--r--public/app/controllers/Office.php71
-rw-r--r--public/app/models/Access_model.php51
-rw-r--r--public/app/models/Content_model.php101
-rw-r--r--public/app/models/Office_model.php314
-rw-r--r--public/app/models/_info.md240
-rw-r--r--public/app/routes/frontend.php176
-rw-r--r--public/app/routes/user.php134
-rw-r--r--public/app/views/components/breadcrumbs.php30
-rw-r--r--public/app/views/components/courses_menu.php97
-rw-r--r--public/app/views/components/footer.php240
-rw-r--r--public/app/views/components/info.php28
-rw-r--r--public/app/views/components/lessons_list.php54
-rw-r--r--public/app/views/components/menu.php28
-rw-r--r--public/app/views/components/subcategories.php19
-rw-r--r--public/app/views/components/top_bar.php40
-rw-r--r--public/app/views/components/user-management.php65
-rw-r--r--public/app/views/js/pdf-designer/application.php7
-rw-r--r--public/app/views/js/submit/application-form.php33
-rw-r--r--public/app/views/user/panel.php12
-rw-r--r--public/assets/css/class.css6
25 files changed, 623 insertions, 1165 deletions
diff --git a/core/classes/Registry.php b/core/classes/Registry.php
index 02a1ec5..d6606f6 100644
--- a/core/classes/Registry.php
+++ b/core/classes/Registry.php
@@ -20,9 +20,9 @@
*/
class Registry
{
- /** STATIC PROPERTIES
- * -------------------------------------------------------------------------
- */
+
+ ## STATIC PROPERTIES
+ ## -------------------------------------------------------------------------
/** @var array $records
* keeps all ready-to-use records
@@ -46,9 +46,9 @@ class Registry
private static $wish = Array();
- /** METHODS
- * -------------------------------------------------------------------------
- */
+
+ ## METHODS
+ ## -------------------------------------------------------------------------
/** set
* --- -- -- - - -
@@ -108,7 +108,7 @@ class Registry
* the data/object/handler/etc until/if-ever is called.
*
* @param string $label : label / refference key
- * @param function :
+ * @param callback $function :
*/
static function vow($label, $function)
{
diff --git a/core/classes/authentication/User.php b/core/classes/authentication/User.php
index f6508ff..2257dc0 100644
--- a/core/classes/authentication/User.php
+++ b/core/classes/authentication/User.php
@@ -11,6 +11,10 @@
class User implements UserInterface
{
+ /** PROPERTIES
+ * -------------------------------------------------------------------------
+ */
+
// @var string
private $userName;
@@ -99,7 +103,6 @@ class User implements UserInterface
return $this;
}
-
/** setEnabled
*
* @param bool $enabled
diff --git a/docker-compose.yml b/docker-compose.yml
index 5af1295..a6b435a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,8 +11,8 @@ services:
build:
context: .
ports:
- # - "80:8080"
- - "1415:8080"
+ - "80:8080"
+ # - "1415:8080"
volumes:
- "./public:/var/www/public"
- "./core:/var/www/core"
diff --git a/public/app/config/setup_application.php b/public/app/config/setup_application.php
index 88dc176..4eb7a55 100644
--- a/public/app/config/setup_application.php
+++ b/public/app/config/setup_application.php
@@ -69,11 +69,12 @@ define('USER_ACCESS_TYPE', [
]);
-
-// ERRORS AND ERROR MESSAGES ///////////////////////////////////////////////////
+// MESSAGES ////////////////////////////////////////////////////////////////////
// -----------------------------------------------------------------------------
+// Error Mesagges, Warnings and other Common Mesages
define('EMPTY_REQUIRED_FIELDS', 'Δεν έχουν συμπληρωθεί όλα τα υποχρεωτικά πεδία');
+define('TICKET_EXPIRED', 'Η φόρμα που συμπληρώσατε φαίνεται να έχει λήξη. Ανανεώστε τη και προσπαθήστε πάλι.');
diff --git a/public/app/controllers/Auth.php b/public/app/controllers/Auth.php
index e2fe989..9f440ed 100644
--- a/public/app/controllers/Auth.php
+++ b/public/app/controllers/Auth.php
@@ -136,7 +136,7 @@ class Auth {
* setups and renders the form for a certain invitation
*
* NOTE:
- * after form is submited, client calls Auth::activate()
+ * after form is submited, client shall call Auth::activate()
*
* @param $id (string|MD5) : invitation code
*
@@ -144,15 +144,13 @@ class Auth {
public static function invitation($id)
{
// get user from invitation number
- $user_array = Registry::use('database')->query(
- "SELECT * FROM user WHERE invitation = :id",
- ['id' => $id]
- )->getFirst();
- if ($user_array == false) {
+ $user_array = Access_model::getUserByInvitation($id);
+
+ if ($user_array == false) { // no invitation ? serve error then die;
Render::view('error/404', ['moto' => 'Δεν βρέθηκε η πρόσκληση']);
die();
}
- $user = json_decode( json_encode($user_array, JSON_UNESCAPED_UNICODE)); // user in json format
+ $user = json_decode(json_encode($user_array, JSON_UNESCAPED_UNICODE));
// format form_setup to a json array
$form_setup = json_decode(json_encode(REGISTRATION_FORM, JSON_UNESCAPED_UNICODE));
@@ -342,6 +340,8 @@ class Auth {
public static function in_admin_group()
{
+ if (!self::is_connected()) return false;
+
$manager = new App_manager();
return ($manager->isGranted([1, 2, 3]));
}
diff --git a/public/app/controllers/Office.php b/public/app/controllers/Office.php
index 800247e..9ff4e14 100644
--- a/public/app/controllers/Office.php
+++ b/public/app/controllers/Office.php
@@ -6,7 +6,7 @@ use Registry;
use Render;
use app\controllers\Auth;
use app\extends\App_manager;
-use app\models\Cms_model;
+use app\models\Content_model;
use app\extends\Cache_service;
/** Office class
@@ -112,10 +112,13 @@ class Office {
- ## PETITIONS
- ## -------------------------------------------------------------------------
- ## secretarial support / teachers' requests and applications
+ ## -------------------------------------------------------------------------
+ ##
+ ## PETITION FORMS
+ ## secretarial support / serve forms for teachers' requests and applications
+ ##
+ ## -------------------------------------------------------------------------
/** request any (empty/new) petition form
@@ -200,7 +203,7 @@ class Office {
]);
// #5: create ticket; then render the view -----------------------------
- $ticket = self::create_ticket($ticket); // save ticket
+ $ticket = self::create_ticket(); // save ticket
Render::view('templates/application', [
'form' => $form,
'applier' => (($userData['prefix'] == 'η') ? 'Η Αιτούσα' : 'Ο Αιτών'),
@@ -263,12 +266,55 @@ class Office {
## -------------------------------------------------------------------------
##
+ ## PETITION SUBMITS
+ ## handle submits of forms
+ ##
+ ## -------------------------------------------------------------------------
+
+
+ /** add_petition
+ *
+ * handle an add petition request (petition form is submited)
+ *
+ * @param void; all params are readed from POST, Auth and SESSION
+ * @return int new petition-id
+ */
+ public static function add_petition()
+ {
+ $post = Registry::get('REQUEST')->POST;
+
+
+ if (self::remove_ticket($post['ticket'])) { // check ticket + remove
+
+ $manager = new App_manager();
+
+ $new_id = Content_model::add_petition([
+ 'user_id' => $manager->getUserToken()->getUser()->getID(),
+ 'type_id' => $post['type_id'],
+ 'subject' => $post['subject'],
+ 'signature' => $post['ticket'],
+ 'form_structure' => serialize($post)
+ ]);
+
+ Render::json([
+ 'success' => true,
+ 'id' => $new_id
+ ]);
+
+ } else {
+ Render::json(['success' => false, 'error' => TICKET_EXPIRED]);
+ }
+ }
+
+
+
+ ## -------------------------------------------------------------------------
+ ##
## TICKET METHODS (create, remove)
## tickets eliminate CSRF attacks
##
## -------------------------------------------------------------------------
-
/** create_ticket
*
* creates a tickef and saves it into session
@@ -278,24 +324,29 @@ class Office {
private static function create_ticket()
{
// create ticket
- $tick = md5( time() . Auth::user_data() . rand(1,65536) );
+ $tick = md5( time() . json_encode(Auth::user_data()) . rand(1,65536) );
// then save to session
if (isset($_SESSION['tickets'])) {
$tickets = explode(',', $_SESSION['tickets']);
- $tickets[] = $tick;
+
+ if (count($tickets) > 99) { // if more than 99 tickets
+ array_shift($tickets); // remove the older
+ }
+ $tickets[] = $tick; // add new ticket to the tickets list
$_SESSION['tickets'] = implode(',', $tickets);
} else {
$_SESSION['tickets'] = $tick;
}
- return $tick;
+ return $tick; // return the xreated ticket
}
+
/** remove_ticker
*
* removes a ticket and return true;
- * if ticket not exists return fase;
+ * NOTE: if ticket not exists return false;
*
* @param string $t : ticket (MD5)
* @return boolean
diff --git a/public/app/models/Access_model.php b/public/app/models/Access_model.php
index 023d361..844ff6b 100644
--- a/public/app/models/Access_model.php
+++ b/public/app/models/Access_model.php
@@ -33,6 +33,19 @@ class Access_model
}
+ /** getUserByInvitation
+ *
+ * @param string $invitation
+ */
+ public static function getUserByInvitation($invitation)
+ {
+ return Registry::use('database')->query(
+ "SELECT * FROM user WHERE invitation = :invitation",
+ ['invitation' => $invitation]
+ )->getFirst();
+ }
+
+
/** create user
*
* creates user record;
@@ -156,24 +169,6 @@ class Access_model
## Set permission methods
## -------------------------------------------------------------------------
-
- /** set_user_privileges
- *
- * @param $privileges (array)
- */
- public static function set_user_privileges($user, $privileges)
- {
- $db = Registry::use('database'); // database connection
- foreach($privileges as $pri) { // pri = privilege id
- $db->runQuery(
- "INSERT INTO user_privilege (user_id, privilege_id) VALUES (:user, :pri)",
- [ ':user' => $user, ":pri" => $pri ]
- );
- }
- return true;
- }
-
-
/** set_user_role
*
* user, role are (int) IDs
@@ -190,24 +185,4 @@ class Access_model
}
- ## List methods
- ## -------------------------------------------------------------------------
-
-
- /** privileges
- * ---
- * get all privileges (as a list)
- * used by cacher; speeds up seveal things
- *
- * @param void
- * @return privileges (array)
- */
- public static function privileges()
- {
- return Registry::use('database')->runQuery(
- "SELECT * FROM privilege",[]
- );
- }
-
-
}
diff --git a/public/app/models/Content_model.php b/public/app/models/Content_model.php
new file mode 100644
index 0000000..ea19165
--- /dev/null
+++ b/public/app/models/Content_model.php
@@ -0,0 +1,101 @@
+<?php
+namespace app\models;
+
+use \Registry;
+
+
+class Content_model {
+
+ ## P E T I T I O N S
+ ## -------------------------------------------------------------------------
+
+ /** add petition
+ *
+ * add petition record to the database
+ *
+ * @param array $data
+ * @return int new petition-ID
+ */
+ public static function add_petition($data)
+ {
+ return Registry::use('database')->query(
+ "INSERT INTO petition
+ (user_id, `type_id`, `subject`, `signature`, `form_structure`)
+ VALUES (:user_id, :type_id, :subject, :signature, :form_structure)",
+ [
+ ':user_id' => $data['user_id'],
+ ':type_id' => $data['type_id'],
+ ':subject' => $data['subject'],
+ ':signature' => $data['signature'],
+ ':form_structure' => $data['form_structure']
+ ]
+ )->lastInsertID();
+ }
+
+
+ /** set protocol
+ *
+ * @param int $pid: petition ID
+ * @param string $protocol: official pritocol number (full string)
+ */
+ public static function set_protocol($pid, $protocol)
+ {
+ Registry::use('database')->runQuery(
+ "UPDATE petition SET protocol = :protocol WHERE id = :pid",
+ [
+ ':protocol' => $protocol,
+ ':pid' => $pid
+ ]
+ );
+ return true;
+ }
+
+
+ /** user petitions
+ *
+ * get all petitions of a user
+ *
+ * @param int $uid: user id
+ * @return array petition records
+ */
+ public static function user_petitions($uid)
+ {
+ return Registry::use('database')->runQuery(
+ "SELECT * FROM petition WHERE user_id = :uid",
+ [ ':uid' => $uid ]
+ );
+ }
+
+
+ /** all petitions
+ *
+ * get all petitions of a user
+ *
+ * @param void
+ * @return array petition records
+ */
+ public static function all_petitions()
+ {
+ return Registry::use('database')->runQuery(
+ "SELECT * FROM petition",
+ []
+ );
+ }
+
+
+
+ ## F I L E S
+ ## -------------------------------------------------------------------------
+
+ /** files
+ * return all files
+ * @param void
+ * @return array
+ */
+ public static function files()
+ {
+ return Registry::use('database')->runQuery("SELECT * from media", []);
+ }
+
+
+}
diff --git a/public/app/models/Office_model.php b/public/app/models/Office_model.php
deleted file mode 100644
index fad11b8..0000000
--- a/public/app/models/Office_model.php
+++ /dev/null
@@ -1,314 +0,0 @@
-<?php
-namespace app\models;
-
-use \Registry;
-
-
-class Cms_model {
-
- /** COURSES
- * -------------------------------------------------------------------------
- */
-
- /** get all categories
- *
- * raw table data (simplest SELECT)
- *
- */
- public static function get_categories()
- {
- return Registry::use('database')->runQuery(
- "SELECT * FROM course ORDER BY label",
- []
- );
- }
-
- /** courses struct
- *
- * a super array with almost any info needed about courses
- *
- * @return (array) ['tree' => ..., 'breadcrumbs' => ... ]
- */
- public static function courses_struct()
- {
- $tree = self::category_tree();
- return [
- 'tree' => $tree,
- 'breadcrumbs' => self::breadcrumbs($tree)
- ];
- }
-
-
- /** constuct a category_tree
- *
- * returns a tree representation of the categories
- *
- * NOTE:
- * category_tree() is an expensive method;
- * it calls 2 other methods implementing recursive algorithms
- * thus it uses many sources to run (particularly RAM).
- * Caching the result is strogly recommended.
- *
- */
- public static function category_tree()
- {
- $categories = self::get_categories(); // get all categories
-
- $tree = self::to_tree($categories); // format to a tree
-
- $tree_wParents = self::tree_parents($tree); // add parents section for each tree-node
-
- return $tree_wParents;
- }
-
-
- /** to_tree
- *
- * constructs a tree from raw-table data;
- * this is a private method and uses a recursive algorithm
- *
- * @param $dataset (array): flar array of records with id/parent-id pairs
- * @return $root (array): id of root category
- *
- * (**) each node has 2 parts:
- * .... .. rec : all record attributes/data as passed into $dataset
- * .... .. childs : array of (children) nodes
- */
- private static function to_tree($dataset, $root = 0)
- {
- $return = [];
-
- // loop data ; search for direct children of root
- foreach($dataset as $key => $rec) {
-
- $child = $rec['id'];
- $parent = $rec['parent_id'];
-
- if ($parent == $root) { // a direct child is found
-
- unset($dataset[$key]); // remove item (no need to traverse again)
-
- // Append the child into result array ; parse its children
- $return[] = [
- 'rec' => [
- 'id' => $rec['id'],
- 'label' => $rec['label'],
- 'order' => $rec['order'],
- 'parent' => $rec['parent_id']
- ],
- 'childs' => self::to_tree($dataset, $child) // recursively
- ];
- }
- }
- return empty($return) ? [] : $return;
- }
-
-
- /** tree_parents
- *
- * adds a section to each tree node with all parents of each node
- *
- * @param $tree (array) : nodes array (each node has `rec` and `childs` sections )
- * @param $parents (array); DO NOT SET IT (takes values automaticaly)
- * @return array of nodes with an extra node[parents] section
- *
- */
- private static function tree_parents($tree, $parents = [])
- {
- $tree_with_parents = [];
-
- foreach($tree as $key => $node) {
- // parents to be pushed for node's children
- $push_parents = $parents; // parents so far
- $push_parents[] = $node['rec']; // this record will be a new parent
-
- $tree_with_parents[$key] = [
- 'rec' => $node['rec'],
- 'parents' => $parents,
- 'childs' => ($node['childs'] == [])
- ? []
- : self::tree_parents($node['childs'], $push_parents)
- ];
- }
-
- return $tree_with_parents;
- }
-
-
- /** all_breadcrumbs
- * -------------------------------------------------------------------------
- *
- * returns an array of all breadcrumbs
- * where array-key of each record is category[id]
- *
- * NOTE:
- * ---
- * Cms_model::all_breadcrumbs returns an indexed super-array;
- * each array item includes a banch of information: [
- * breadcrumb,
- * rec: [ id , title ],
- * parents: [ [id, title] , ... ]
- * childs: [ [id, title] , ... ],
- * level
- * ]
- *
- * Use Cases:
- * ---
- * as a super-array, the output can be used in many cases
- * for example...
- * into <select-option> form elements
- * .. while selecting category for a post
- * .. or editing a category
- * or directry referring to category's parents/childs
- *
- * Arguments:
- * ---
- * @param $tree (array) : category tree (with childs and parents parts)
- * @param $detimiter (string, optional) : string to split breadcrumb's path-nodes
- * @param $exception (int, optional) : id of category to exclude (subcategories shall be excluded too)
- * @param $l (int, not-pass) : depth level of the node; DO NOT SET (takes values automaticaly)
- * @return array of breadcrumbs
- * -------------------------------------------------------------------------
- */
- static public function breadcrumbs($tree, $delimiter = " / ", $exception = 0, $l = 0)
- {
- $all = []; // results array
-
- foreach($tree as $node) { // loop through all nodes
-
- if (intval($node['rec']['id']) != $exception) { // if node is not exception
-
- // construct breadcrumb html of node
- // --- -- -- - - -
- $breadcrumb = "";
- foreach($node['parents'] as $par) { // first: join path titles
- $breadcrumb .= $par['label'] . $delimiter;
- }
- $breadcrumb .= $node['rec']['label']; // last: append title
-
- // make a new super record
- // --- -- -- - - -
- $all[$node['rec']['id']] = [ // set record is as key
- 'breadcrumb' => $breadcrumb, // add breadcrump to results
- 'rec' => $node['rec'], // + node info
- 'parents' => $node['parents'], // + parents array
- 'childs' => self::first_level_childs($node), // + direct childs
- 'level' => $l // + level
- ];
-
- // recursively traverse children nodes
- // --- -- -- - - -
- if (isset($node['childs']) && $node['childs'] != []) {
- $child_breadcrumbs = self::breadcrumbs(
- $node['childs'],
- $delimiter,
- $exception,
- $l+1
- );
-
- $all = $all + $child_breadcrumbs; // concatenate arrays (keep array-keys)
- }
- }
-
- }
- return $all;
-
- }
-
- /** first_level_childs
- * --- -- -- - - -
- * used by all_breadcrumbs()
- */
- static private function first_level_childs($node)
- {
- $childs = [];
- if ($node['childs'] == []) {
- return [];
- }
- foreach($node['childs'] as $key => $kid) {
- $childs[] = [
- 'id' => $kid['rec']['id'],
- 'label' => $kid['rec']['label']
- ];
- }
- return $childs;
- }
-
-
-
-
- /** LESSONS
- * -------------------------------------------------------------------------
- */
-
-
- /** lessons of course
- *
- * @param $id (int) : course_id
- */
- public static function lessons_of_course($id)
- {
- // TODO: order results in some way
-
- return Registry::use('database')->runQuery(
- "SELECT lesson.*, lesson_privilege.privilege_id FROM lesson
- LEFT JOIN lesson_privilege ON lesson_privilege.lesson_id = lesson.id
- WHERE lesson.status = 1 AND lesson.course_id = :id
- ORDER BY lesson_privilege.privilege_id ASC",
- [':id' => $id]
- );
- }
-
- /** lesson
- *
- * @param $id (int) : lesson id
- */
- public static function lesson($id)
- {
- // TODO: order results in some way
-
- return Registry::use('database')->query(
- "SELECT lesson.*, lesson_privilege.privilege_id FROM lesson
- LEFT JOIN lesson_privilege ON lesson_privilege.lesson_id = lesson.id
- WHERE lesson.status = 1 AND lesson.id = :id",
- [':id' => $id]
- )->getFirst();
- }
-
-
-
- /** files
- * return all files
- * @param void
- * @return array
- */
- public static function files()
- {
- return Registry::use('database')->runQuery("SELECT * from media", []);
- }
-
-
- /** pages
- *
- * return all pages as array;
- * array key of each item shall be the page-id
- *
- * @param void
- * @return array
- */
- public static function pages()
- {
- $result = [];
- $pages = Registry::use('database')->runQuery("SELECT * FROM page", []);
- foreach($pages as $key => $page) {
- $result[ $page['id'] ] = [
- 'title' => $page['title'],
- 'body' => $page['body'],
- 'status' => $page['status']
- ];
- }
- // print_r($result); die();
- return $result;
- }
-
-}
diff --git a/public/app/models/_info.md b/public/app/models/_info.md
index ac6d334..9f02061 100644
--- a/public/app/models/_info.md
+++ b/public/app/models/_info.md
@@ -3,68 +3,72 @@
## user fields; insert / update sql queries
-INSERT INTO user
-( id,
- prefix,
- first_name,
- last_name,
- email,
- father_name,
- registration_number,
- sector_id,
- specialty,
- belonging_school,
- working_shcool,
- position_type_id,
- phone,
- password,
- expiration,
- otp,
- otp_expiration,
- activation,
- creation,
-active) VALUES (:id,
- :prefix,
- :first_name,
- :last_name,
- :email,
- :father_name,
- :registration_number,
- :sector_id,
- :specialty,
- :belonging_school,
- :working_shcool,
- :position_type_id,
- :phone,
- :password,
- :expiration,
- :otp,
- :otp_expiration,
- :activation,
- :creation,
-:active )
-
-
-UPDATE user
-SET prefix = :prefix,
-first_name = :first_name,
-last_name = :last_name,
-email = :email,
-father_name = :father_name,
-registration_number = :registration_number,
-sector_id = :sector_id,
-specialty = :specialty,
-belonging_school = :belonging_school,
-working_shcool = :working_shcool,
-position_type_id = :position_type_id,
-phone = :phone,
-password = :password,
-expiration = :expiration,
-otp = :otp,
-otp_expiration = :otp_expiration,
-activation = :activation,
-creation = :creation,
-active = :active,
+Insert user:
+
+ INSERT INTO user
+ ( id,
+ prefix,
+ first_name,
+ last_name,
+ email,
+ father_name,
+ registration_number,
+ sector_id,
+ specialty,
+ belonging_school,
+ working_shcool,
+ position_type_id,
+ phone,
+ password,
+ expiration,
+ otp,
+ otp_expiration,
+ activation,
+ creation,
+ active) VALUES (:id,
+ :prefix,
+ :first_name,
+ :last_name,
+ :email,
+ :father_name,
+ :registration_number,
+ :sector_id,
+ :specialty,
+ :belonging_school,
+ :working_shcool,
+ :position_type_id,
+ :phone,
+ :password,
+ :expiration,
+ :otp,
+ :otp_expiration,
+ :activation,
+ :creation,
+ :active )
+
+
+Update user
+
+ UPDATE user
+ SET prefix = :prefix,
+ first_name = :first_name,
+ last_name = :last_name,
+ email = :email,
+ father_name = :father_name,
+ registration_number = :registration_number,
+ sector_id = :sector_id,
+ specialty = :specialty,
+ belonging_school = :belonging_school,
+ working_shcool = :working_shcool,
+ position_type_id = :position_type_id,
+ phone = :phone,
+ password = :password,
+ expiration = :expiration,
+ otp = :otp,
+ otp_expiration = :otp_expiration,
+ activation = :activation,
+ creation = :creation,
+ active = :active,
## record_types
@@ -158,16 +162,122 @@ call_user_func(array($myobject, 'say_hello'));
\ controllers
[ ] App
- [ ] Auth
+ [*] Auth
\ extends
[ ] Cache_service
[*] App_manager
[*] App_user
[ ] SendMail_service
- [ ] Form_builder
+ [*] Form_builder
\ models
[ ] Access_model
- [ ] History_model \ No newline at end of file
+ [ ] History_model
+
+
+
+# DataBase Structure
+
+
+
+ SET NAMES utf8;
+ SET time_zone = '+00:00';
+ SET foreign_key_checks = 0;
+ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
+
+ SET NAMES utf8mb4;
+
+ DROP TABLE IF EXISTS `history`;
+ CREATE TABLE `history` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `user_id` int(11) NOT NULL,
+ `type` smallint(6) NOT NULL,
+ `message` varchar(140) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `note` text COLLATE utf8mb4_unicode_ci,
+ `ip` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `history_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
+ DROP TABLE IF EXISTS `media`;
+ CREATE TABLE `media` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `title` varchar(256) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `user_id` int(11) NOT NULL,
+ `path` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `type` varchar(512) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'media-type',
+ PRIMARY KEY (`id`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `media_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
+ DROP TABLE IF EXISTS `petition`;
+ CREATE TABLE `petition` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `user_id` int(11) NOT NULL,
+ `type_id` smallint(6) NOT NULL,
+ `form_structure` text COLLATE utf8mb4_unicode_ci NOT NULL,
+ `protocol` int(11) DEFAULT NULL,
+ `signature` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `record_date` date DEFAULT NULL,
+ `creation_date` datetime DEFAULT CURRENT_TIMESTAMP,
+ `update_date` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `signature` (`signature`),
+ KEY `user_id` (`user_id`),
+ CONSTRAINT `petition_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
+ DROP TABLE IF EXISTS `petition_media`;
+ CREATE TABLE `petition_media` (
+ `petition_id` bigint(20) NOT NULL,
+ `media_id` bigint(20) NOT NULL,
+ KEY `petition_id` (`petition_id`),
+ KEY `media_id` (`media_id`),
+ CONSTRAINT `petition_media_ibfk_1` FOREIGN KEY (`petition_id`) REFERENCES `petition` (`id`),
+ CONSTRAINT `petition_media_ibfk_2` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
+ DROP TABLE IF EXISTS `role`;
+ CREATE TABLE `role` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `alias` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `label` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
+ PRIMARY KEY (`id`)
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
+
+ DROP TABLE IF EXISTS `user`;
+ CREATE TABLE `user` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `prefix` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `first_name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `last_name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `email` varchar(48) COLLATE utf8mb4_unicode_ci NOT NULL,
+ `father_name` varchar(48) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `registration_number` bigint(20) DEFAULT NULL COMMENT 'AM',
+ `sector` varchar(48) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'sector_id + speciality',
+ `belonging_school` varchar(96) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `position` varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'chief, permanent, deputy etc',
+ `phone` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `password` varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
+ `role_id` int(11) DEFAULT NULL,
+ `expiration` datetime DEFAULT NULL COMMENT 'account expiration datetime',
+ `otp` varchar(16) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'one time password for reset password',
+ `otp_expiration` datetime DEFAULT NULL,
+ `invitation` varchar(160) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'invitation code',
+ `creation_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'creation datetime',
+ `update_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ `active` smallint(6) NOT NULL DEFAULT '0' COMMENT 'account status flag; 1=active 0=inactive',
+ PRIMARY KEY (`id`),
+ KEY `role_id` (`role_id`),
+ CONSTRAINT `user_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`) ON DELETE NO ACTION
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+
diff --git a/public/app/routes/frontend.php b/public/app/routes/frontend.php
index 14152c1..adfe936 100644
--- a/public/app/routes/frontend.php
+++ b/public/app/routes/frontend.php
@@ -13,6 +13,12 @@ use app\extends\Cache_service;
Route::add('/', function() { Render::view('user/login'); });
+
+// invitation
+////////////////////////////////////////////////////////////////////////////////
+
+// request invitation (for account activation)
+// --- -- -- - - -
Route::add('/invitation/([0-9]*)', function($id) {
if ($id == "" || $id == "0") { Render::view('error/404');
} else {
@@ -20,15 +26,16 @@ Route::add('/invitation/([0-9]*)', function($id) {
}
});
-// new petition
-Route::add('/petition/([0-9a-z\-_]*)', function($tag) {
- Office::request_petition($tag);
-});
+// request activation (submit invitation; POST:form is sent)
+// --- -- -- - - -
+Route::add('/account/activate', function() { Auth::activate(); }, 'post');
-// existing petition
-Route::add('/petition/([0-9a-z\-_]*)/([0-9a-f]*)', function($tag) {
- Office::filter_request_petition($tag, $id);
-});
+// DEPRICATED: user sends a registration form
+// --- -- -- - - -
+# Route::add('/account/register', function() {
+# $response = Auth::register();
+# Render::json($response);
+# },'post');
@@ -42,141 +49,102 @@ Route::notFound( function() { // 404 error page
-// Common content
-////////////////////////////////////////////////////////////////////////////////
-
-
-Route::add('/course/([0-9]*)', // request course by course-id
- function($id) { Cms::course($id); }
-);
-
-Route::add('/lesson/([0-9]*)', // request lesson by lesson-id
- function($id) { Cms::lesson($id); }
-);
-
-Route::add('/page/([0-9]*)', // request lesson by lesson-id
- function($id) { Cms::page($id); }
-);
-
-Route::add('/serve/file/([0-9a-zA-Z-_\.\/]*)', // serve file by path
- function ($path) { Cms::serve_file($path); } // (also ?type= is sent)
-);
-
-
-
-
-// Account
-////////////////////////////////////////////////////////////////////////////////
-
-// [ok] login
-// [ok] register
-// [ok] activate
-// [..] ask-reset
-// [..] reset
-// [..] profile
-// [..] edit-profile
-// [..] subscriptions
-// [..] payments
-// [..] pay
-// [..] order
-
-
-
-
-/** URL-format Proposals and common Route regex solutions
+/** Examples of real-world route formats
+ *
+ * URL-format Proposals and common Route regex solutions
* -----------------------------------------------------------------------------
*
* Page (almost-static content):
* /about/{url}
-# Route::add('/about/([0-9a-zA-Z-_\/]*)', function($url) { Page::fromUrl($url); });
+ # Route::add('/about/([0-9a-zA-Z-_\/]*)', function($url) { Page::fromUrl($url); });
*
* Product:
* /{level-1}/{level-2}/{level-3}/{friendly-url}-{id}
-# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)',
-# function($category, $subcategory, $group, $label, $id) {
-# Product::fromID([$$category, $subcategory, $group, $label], $id);
-# }
-# );
+ # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)',
+ # function($category, $subcategory, $group, $label, $id) {
+ # Product::fromID([$$category, $subcategory, $group, $label], $id);
+ # }
+ # );
*
* Category
* /{category}/[ {subcategory}[ /{group}]]
-# Route::add('/([0-9a-zA-Z-_]*)', function($a) { Category::url([$a]); };
-# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Category::url([$a, $b]); });
-# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Category::url([$a, $b, $c]); });
+ # Route::add('/([0-9a-zA-Z-_]*)', function($a) { Category::url([$a]); };
+ # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Category::url([$a, $b]); });
+ # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Category::url([$a, $b, $c]); });
*
* othet routes used in some user-cases
-
-# Route::add('/lesson/([0-9a-f]*)/([0-9a-zA-Z-_]*)',
-# function($ticket, $lesson) { Lesson::show([$lesson, $ticket]); }
-# );
-#
-# Route::add('/media/([0-9a-f]*)/([0-9a-zA-Z-_]*)/([0-9]*)/',
-# function($ticket, $type, $id) { Media::serve([$type, $id, $ticket]); }
-# );
+ *
+ # Route::add('/lesson/([0-9a-f]*)/([0-9a-zA-Z-_]*)',
+ # function($ticket, $lesson) { Lesson::show([$lesson, $ticket]); }
+ # );
+ #
+ # Route::add('/media/([0-9a-f]*)/([0-9a-zA-Z-_]*)/([0-9]*)/',
+ # function($ticket, $type, $id) { Media::serve([$type, $id, $ticket]); }
+ # );
*
* 4-th level paths belong to products
-# Route::add('/about/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)',
-# function($a, $b, $c) { Page::show([$a, $b, $c]); }
-# );
+ # Route::add('/about/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)',
+ # function($a, $b, $c) { Page::show([$a, $b, $c]); }
+ # );
*
*
* OTHER EXAMPLES (use it for brainsrtorming)
* -----------------------------------------------------------------------------
*
*
-# // Typical Use
-# // ---
-# Route::add('/art', function() { Art::blah(); });
-# Route::add('/art/db', function() { Art::fromDatabase(); });
-# Route::add('/art/([0-9]*)', function($id) { Art::getInfo($id); });
+ # // Typical Use
+ # // ---
+ # Route::add('/art', function() { Art::blah(); });
+ # Route::add('/art/db', function() { Art::fromDatabase(); });
+ # Route::add('/art/([0-9]*)', function($id) { Art::getInfo($id); });
*
* Get-Post route example
-# Route::add('/contact-form', function() {
-# echo '<form method="post"><input type="text" name="test" /><input type="submit" value="send" /></form>';
-# }, 'get');
-
- Route::add('/contact-form', function() {
- echo 'Hey! The form has been sent:<br/>'; print_r($_POST);
- }, 'post');
+ # Route::add('/contact-form', function() {
+ # echo '<form method="post"><input type="text" name="test" /><input type="submit" value="send" /></form>';
+ # }, 'get');
+
+ Route::add('/contact-form', function() {
+ echo 'Hey! The form has been sent:<br/>'; print_r($_POST);
+ }, 'post');
*
* Accept number as parameter
-# Route::add('/foo/([0-9]*)/bar', function($var1) {
-# // echo $var1.' is a number!';
- echo "{$var1} is a number!";
-# });
+ # Route::add('/foo/([0-9]*)/bar', function($var1) {
+ # // echo $var1.' is a number!';
+ echo "{$var1} is a number!";
+ # });
*
* About pages
-# Route::add('/about/([0-9a-zA-Z-_]*)', function($page) {
-# InfoPage::render('about/'.page);
-# });
+ # Route::add('/about/([0-9a-zA-Z-_]*)', function($page) {
+ # InfoPage::render('about/'.page);
+ # });
*
* handle a request like: /foo/123/bar/3254-lefki-zaxari-marata-1kg
* where first-numeric-part of last-uri-section (3254) is the product number
-# Route::add('/foo/([0-9]*)/bar/([0-9]*)-([0-9a-zA-Z-_]*)', function($num, $id, $name) {
-# echo $num .' is some nomber, id = '. $id .' and label = '. $name;
-# });
+ # Route::add('/foo/([0-9]*)/bar/([0-9]*)-([0-9a-zA-Z-_]*)', function($num, $id, $name) {
+ # echo $num .' is some nomber, id = '. $id .' and label = '. $name;
+ # });
*
* handle a request like: /zaxares-glykantika/lefki-zaxari-year-2022-45678
* where last-numeric-part of last-uri-section (45678) is the product number
-# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)',
-# function($category, $subcategory, $group, $label, $id) {
-# Shop::product([$$category, $subcategory, $group, $label], $id);
-# });
+ # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)',
+ # function($category, $subcategory, $group, $label, $id) {
+ # Shop::product([$$category, $subcategory, $group, $label], $id);
+ # });
*
* last chance to resolve (some friendly url)
-# Route::add('/([0-9a-zA-Z-_]*)', function($a) { Resolve::uri([$a]); });
-# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Resolve::uri([$a, $b]); });
-# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Resolve::uri([$a, $b, $c]); });
+ # Route::add('/([0-9a-zA-Z-_]*)', function($a) { Resolve::uri([$a]); });
+ # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b) { Resolve::uri([$a, $b]); });
+ # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)', function($a, $b, $c) { Resolve::uri([$a, $b, $c]); });
*
*
* Product page
* handle a request like: /pantopoleio/zaxares/lefki-zaxari/lefki-zaxari-year-2022-45678
* where last-numeric-part of last-uri-section (45678) is the product number
-# Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)',
-# function($category, $subcategory, $group, $label, $id) {
-# Shop::product([$$category, $subcategory, $group, $label], $id);
-# });
+ # Route::add('/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)/([0-9a-zA-Z-_]*)-([0-9]*)',
+ # function($category, $subcategory, $group, $label, $id) {
+ # Shop::product([$$category, $subcategory, $group, $label], $id);
+ # });
*
* ------------------------------------------------------------------------------
- */
+*/
diff --git a/public/app/routes/user.php b/public/app/routes/user.php
index 26483f4..12ca7d2 100644
--- a/public/app/routes/user.php
+++ b/public/app/routes/user.php
@@ -2,6 +2,7 @@
use app\controllers\Auth;
use app\controllers\Classroom_user;
+use app\controllers\Office;
/** User Connection Management Routes
@@ -25,28 +26,12 @@ Route::add('/logout', function() {
header('Location: /'); die();
});
-// request activation (from invitation page; POST:form is sent)
-Route::add('/account/activate', function() { Auth::activate(); }, 'post');
+
// request password reset
Route::add('/account/reset_password', function() { Auth::reset_password(); } );
-// invite some users
-Route::add('/invite', function() {
- Auth::allowRoles([1, 2, 3]);
- Render::view('admin/invite');
-});
-
-Route::add('/panel', function() {
- Render::view('user/panel');
- // Render::json([
- // 'connected' => Auth::is_connected(),
- // 'user' => Auth::user_data(),
- // ]);
-});
-
-
// Replies to common requests (POST method)
// --- -- -- - - -
@@ -58,36 +43,105 @@ Route::add('/account/check-login', function() {
'post'
);
-// user sends a registration form
-Route::add('/account/register', function() {
- $response = Auth::register();
- Render::json($response);
-},'post');
-// Account Management
-// --- -- -- - - -
+/* DEPRICATED:
+ // Account Management
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // user profile
+ Route::add('/account/profile', function() {
+ $user = Auth::is_connected();
+ if ($user === false) {
+ Render::view('error/general',
+ [
+ 'title' => 'Nope!',
+ 'message' => "<h2>No profile</h2>User is not connected"
+ ]
+ );
-// user profile
-Route::add('/account/profile', function() {
- $user = Auth::is_connected();
- if ($user === false) {
- Render::view('error/general',
- [
- 'title' => 'Nope!',
- 'message' => "<h2>No profile</h2>User is not connected"
- ]
- );
-
- } else {
- Render::json(['success' => true, 'status' => 'user is connected']);
+ } else {
+ Render::json(['success' => true, 'status' => 'user is connected']);
+ }
}
- }
-);
+ );
+--- */
+
+
+// routes for connected users
+////////////////////////////////////////////////////////////////////////////////
+
+if (Auth::is_connected()) {
+
+ // serve content
+ // -------------------------------------------------------------------------
+
+ // control panel
+ // --- -- -- - - -
+ Route::add('/panel', function() {
+ Render::view('user/panel',[
+ 'is_admin' => Auth::in_admin_group(),
+ 'content' => 'info',
+ 'user' => json_decode(json_encode(
+ Auth::user_data(), JSON_UNESCAPED_UNICODE
+ ))
+ ]);
+ });
+
+ // file of petitions
+ // --- -- -- - - -
+ Route::add('/user/petitions', function() {
+ Render::view('admin/invite');
+ });
+
+ // request New petition form
+ // --- -- -- - - -
+ Route::add('/petition/([0-9a-z\-_]*)', function($tag) {
+ Office::request_petition($tag);
+ });
+
+ // request existing petition
+ // --- -- -- - - -
+ Route::add('/petition/signature/([0-9a-f]*)', function($signature) {
+ Office::filter_request_petition($signature);
+ });
+
+
+ // CRUD content
+ // -------------------------------------------------------------------------
+
+ // add petition
+ // --- -- -- - - -
+ Route::add('/petition/new', function() {
+ Office::add_petition();
+ }, 'post');
+
+
+}
+
+
+
+// routes for administrators
+////////////////////////////////////////////////////////////////////////////////
+
+if (Auth::in_admin_group()) {
+
+ // administer petitions
+ // --- -- -- - - -
+ Route::add('/admin/petitions', function() {
+ Render::view('user/panel');
+ });
+
+ // invite user(s)
+ // --- -- -- - - -
+ Route::add('/admin/invite', function() {
+ Render::view('admin/invite');
+ });
+}
// temporary (on development)
-// --- -- -- - --
+////////////////////////////////////////////////////////////////////////////////
// NOTE: these is only for testing purposes
// test connection
diff --git a/public/app/views/components/breadcrumbs.php b/public/app/views/components/breadcrumbs.php
deleted file mode 100644
index 59c0fca..0000000
--- a/public/app/views/components/breadcrumbs.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-/** breadcrumbs
- * -----------------------------------------------------------------------------
- *
- * imported variables
- * ---
- * @param $id : category_id of last level
- * @param $label : category title of last level
- * @param $parents : array of parent nodes
- * -----------------------------------------------------------------------------
- */
-
-?>
-<div class="breadcrumb">
- <!-- home -->
- <a href="/">Classroom</a>
-
- <!-- parent nodes -->
- <?php if ($id != 0) : ?>
- <?php foreach($parents as $node) : ?>
- <i class="fas fa-angle-right"></i> <a href="/course/<?=$node['id']?>"><?=$node['label']?></a>
- <?php endforeach; ?>
- <?php endif; ?>
-
- <!-- last (current) node -->
- <?php if ($id != 0) : ?>
- <i class="fas fa-angle-right"></i> <a href="/course/<?=$id?>"><?=$label?></a>
- <?php endif; ?>
-
-</div> \ No newline at end of file
diff --git a/public/app/views/components/courses_menu.php b/public/app/views/components/courses_menu.php
deleted file mode 100644
index 6539f8c..0000000
--- a/public/app/views/components/courses_menu.php
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-/** Categories Menu
- * -----------------------------------------------------------------------------
- * sits in the (left) sidebar
- *
- * imported variables
- * ---
- * @param $categories (array) : the categories tree
- * @param $open_path (array) : 'id's array of selected categories
- *
- * example call:
- * (draw the categories-menu and set open the categories with ids 1 and 2)
- * ---
- * Render::template("section/categories_menu.php",[
- * 'categories' => $category_tree,
- * 'open_path' => [1 ,2]
- * ]);
- *
- * -----------------------------------------------------------------------------
- */
-
-/** tree_ul
- * creates (recursively) a nested ul-li tree of categories
- * --- -- -- - - -
- * @param $tree (array) : categories array formated as tree
- * @param $open_nodes (array) : array of categor ids that shall be marked open/selected
- * @return $html (string)
- */
-function tree_li($tree, $open_nodes = [], $l = 0)
-{
- $html = "";
-
- foreach($tree as $node) {
-
- // if has childs ...
- // write li ; traverse children recursively
- if ((isset($node['childs'])) && ( $node['childs']!= [])) {
-
- if (in_array(intval($node['rec']['id']), $open_nodes)) {
- $inner_class = "inner show";
- $sign = "–";
- $a_class = "has-childs selected";
-
- } else {
- $inner_class = "inner";
- $sign = "+";
- $a_class = "has-childs";
- }
-
- $html .= "<li>
- <a href='/course/{$node['rec']['id']}' class='{$a_class}'>
- <span class='label'>{$node['rec']['label']}</span>
- <span class='toggler'>{$sign}</span>
- </a>
- <ul class='{$inner_class}'>"
- . tree_li($node['childs'], $open_nodes, $l+1)
- ."</ul>
- </li>";
-
-
- } else { // else just write the li
-
- if (in_array(intval($node['rec']['id']), $open_nodes)) {
- $u_in = "<u>";
- $u_out = "</u>";
- $a_class = "selected";
-
- } else {
- $u_in = "";
- $u_out = "";
- $a_class = "";
-
- }
-
- $html .= "<li>
- <a href='/course/{$node['rec']['id']}' class='{$a_class}'>
- <span class='label'>{$node['rec']['label']}</span>
- </a>
- </li>";
- }
- }
-
- return $html;
-
-}
-
-
-// draw the menu (hidden on XS screens)
-// -----------------------------------------------------------------------------
-echo "<h3>Διαθέσιμη ύλη</h3>";
-echo "<ul class='hidden-xs side-bar'>". tree_li($categories, $open_path) ."</ul>";
-
-
-
-// TODO:
-// draw menu for XS screens (for example, just the 1st-level categories)
-// (maybe in an accordion so it won;t take too much area on small screens)
diff --git a/public/app/views/components/footer.php b/public/app/views/components/footer.php
deleted file mode 100644
index 7cd4a5a..0000000
--- a/public/app/views/components/footer.php
+++ /dev/null
@@ -1,240 +0,0 @@
-<?php
-
-use app\extends\Cache_service;
-
-
-/** DESIGNERS
- * -----------------------------------------------------------------------------
- *
- * structures that combine several design information
- * in a json structrure and parses inta a quite complicated view;
- *
- * co-operate with pages
- *
- * can be used to rended menus, sections like header or footer etc;
- *
- * TODO:
- * + embed it as a core \Render method
- * + dynamic designers
- * + recursive designers
- *
- * Here we implement a simplified version of the consept
- * where entities shall always be `pages`
- *
- *
- * PARAMETRES
- * --- -- -- - - -
- *
- * primary properties of designer structure are 2 properties
- *
- * @var class (string): container class name
- * @var struct (json array): representatoion of the "to-be-designed" structure
- *
- * TODO: support more complx `class` strings ex. `.container>#footer>row`
- *
- *
- * Each sub-structure has 2-5 properties:
- *
- * @var title (string) : title of the sub-section
- * @var entity (string) : type of entity (ex: page/lesson/etc; TODO: method of CMS_model?)
- * @var list (array) : list of entity id(s)
- * @var template (string) : template that is used to draw the listed pages' info
- * @var width (string) : class that relates to sub-structure's width
- *
- * NOTE:
- * designer parsing and rendering can be a quite expensive proccess
- * thus it is strongly recommented to use cached entities
- *
- *
- * Example structure:
- {
- "class" : "row", # container class
- "struct" : [
- { # block 1
- "title" : "",
- "entity" : "page",
- "list" : [2, 1, 3], # pages to be listed
- "template" : "list", # list page titles with link to the pages
- "width" : "col-md-4"
- },
- {
- "template" : "null", # list nothing
- "width" : "col-md-3"
- },
- {
- "entity" : "page",
- "list" : [4], # list content of page 4;
- "template" : "content", # set title to page-title
- "width" : "col-md-5"
- }
-
- TODO: (wish)
- ,{
- "template": "struct",
- "struct" : [
- {
- title, entity, list, template, width
- },
- ...
- ]
- }
- ]
- }
- *
- * brainstormin: (TODO:)
- * use some document-describe stucture like the one on the pdfmake js-library
- * -----------------------------------------------------------------------------
- */
-
-
-/** check imported variables / data
- * -----------------------------------------------------------------------------
- */
-if (!isset($designer)) {
-
- // default designer (and first case-study)
- $designer = '{
- "class" : "row",
- "struct" : [
- {
- "title" : "Πληροφορίες",
- "entity" : "page",
- "list" : [2, 1, 3, 4],
- "template" : "list",
- "width" : "col-md-4 no-list-mark"
- },
- {
- "entity" : "page",
- "list" : [6],
- "template" : "content",
- "width" : "col-md-3 no-list-mark"
- },
- {
- "entity" : "page",
- "list" : [5],
- "template" : "content",
- "width" : "col-md-5 no-list-mark"
- }
- ]
- }';
-}
-
-// $entity list shall be passed
-// entity link url shall be passed
-
-
-/** templating functions
- * -----------------------------------------------------------------------------
- */
-
-/** List template
- * --- -- -- - - -
- *
- * lists entity titles with links
- * in a `ul>li` html-structure
- *
- * @param $title
- * @param $list
- * @param $container
- */
-function list_template($title, $list, $container, $entity) {
-
- $result = '<div class="'. $container .'">
- <h4>'. $title .'</h4>
- <ul>';
-
- foreach($list as $id) {
-
- if ($entity[$id]['status'] == 1) { // if entity is published
- $result .= '
- <li>
- <a href="/page/'. $id . '">
- ' . $entity[$id]['title'] .'
- </a>
- </li>';
- }
-
- }
- return $result . '</ul></div>';
-}
-
-/** content_template
- *
- * lists whole title and content of entity
- *
- * @param $list
- * @param $container
- */
-function content_template($list, $container, $entity) {
-
- $parsedown = new Parsedown();
-
- $result = '<div class="'. $container .'"><ul>';
-
- foreach($list as $id) {
-
- if ($entity[$id]['status'] == 1) { // if entity is published
-
- $result .= '
- <li>
- <h4>'. $entity[$id]['title'] .'</h4>
- <div>'. $parsedown->text($entity[$id]['body']) .'</div>
- </li>';
- }
-
- }
- return $result .'</ul></div>';
-}
-
-
-/** ready to start the proccessing
- * -----------------------------------------------------------------------------
- */
-
-// decode ...
-$parse = json_decode($designer);
-
-/** then start parse-proccessing ...
- * -----------------------------------------------------------------------------
- */
-?>
-
-
-
-<div class="<?=$parse->class?>">
-
- <?php
- foreach( $parse->struct as $section ) {
-
- switch ($section->template) {
-
- case 'list':
- echo list_template(
- $section->title,
- $section->list,
- $section->width,
- $entity
- );
- break;
-
- case 'content':
- echo content_template(
- $section->list,
- $section->width,
- $entity
- );
- break;
-
- default: // ex. 'null'
-
- echo '<div class="'. $section->width .'">
- <h4>'. $section->title.'</h4>
- </div>';
- }
-
- }
- ?>
-
-</div>
-
-
diff --git a/public/app/views/components/info.php b/public/app/views/components/info.php
new file mode 100644
index 0000000..02c13e9
--- /dev/null
+++ b/public/app/views/components/info.php
@@ -0,0 +1,28 @@
+<?php
+/** Menu of words (for logged-in user)
+ * -----------------------------------------------------------------------------
+ *
+ * imported:
+ * @var stdClass $user (mandatory)
+ * @var boolen $is_admin (mandatory)
+ */
+?>
+<div class="info">
+ <p>&nbsp;</p>
+ <p>
+ <b><?=$user->first_name?> <?=$user->last_name?></b>
+ <?php if ($is_admin) : ?>
+ (Administrator)
+ <?php endif; ?>
+ </p>
+
+ <p><b><?=$user->position?></b></p>
+ <p><b><?=$user->sector?></b></p>
+
+ <p>AM: <b><?=$user->registration_number?></b></p>
+
+ <p>Email: <b><?=$user->email?></b></p>
+ <p>Tηλέφωνο: <b><?=$user->phone?></b></p>
+
+</div>
+
diff --git a/public/app/views/components/lessons_list.php b/public/app/views/components/lessons_list.php
deleted file mode 100644
index a778d59..0000000
--- a/public/app/views/components/lessons_list.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-/** lessons list
- * -----------------------------------------------------------------------------
- *
- * imported variables:
- * ---
- * @param $lessons : array of lessons
- * @param $fieldset : array of optional fields to show [category, intro, date]
- *
- * example call:
- * ---
- * Render::template("sections/articles_list.php",[
- * 'articles' => $category_tree,
- * 'fieldset' => ['date', 'intro']
- * ])
- * -----------------------------------------------------------------------------
- */
-?>
-
-
-<?php foreach($lessons as $post) : ?>
-
- <!-- <div class="col-xl-4 col-lg-6"> -->
- <div class="post-card">
-
- <?php if (in_array('date', $fieldset)) : ?>
- <?=$post['date']?>
- <?php endif; ?>
-
- <div class="post-card--content">
-
- <h3>
- <a href="/lesson/<?=$post['id']?>"><?=$post['title']?></a>
- </h3>
-
- <?php if (in_array('level', $fieldset)) : ?>
- <p class="getegory">(επίπεδο πρόσβασης <?=$post['privilege_id']?>)</p>
- <?php endif; ?>
-
- <?php if (in_array('category', $fieldset)) : ?>
- <p class="category"><?=$post['course_id']?></p>
- <?php endif; ?>
-
- <?php if (in_array('intro', $fieldset) && $post['intro']) : ?>
- <p class="intro"><?=$post['intro']?></p>
- <?php endif; ?>
-
- </div>
-
- </div>
- <!-- </div> -->
-
-<?php endforeach; ?>
-
diff --git a/public/app/views/components/menu.php b/public/app/views/components/menu.php
index 60ad395..524547c 100644
--- a/public/app/views/components/menu.php
+++ b/public/app/views/components/menu.php
@@ -1,17 +1,31 @@
+<?php
+/** Menu of words (for logged-in user)
+ * -----------------------------------------------------------------------------
+ *
+ * imported:
+ * @var boolen $is_admin (mandatory)
+ */
+?>
<ul class="list-group">
<li class="list-group-item"><a href="/petition/application">Νέα Αίτηση</a></li>
<li class="list-group-item"><a href="/petition/penalty">Νέo Πρακτικό Πειθαρχικής Υπόθεσης</a></li>
- <li class="list-group-item separator">Αρχείο</li>
- <li class="list-group-item"><a href="/account/petitions">Πρακτικά και οι αιτήσεις</a></li>
+
+ <li class="list-group-item separator">To αρχείο σας</li>
+ <li class="list-group-item"><a href="/user/petitions">Πρακτικά και αιτήσεις</a></li>
+
<li class="list-group-item separator">Προφίλ</li>
- <li class="list-group-item"><a href="/account/update">Ενημέρωση των στοιχείων σας</a></li>
- <li class="list-group-item"><a href="/account/new-password">Αλλαγή password</a></li>
+ <li class="list-group-item"><a href="/user/update">Ενημέρωση στοιχείων</a></li>
+ <li class="list-group-item"><a href="/user/new-password">Αλλαγή password</a></li>
+
+ <?php if ($is_admin) : ?>
<li class="list-group-item separator">Διαχείριση</li>
- <li class="list-group-item"><a href="/account/update">Κατάσταση πρακτικών & αιτήσεων</a></li>
- <li class="list-group-item"><a href="/account/update">Αποστολή προσκλήσεων</a></li>
+ <li class="list-group-item"><a href="/admin/petitions">Κατάσταση πρακτικών & αιτήσεων</a></li>
+ <li class="list-group-item"><a href="/admin/invite">Αποστολή προσκλήσεων</a></li>
+ <?php endif; ?>
+
<li class="list-group-item separator"></li>
+
<li class="list-group-item"><a href="/logout">Αποσύνδεση</a></li>
</ul>
-
diff --git a/public/app/views/components/subcategories.php b/public/app/views/components/subcategories.php
deleted file mode 100644
index 5c05a94..0000000
--- a/public/app/views/components/subcategories.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<!-- Sub-Categories -->
-
-<?php if ($breadcrumbs[ $id ]['childs'] != []) : ?>
-
- <h5>Υποκεφάλαια</h5>
-
- <div class="category-childs">
-
- <?php foreach($breadcrumbs[ $id ]['childs'] as $key => $child) : ?>
-
- <a href="/course/<?=$child['id']?>" class="btn btn-light">
- <?=$child['label']?>
- </a>
-
- <?php endforeach; ?>
-
- </div>
-
-<?php endif; ?> \ No newline at end of file
diff --git a/public/app/views/components/top_bar.php b/public/app/views/components/top_bar.php
deleted file mode 100644
index eaffe76..0000000
--- a/public/app/views/components/top_bar.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/** top bar
- * -----------------------------------------------------------------------------
- *
- * rendrers breadcrumbs and user menu
- *
- * imported variables
- * ---
- * @param $id : category_id of last level
- * @param $label : category title of last level
- * @param $parents : array of parent nodes
- * -----------------------------------------------------------------------------
- */
-
-// initialize variables needed if not passed
-// (needed while requiring breadcrumbs)
-if (!isset($id)) {
- $id = 0;
- $label = "";
- $parents = [];
-}
-
-?>
-<div class="top-bar">
-
- <?php // breadcrumbs
- ////////////////////////////////////////////////////////////////////////
- Render::view("components/breadcrumbs", [
- 'id' => $id,
- 'label' => $label,
- 'parents' => $parents
- ]);
- ?>
-
- <?php // User management drop-down
- ////////////////////////////////////////////////////////////////////////
- Render::view('components/user-management');
- ?>
-
-</div><!-- /top-bar --> \ No newline at end of file
diff --git a/public/app/views/components/user-management.php b/public/app/views/components/user-management.php
deleted file mode 100644
index 636f2ff..0000000
--- a/public/app/views/components/user-management.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<div class="user">
-
- <div class="dropdown js-visitor">
- <button type="button" class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
- <i class="fa fa-regular fa-user"></i>
- Διαχείριση Λογαριασμού
- <span class="caret"></span>
- </button>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="/login">Είσοδος</a></li>
-
- <li><hr class="dropdown-divider"></li>
-
- <li><a class="dropdown-item" href="/registration">Εγγραφή</a></li>
- <li><a class="dropdown-item disabled" href="/reset-password">Επαναφορά password</a></li>
- </ul>
- </div>
-
- <div class="dropdown js-subscriber">
- <button type="button" class="btn btn-default dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
- <i class="fa fa-regular fa-user"></i>
- Διαχείριση Λογαριασμού <span class="caret"></span>
- </button>
- <ul class="dropdown-menu">
- <li><a class="dropdown-item" href="/account/profile">Διαχείριση Προφίλ</a></li>
- <li><a class="dropdown-item" href="/account/courses">Ύλη μαθημάτων</a></li>
- <li><a class="dropdown-item" href="/account/payments">Πληρωμές</a></li>
-
- <li><hr class="dropdown-divider"></li>
-
- <li><a class="dropdown-item" href="/logout">Έξοδος</a></li>
- </ul>
- </div>
-
-</div>
-
-
-<script>
- // if user is connected hide anonymous user menu and show connected user's content
- if (cookieExists('cluser') && (readCookie('cluser').includes('connected'))) {
- [].forEach.call(document.querySelectorAll('.js-visitor'), function (el) {
- el.style.display = 'none';
- });
- [].forEach.call(document.querySelectorAll('.js-subscriber'), function (el) {
- el.style.display = 'unset';
- });
-
- // also extract user's full name to personalize messages
- let connection = unescape(readCookie('cluser')).split(';');
- connection.shift(); // remove 1st item (="connection")
- let name = connection.join(' '); console.log(name);
- var node = document.querySelectorAll('.js-subscriber button')[0];
- node.innerHTML = `<i class="fa fa-regular fa-user"></i> ${name} <span class="caret"></span>`;
-
-
- } else { // else ... do the opposite
- [].forEach.call(document.querySelectorAll('.js-subscriber'), function (el) {
- el.style.display = 'none';
- });
- [].forEach.call(document.querySelectorAll('.js-visitor'), function (el) {
- el.style.display = 'unset';
- });
- }
-
-</script>
diff --git a/public/app/views/js/pdf-designer/application.php b/public/app/views/js/pdf-designer/application.php
index 1d77c67..7441094 100644
--- a/public/app/views/js/pdf-designer/application.php
+++ b/public/app/views/js/pdf-designer/application.php
@@ -11,6 +11,11 @@ function designer(data, defines) {
var elDate = d.toLocaleDateString('el-GR', options);
var year = d.getFullYear().toString();
+ // var tick_parts = defines.ticket.match(/.{1,4}/g) ?? [];
+ // var easyread_ticket = tick_parts.join('-');
+
+
+
// get labels from id-specified objects
let petition = 'Αίτηση';
@@ -104,7 +109,7 @@ function designer(data, defines) {
footer: {
text: [
'Αριθμός πρωτοκόλου: A124-2501-4568-7 / 2023-12-15',
- '\ndocument signature: ' + defines.ticket
+ '\ndocument signature: ' + defines.ticket
],
style: 'signature'
diff --git a/public/app/views/js/submit/application-form.php b/public/app/views/js/submit/application-form.php
index ed77c1f..2480d67 100644
--- a/public/app/views/js/submit/application-form.php
+++ b/public/app/views/js/submit/application-form.php
@@ -3,6 +3,7 @@
return { // select content data
subject: $('input[name=subject]').val(),
date: $('input[name=date]').val(),
+ type_id: 1, // 1 = application document
first_name: $('input[name=first_name]').val(),
last_name: $('input[name=last_name]').val(),
father_name: $('input[name=father_name]').val(),
@@ -14,7 +15,7 @@
sector: selected_text($('select[name=sector]')),
position: selected_text($('select[name=position]')),
request: $('textarea[name=request]').val(),
- now: Math.floor(Date.now() / 1000),
+ now: Math.floor(Date.now() / 1000), // client timestamp
ticket: ref.ticket
};
}
@@ -28,30 +29,22 @@
$('.content-form form').submit( event => {
event.preventDefault();
- if (false) {
- alert('Τα δυο passrods δεν ταιριάζουν!');
+ // select action url (add or update)
+ var request = '/petition/new';
- } else {
+ // send POST request
+ $.post(request, postObject())
+ .done(function( data ) {
+ console.log(data);
- var data = postObject();
+ if (data.success) { // ok ? redirect to panel
+ window.location.href = '/panel';
- var form_data = { // prepare data to post
- subject: $('input[name=of_department]').val(),
- content: JSON.stringify(data),
- on_date: $('input[name=date]').val(),
- user_id: $('input[name=id]').val()
+ } else { // error ? alert!
+ alert(data.error);
}
- // select action url (add or update)
- // var request = '/account/register';
- console.log(data);
-
- // send POST request
- // $.post(request, form_data)
- // .done(function( data ) {
- // $('.classroom .content-form').html(data.message)
- // });
- }
+ });
});
diff --git a/public/app/views/user/panel.php b/public/app/views/user/panel.php
index 6888a7a..01a3777 100644
--- a/public/app/views/user/panel.php
+++ b/public/app/views/user/panel.php
@@ -23,13 +23,21 @@
<div class="col-xs-12 col-sm-3 info">
<?php // menu
- ////////////////////////////////////////////////////////////////////
- Render::view('components/menu');
+ //////////////////////////////////////////////////////////////////
+ Render::view('components/menu', ['is_admin' => $is_admin]);
?>
</div>
<div class="col-xs-12 col-sm-9">
+ <?php // content sub-section
+ //////////////////////////////////////////////////////////////////
+ Render::view('components/'.$content, [
+ 'is_admin' => $is_admin,
+ 'user' => $user
+ ]);
+ ?>
+
<!-- content
** petitions datatable
* change password -> link out (?)
diff --git a/public/assets/css/class.css b/public/assets/css/class.css
index 173010f..ef9239e 100644
--- a/public/assets/css/class.css
+++ b/public/assets/css/class.css
@@ -43,6 +43,7 @@ select, select option {
font-weight: 400;
font-size: 1rem;
}
+body { margin: 1em 0; }
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { font-weight: 400; };
@@ -75,6 +76,11 @@ html, body {
.info li.list-group-item:hover { background: #f2f2f2; }
.info li.list-group-item.separator { border: 2px solid #f2f2f2; background: #f2f2f2; padding:1px 8px; color: #666; }
+
+
+.info p { font-size: 14px; line-height: 200%; margin-bottom: .33em; }
+.info h4 { font-size: 16px; font-weight: 400; }
+
/** micro-positioning classes
* -----------------------------------------------------------------------------
*/