diff options
| author | George Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2023-04-25 03:40:09 +0300 |
|---|---|---|
| committer | George Halkiadakis <gchalkiadakis@sklavenitis.co.gr> | 2023-04-25 03:40:09 +0300 |
| commit | 65d07ba64d45c77d2db16272710ec5702b34d641 (patch) | |
| tree | 4578793e288cd1a6dc08f87ab44d0e3568904c12 /public/app | |
| parent | 13753d58d6aceaea8f246040518d50f2eb06a8d9 (diff) | |
| download | classroom-65d07ba64d45c77d2db16272710ec5702b34d641.tar.gz classroom-65d07ba64d45c77d2db16272710ec5702b34d641.tar.bz2 classroom-65d07ba64d45c77d2db16272710ec5702b34d641.zip | |
front-end: putting everything together
Diffstat (limited to 'public/app')
| -rw-r--r-- | public/app/controllers/Auth.php | 48 | ||||
| -rw-r--r-- | public/app/controllers/Product.php | 52 | ||||
| -rw-r--r-- | public/app/controllers/Resolve.php | 91 | ||||
| -rw-r--r-- | public/app/controllers/admin/Course_admin.php | 33 | ||||
| -rw-r--r-- | public/app/controllers/cms/Course.php | 116 | ||||
| -rw-r--r-- | public/app/extends/Cache_service.php | 45 | ||||
| -rw-r--r-- | public/app/models/cms/Course_model.php | 45 | ||||
| -rw-r--r-- | public/app/routes/backend.php | 7 | ||||
| -rw-r--r-- | public/app/routes/frontend.php | 10 | ||||
| -rw-r--r-- | public/app/views/components/breadcrumbs.php | 6 | ||||
| -rw-r--r-- | public/app/views/components/lessons_list.php | 51 | ||||
| -rw-r--r-- | public/app/views/components/subcategories.php | 18 | ||||
| -rw-r--r-- | public/app/views/components/top_bar.php | 6 | ||||
| -rw-r--r-- | public/app/views/templates/course.php | 82 |
14 files changed, 406 insertions, 204 deletions
diff --git a/public/app/controllers/Auth.php b/public/app/controllers/Auth.php index b00843c..0570a5e 100644 --- a/public/app/controllers/Auth.php +++ b/public/app/controllers/Auth.php @@ -186,7 +186,7 @@ class Auth { $manager = new Classroom_manager(); if ($manager->hasUserToken()) { - echo 'user is connected'; + // user is connected; $token = $manager->getUserToken(); $user = $token->getUser(); @@ -226,9 +226,19 @@ class Auth { * to access the source * */ - public static function hasPermition($permit = []) + public static function hasPermition($permit = [0]) { - if ($permit == []) return true; + if (in_array(0, $permit)) { // permision 0 means public + return true; // permision 0 is always granted + } + + if ($user = $this->is_connected() === flase) { // if not connected + return false; // then no other permition is granted + } + + if ($user instanceof UserInterface) { + return ( !empty( array_intersect($permit, $user->getPrivileges()) ) ); + } } @@ -243,11 +253,11 @@ class Auth { * example: * [ * [ - * role => ['editor','designer'] + * role => [2, 3] * permition => ['10', '12', '18'] * ], * [ - * role => ['admin' , 'developερ'] + * role => [1 , 4] * ], * [ * permition => [ 3 ] @@ -256,12 +266,12 @@ class Auth { * * defines (and parses to) a requirements rule of: * [ - * user should be editor or designer - * and have permition 10 or 12 or 18 + * user should be creator or editor + * _AND_ have permition 10 or 12 or 18 * ] * OR * [ - * user should be an administratoe or developer + * user should be an administrator or developer * ] * OR * [ @@ -274,17 +284,25 @@ class Auth { { $authorized = false; foreach($requirements as $required) { - if ( (self::isGranted($required['role'] ?? [])) - && (self::hasPermition($required['permition'] ?? [])) ) { - $authorized = true; + + if (isset($required['role'])) { // if a role is required + if ( (self::isGranted($required['role'])) // authorize both role + && (self::hasPermition($required['permition'] ?? [ 0 ])) ) { // and permition + // $authorized = true; + return true; + } + + } else { // else, if not is not required + if (self::hasPermition($required['permition'] ?? [ 0 ])) { // authorize permition + // $authorized = true; + return true; + } } } return $authorized; } - - public static function forgot_pass() { } @@ -322,10 +340,10 @@ class Auth { } - public static function is_admin() + public static function in_admin_group() { $manager = new Classroom_manager(); - return ($manager->isGranted([1,2,3])); + return ($manager->isGranted([1, 2, 3])); } diff --git a/public/app/controllers/Product.php b/public/app/controllers/Product.php deleted file mode 100644 index 0193ed9..0000000 --- a/public/app/controllers/Product.php +++ /dev/null @@ -1,52 +0,0 @@ -<?php - -namespace app\controllers; - -use app\models\market\Product_model; -use app\models\market\ProductCategories_model; - -class Product { - - public static function fromUrl($url, $pathArr) - { - $product = proxy([\app\models\market\Product_model::class, 'fromUrl'], - [ $url ], CACHE_PRODUCT_TTL - ); - - // TODO: - // verify path, else redirect - - if ($product === false) { - header("HTTP/1.0 404 Not Found"); - render_view('error/404', ['message' => 'Of all the things I\'ve lost, I miss my mind the most.']); - return ; - } - - // render page - load_template('products', [ 'data' => [ - 'title' => $product['Title'], - 'seo' => [], - 'tree' => proxy( - [\app\models\market\ProductCategories_model::class, 'tree'], - [], CACHE_ROOT_TTL - ), - 'hierarchyPath' => explode('.', substr($product['Hierarchy'], 1, -1)), - 'sections' => [ - [ - 'view' => 'content/product_list/Product_List_Filters', - 'key' => 'filters', - 'data' => [] - ], - [ - 'view' => 'content/product/product_details', - 'key' => 'product', - 'data' => $product - ] - ] - ] - ]); - - } - - -} diff --git a/public/app/controllers/Resolve.php b/public/app/controllers/Resolve.php deleted file mode 100644 index 7b9222c..0000000 --- a/public/app/controllers/Resolve.php +++ /dev/null @@ -1,91 +0,0 @@ -<?php - -namespace app\controllers; - -use \Benchmark; - -/** Resolve class - * will resolve ambiguous utl-request patterns - * --- - * Then it can route the request to some controller; - * Alternatively it can proccess the request via Models - * and initiate the View engine - */ -class Resolve { - - public static function url($array) - { - $fullUrl = implode('/', $array); - $url = $array[count($array) - 1]; - - - if (!PRODUCTION) Benchmark::add_spot('proxy-page'); - - // proxying check if page with this url - $page = proxy( - [\app\models\cms\Page_model::class, 'fromUrl'], - [ $fullUrl ], CACHE_ROOT_TTL, - PROXY_CACHE_ERRORS - ); - // if page exist, construct page - if ($page !== false) { - // page exists, render page - load_template('base', [ 'page' => [ - 'title' => $page['Title'], - 'seo' => [], - 'sections' => [ - [ - 'view' => 'content/static', - 'key' => 'page', - 'data' => $page - ] - ] - ] - ]); - return ; - } - - - if (!PRODUCTION) Benchmark::add_spot('proxy-category'); - - // proxying check if products category with this url - $category = proxy( - [\app\models\market\ProductCategories_model::class, 'categoryFromUrl'], - [ $fullUrl ], CACHE_CATEGORY_TTL - ); - // if category exist, construct category - if ($category !== false) { - // render page - load_template('products', [ 'data' => [ - 'title' => $category['Title'], - 'seo' => [], - 'tree' => proxy( - [\app\models\market\ProductCategories_model::class, 'tree'], - [], CACHE_ROOT_TTL - ), - 'hierarchyPath' => explode('.', substr($category['Hierarchy'], 1, -1)), - 'sections' => [ - [ - 'view' => 'content/product_list/Product_List_Filters', - 'key' => 'filters', - 'data' => $category - ], - [ - 'view' => 'content/product_list/product_list', - 'key' => 'products', - 'data' => $category['products'] - ] - ] - ] - ]); - return ; - } - - - // not page nor category?: reply 404 - header("HTTP/1.0 404 Not Found"); - render_view('error/404', ['message' => 'Say something I\'m givin\' up on you.']); - - } - -}
\ No newline at end of file diff --git a/public/app/controllers/admin/Course_admin.php b/public/app/controllers/admin/Course_admin.php index bb4deb0..c2e06f2 100644 --- a/public/app/controllers/admin/Course_admin.php +++ b/public/app/controllers/admin/Course_admin.php @@ -5,6 +5,7 @@ namespace app\controllers\admin; use Registry; use Render; use app\models\cms\Course_model; +use app\extends\Cache_service; class Course_admin { @@ -22,15 +23,7 @@ class Course_admin { */ public static function breadcrumbs() { - $tree = proxy( // cache-get categories - [\app\models\cms\Course_model::class, 'category_tree'], - [], CACHE_ROOT_TTL - ); - $breadcrumbs = proxy( // cache-get breadcrumbs - [\app\models\cms\Course_model::class, 'breadcrumbs'], - [$tree], CACHE_ROOT_TTL - ); - Render::json($breadcrumbs); // send as json + Render::json( Cache_service::courses_struct()['breadcrumbs'] ); } /** add course @@ -75,26 +68,15 @@ class Course_admin { /** update courses cache * --- -- -- - - - + * Forces re-caching of courses tree * Shall run if anything changes to courses * * @param void - * @return (array): the two course caches + * @return (array): ['tree' => ..., 'breadcrumbs' => ... ] */ public static function update_courses_cache() { - $tree = proxy( // cache-get categories - [\app\models\cms\Course_model::class, 'category_tree'], - [], CACHE_ROOT_TTL, PROXY_IGNORE_CACHE - ); - $breadcrumbs = proxy( // cache-get breadcrumbs - [\app\models\cms\Course_model::class, 'breadcrumbs'], - [$tree], CACHE_ROOT_TTL, PROXY_IGNORE_CACHE - ); - - return [ - 'tree' => $tree, - 'breadcrumbs' => $breadcrumbs - ]; + return Cache_service::courses_struct(PROXY_IGNORE_CACHE); } @@ -289,10 +271,7 @@ class Course_admin { */ public static function files() { - return proxy( // cache-get files - [\app\models\cms\Course_model::class, 'files'], - [], CACHE_ROOT_TTL - ); + return Cache_service::files_attributes(); } diff --git a/public/app/controllers/cms/Course.php b/public/app/controllers/cms/Course.php index b671a5f..7e53d3a 100644 --- a/public/app/controllers/cms/Course.php +++ b/public/app/controllers/cms/Course.php @@ -6,9 +6,45 @@ use Registry; use Render; use app\controllers\Auth; use app\models\cms\Course_model; +use app\extends\Cache_service; class Course { + + /** PERMITION + * ------------------------------------------------------------------------- + */ + + + /** is admin or permited + * + * shortcut method for checking access authorization + * + * returns true if user belogns to the admin group + * or has the specified permition/privilege + * + * @param $privilege_id (int) + * + * NOTE: + * unlike the other authorization methods ... + * $privilege_id is NOT an array but a single privilege id + * + * @return true|false + */ + private static function is_admin_or_permited( $privilege_id) + { + return ( + Auth::in_admin_group() + || Auth::has_Permition([ $privilege_id ]) + ); + } + + + + /** FILES + * ------------------------------------------------------------------------- + */ + /** serve file by file_path * (request is valid only for admin users) * @@ -17,8 +53,10 @@ class Course { */ public static function serve_file($file_path) { - // check privileges - if (Auth::is_admin()) { // TODO: -OR- has prvivilege + $file = self::get_file_attributes($file_path); + + // if user is authorized + if (is_admin_or_permited($file['privilege_id'])) { $media_type = Registry::get('REQUEST')->GET['type']; // get media-type $real_path = MEDIA_STORAGE_ROOT . $file_path; // construct real path @@ -33,4 +71,78 @@ class Course { } } + + /** get_file_attributes + * + * returns attributes of a file + * (medias are proxied for speed optimization) + * + * @param $path (string) : file path + * @return $file attributes --or-- false + */ + private static function get_file_attributes($path) + { + $medias = Cache_service::files_attributes(); + + foreach($medias as $key => $medi) { + if ($medi['path'] == $path) { + return $medi; + } + } + + return false; + } + + + + /** COURSES + * ------------------------------------------------------------------------- + */ + + + public static function course($id) + { + $cache = Cache_service::courses_struct(); + $tree = $cache['tree']; + $breadcrumbs = $cache['breadcrumbs']; + $lessons = Course_model::lessons_of_course(intval($id)); + $id = intval($id); + + // print_r($breadcrumbs); die(); + + // find parent_ids of current category (to open the menu tree) + $course_path = []; + foreach($breadcrumbs[$id]['parents'] as $key => $parent) { + $course_path[] = intval($parent['id']); + } + $course_path[] = intval($id); + + Render::view('templates/course', [ + 'id' => $id, + 'title' => $breadcrumbs[ $id ]['rec']['label'], + 'categories' => $tree, + 'breadcrumbs' => $breadcrumbs, + 'lessons' => $lessons, + 'course_path' => $course_path + ]); + } + + + + + + + /** LESSONS + * ------------------------------------------------------------------------ + */ + + + + + + + + + + }
\ No newline at end of file diff --git a/public/app/extends/Cache_service.php b/public/app/extends/Cache_service.php new file mode 100644 index 0000000..e44cc8e --- /dev/null +++ b/public/app/extends/Cache_service.php @@ -0,0 +1,45 @@ +<?php +namespace app\extends; + +use app\models\cms\Course_model; +use app\models\admin\Privilege_model; + +/** Cache service + * ----------------------------------------------------------------------------- + * + * class that gathers common source-expensive queries + * and helps for performance optimization + * + */ +class Cache_service +{ + + public static function courses_struct( $options = 0 ) + { + return proxy( // cache-get categories + [\app\models\cms\Course_model::class, 'courses_struct'], + [], CACHE_ROOT_TTL, $options + ); + } + + public static function files_attributes( $options = 0 ) + { + return proxy( + [\app\models\cms\Course_model::class, 'files'], + [], CACHE_ROOT_TTL, $options + ); + } + + + public static function privileges_hierarchy( $options = 0 ) + { + return proxy( + [\app\models\admin\Privilege_model::class, 'privileges'], + [], CACHE_ROOT_TTL, $options + ); + } + + + + +}
\ No newline at end of file diff --git a/public/app/models/cms/Course_model.php b/public/app/models/cms/Course_model.php index 3d0ac1c..d8a8a0e 100644 --- a/public/app/models/cms/Course_model.php +++ b/public/app/models/cms/Course_model.php @@ -6,6 +6,10 @@ use \Registry; class Course_model { + /** COURSES + * ------------------------------------------------------------------------- + */ + /** get all categories * * raw table data (simplest SELECT) @@ -19,6 +23,21 @@ class Course_model { ); } + /** 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 * @@ -216,6 +235,32 @@ class Course_model { } + + + /** LESSONS + * ------------------------------------------------------------------------- + */ + + + /** lessons of course + * + * @param $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", + [':id' => $id] + ); + } + + + /** files * return all files * @param void diff --git a/public/app/routes/backend.php b/public/app/routes/backend.php index 5d6189d..475f52b 100644 --- a/public/app/routes/backend.php +++ b/public/app/routes/backend.php @@ -3,7 +3,7 @@ use app\controllers\Auth; use app\controllers\admin\Course_admin; use app\models\admin\Privilege_model; - +use app\extends\Cache_service; // admin panel // --- @@ -91,10 +91,7 @@ Route::add('/admin/privileges', function () { // --- Route::add('/admin/api/privileges', function () { Auth::allowRoles([1, 2, 3]); // allow few admin-panel roles - Render::json( proxy( - [\app\models\admin\Privilege_model::class, 'privileges'], - [], CACHE_ROOT_TTL - )); + Render::json( Cache_service::privileges_hierarchy() ); }); // add privilege diff --git a/public/app/routes/frontend.php b/public/app/routes/frontend.php index 898b23a..f9e74db 100644 --- a/public/app/routes/frontend.php +++ b/public/app/routes/frontend.php @@ -4,15 +4,13 @@ use app\controllers\Auth; use app\controllers\Classroom_user; use app\controllers\cms\Course; use app\models\cms\Course_model; +use app\extends\Cache_service; // Home/Welcome // --- Route::add('/', function() { // echo 'Welcome!'; }); Render::view('welcome', [ // cache categories (while retrieving) - 'categories' => proxy( - [\app\models\cms\Course_model::class, 'category_tree'], - [], CACHE_ROOT_TTL - ) + 'categories' => Cache_service::courses_struct()['tree'] ]); // header('Location: /some/default/url', true, 302); }); @@ -46,8 +44,8 @@ Route::notFound( function() { // Resolve urls // --- -- -- - - - -Route::add('/course/([0-9a-zA-Z-_]*)', - function($label) { Course::show([$label]); } +Route::add('/course/([0-9]*)', + function($id) { Course::course($id); } ); Route::add('/lesson/([0-9a-f]*)/([0-9a-zA-Z-_]*)', diff --git a/public/app/views/components/breadcrumbs.php b/public/app/views/components/breadcrumbs.php index 471cfb6..90b4af9 100644 --- a/public/app/views/components/breadcrumbs.php +++ b/public/app/views/components/breadcrumbs.php @@ -5,7 +5,7 @@ * imported variables * --- * @param $id : category_id of last level - * @param $title : category title of last level + * @param $label : category title of last level * @param $parents : array of parent nodes * ----------------------------------------------------------------------------- */ @@ -18,13 +18,13 @@ <!-- parent nodes --> <?php if ($id != 0) : ?> <?php foreach($parents as $node) : ?> - <i class="fas fa-angle-right"></i> <a href="/wiki/category?id=<?=$node['id']?>"><?=$node['title']?></a> + <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="/wiki/category?id=<?=$id?>"><?=$title?></a> + <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/lessons_list.php b/public/app/views/components/lessons_list.php new file mode 100644 index 0000000..1c59164 --- /dev/null +++ b/public/app/views/components/lessons_list.php @@ -0,0 +1,51 @@ +<?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'] + * ]) + * ----------------------------------------------------------------------------- + */ +?> +<div class="row"> + + <?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('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; ?> + +</div>
\ No newline at end of file diff --git a/public/app/views/components/subcategories.php b/public/app/views/components/subcategories.php new file mode 100644 index 0000000..58f53fa --- /dev/null +++ b/public/app/views/components/subcategories.php @@ -0,0 +1,18 @@ +<!-- 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 index ed96e35..0e6e437 100644 --- a/public/app/views/components/top_bar.php +++ b/public/app/views/components/top_bar.php @@ -3,9 +3,9 @@ <?php // breadcrumbs //////////////////////////////////////////////////////////////////////// Render::template("components/breadcrumbs", [ - 'id' => 0, - 'title' => '', - 'parents' => [] + 'id' => $id, + 'label' => $label, + 'parents' => $parents ]); ?> diff --git a/public/app/views/templates/course.php b/public/app/views/templates/course.php new file mode 100644 index 0000000..9d42297 --- /dev/null +++ b/public/app/views/templates/course.php @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title><?=SITE_TITLE?> - <?=$title?></title> + + <?php // header includes + //////////////////////////////////////////////////////////////////////// + Render::view('components/header_includes'); + ?> + +</head> +<body class="classroom"> + + <?php // top-bar + //////////////////////////////////////////////////////////////////////// + Render::view('components/top_bar', [ + 'id' => $id, + 'label' => $breadcrumbs[ $id ]['rec']['label'], + 'parents' => $breadcrumbs[ $id ]['parents'] + ]); + ?> + + +<div class="main-content container"> + <div class="row"> + + <div class="col col-md-5 col-lg-4 d-sm-none d-md-block side-bar"> + + <?php // tree of courses + //////////////////////////////////////////////////////////////////////// + Render::view('components/courses_menu', [ + 'categories' => $categories, + 'open_path' => $course_path + ]); + ?> + + </div> + + <div class="col col-sm-12 col-md-7 col-lg-8 course-view"> + + <!-- Category Title --> + <h3> + <?=$breadcrumbs[ $id ]['rec']['label']?> + </h3> + + + <!-- Sub-Categories --> + <?php + Render::view('components/subcategories',[ + 'id' => $id, + 'breadcrumbs' => $breadcrumbs + ]) + ?> + + + <!-- Articles List --> + <?php if ($lessons) : ?> + + <h5>Μαθήματα</h5> + + <?php // list of posts/articles + //////////////////////////////////////////////////// + Render::view("components/lessons_list", [ + 'lessons' => $lessons, + 'fieldset' => ['intro'] // ['intro', 'date'] + ]); + ?> + <?php endif; ?> + + + + + </div> + + </div> + </div> + + + <script src="/assets/js/classroom.js"></script> +</body> +</html> |
