From 993a4f92d6a1d35c2aa0284c5a475fa2f021db52 Mon Sep 17 00:00:00 2001 From: dignajar Date: Sat, 16 Jan 2021 13:03:16 +0100 Subject: [PATCH] API create/edit/delete category, UI for manage categories, UI for manage users still in progress, improvments in dbList class, warn the user when didn't save the progress in the editor --- bl-kernel/abstract/dblist.class.php | 24 ++- bl-kernel/admin/controllers/about.php | 14 +- bl-kernel/admin/controllers/add-category.php | 2 +- bl-kernel/admin/controllers/add-user.php | 2 +- bl-kernel/admin/controllers/categories.php | 16 +- bl-kernel/admin/controllers/edit-category.php | 25 +-- bl-kernel/admin/controllers/edit-user.php | 45 +----- bl-kernel/admin/controllers/plugins.php | 16 +- bl-kernel/admin/controllers/themes.php | 2 +- bl-kernel/admin/controllers/users.php | 21 +-- bl-kernel/admin/themes/booty/html/alerts.php | 11 +- bl-kernel/admin/themes/booty/html/sidebar.php | 26 ++-- bl-kernel/admin/views/add-category.php | 3 +- bl-kernel/admin/views/add-user.php | 4 +- bl-kernel/admin/views/edit-category.php | 147 +++++++++--------- bl-kernel/admin/views/editor.php | 22 ++- bl-kernel/admin/views/editor/file-manager.php | 2 +- bl-kernel/boot/init.php | 3 +- bl-kernel/boot/variables.php | 2 +- bl-kernel/functions.php | 136 ++++++++++------ bl-kernel/helpers/bootstrap.class.php | 14 +- bl-kernel/js/api.js | 50 ++++++ bl-kernel/pages.class.php | 7 +- bl-kernel/pagex.class.php | 10 +- bl-languages/en.json | 4 +- bl-plugins/api/plugin.php | 53 ++++++- bl-themes/blogx/index.php | 7 +- 27 files changed, 392 insertions(+), 276 deletions(-) diff --git a/bl-kernel/abstract/dblist.class.php b/bl-kernel/abstract/dblist.class.php index 42d8a8b5..55610f22 100644 --- a/bl-kernel/abstract/dblist.class.php +++ b/bl-kernel/abstract/dblist.class.php @@ -99,6 +99,11 @@ class dbList extends dbJSON return $key; } + /* Delete an item from the dblist === Bludit v4 + + @key string Key of the item to be deleted + @returns boolean Returns TRUE if the database was successfully saved, FALSE otherwise + */ public function remove($key) { if (!isset($this->db[$key])) { @@ -184,16 +189,21 @@ class dbList extends dbJSON return false; } - // Returns an array with a portion of the database filtered by key - // Returns array( 'key'=>'', 'name'=>'', 'template'=>'', 'description'=>'', list'=>array() ) + /* Returns an array with a portion of the database filtered by key === Bludit v4 + + @key string The item key + @returns array/bool Returns the following structure array('key'=>'', 'name'=>'', 'template'=>'', 'description'=>'', list'=>array()), FALSE if the key doesn't exist + */ public function getMap($key) { - if (isset($this->db[$key])) { - $tmp = $this->db[$key]; - $tmp['key'] = $key; - return $tmp; + if (!$this->exists($key)) { + Log::set(__METHOD__.LOG_SEP.'The item doesn\'t exist. Key: '.$key); + return false; } - return false; + + $tmp = $this->db[$key]; + $tmp['key'] = $key; + return $tmp; } } \ No newline at end of file diff --git a/bl-kernel/admin/controllers/about.php b/bl-kernel/admin/controllers/about.php index a27002e5..34b62b19 100644 --- a/bl-kernel/admin/controllers/about.php +++ b/bl-kernel/admin/controllers/about.php @@ -1,4 +1,16 @@ $layout['title'] = $L->g('About') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/add-category.php b/bl-kernel/admin/controllers/add-category.php index 5284f90c..6529ab51 100644 --- a/bl-kernel/admin/controllers/add-category.php +++ b/bl-kernel/admin/controllers/add-category.php @@ -15,4 +15,4 @@ checkRole(array('admin')); // ============================================================================ // HTML -$layout['title'] .= ' - '.$L->g('New category'); \ No newline at end of file +$layout['title'] = $L->g('New category') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/add-user.php b/bl-kernel/admin/controllers/add-user.php index 68659d3a..3783450a 100644 --- a/bl-kernel/admin/controllers/add-user.php +++ b/bl-kernel/admin/controllers/add-user.php @@ -15,4 +15,4 @@ checkRole(array('admin')); // ============================================================================ // HTML <title> -$layout['title'] .= ' - '.$L->g('New user'); \ No newline at end of file +$layout['title'] = $L->g('New user') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/categories.php b/bl-kernel/admin/controllers/categories.php index 3a22161b..baf4a0d0 100644 --- a/bl-kernel/admin/controllers/categories.php +++ b/bl-kernel/admin/controllers/categories.php @@ -1,7 +1,7 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); // ============================================================================ -// Check role +// Authorization // ============================================================================ checkRole(array('admin')); @@ -11,16 +11,8 @@ checkRole(array('admin')); // ============================================================================ // ============================================================================ -// Main before POST +// Main // ============================================================================ -// ============================================================================ -// POST Method -// ============================================================================ - -// ============================================================================ -// Main after POST -// ============================================================================ - -// Title of the page -$layout['title'] .= ' - '.$L->g('Categories'); \ No newline at end of file +// HTML <title> +$layout['title'] = $L->g('Categories') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/edit-category.php b/bl-kernel/admin/controllers/edit-category.php index 9df8f48c..ac4fa37a 100644 --- a/bl-kernel/admin/controllers/edit-category.php +++ b/bl-kernel/admin/controllers/edit-category.php @@ -1,7 +1,7 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); // ============================================================================ -// Check role +// Authorization // ============================================================================ checkRole(array('admin')); @@ -11,26 +11,9 @@ checkRole(array('admin')); // ============================================================================ // ============================================================================ -// Main before POST +// Main // ============================================================================ -// ============================================================================ -// POST Method -// ============================================================================ - -if ($_SERVER['REQUEST_METHOD'] == 'POST') { - if ($_POST['action']=='delete') { - deleteCategory($_POST); - } elseif ($_POST['action']=='edit') { - editCategory($_POST); - } - - Redirect::page('categories'); -} - -// ============================================================================ -// Main after POST -// ============================================================================ $categoryKey = $layout['parameters']; if (!$categories->exists($categoryKey)) { @@ -40,5 +23,5 @@ if (!$categories->exists($categoryKey)) { $categoryMap = $categories->getMap($categoryKey); -// Title of the page -$layout['title'] .= ' - '.$L->g('Edit Category').' [ '.$categoryMap['name'] . ' ] '; \ No newline at end of file +// HTML <title> +$layout['title'] = $L->g('Edit Category') . ' [ ' . $categoryMap['name'] . ' ] ' . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/edit-user.php b/bl-kernel/admin/controllers/edit-user.php index 7caa38e4..bc6b0304 100644 --- a/bl-kernel/admin/controllers/edit-user.php +++ b/bl-kernel/admin/controllers/edit-user.php @@ -1,46 +1,15 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); +// ============================================================================ +// Authorization +// ============================================================================ + // ============================================================================ // Functions // ============================================================================ // ============================================================================ -// Main before POST -// ============================================================================ - -// ============================================================================ -// POST Method -// ============================================================================ - -if ($_SERVER['REQUEST_METHOD'] == 'POST') { - // Prevent non-administrators to change other users - if ($login->role()!=='admin') { - $_POST['username'] = $login->username(); - unset($_POST['role']); - } - - if (isset($_POST['deleteUserAndDeleteContent']) && ($login->role()==='admin')) { - $_POST['deleteContent'] = true; - deleteUser($_POST); - } elseif (isset($_POST['deleteUserAndKeepContent']) && ($login->role()==='admin')) { - $_POST['deleteContent'] = false; - deleteUser($_POST); - } elseif (isset($_POST['disableUser']) && ($login->role()==='admin')) { - disableUser(array('username'=>$_POST['username'])); - } else { - editUser($_POST); - } - - Alert::set($L->g('The changes have been saved')); - - if ($login->role()==='admin') { - Redirect::page('users'); - } - Redirect::page('edit-user/'.$login->username()); -} - -// ============================================================================ -// Main after POST +// Main // ============================================================================ $username = $layout['parameters']; @@ -56,5 +25,5 @@ try { Redirect::page('users'); } -// Title of the page -$layout['title'] = $L->g('Edit user').' - '.$layout['title']; \ No newline at end of file +// HTML <title> +$layout['title'] = $L->g('Edit user') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/plugins.php b/bl-kernel/admin/controllers/plugins.php index 074f555a..8c5f62df 100644 --- a/bl-kernel/admin/controllers/plugins.php +++ b/bl-kernel/admin/controllers/plugins.php @@ -1,7 +1,7 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); // ============================================================================ -// Check role +// Authorization // ============================================================================ checkRole(array('admin')); @@ -11,16 +11,8 @@ checkRole(array('admin')); // ============================================================================ // ============================================================================ -// Main before POST +// Main // ============================================================================ -// ============================================================================ -// POST Method -// ============================================================================ - -// ============================================================================ -// Main after POST -// ============================================================================ - -// Title of the page -$layout['title'] .= ' - '.$L->g('Plugins'); \ No newline at end of file +// HTML <title> +$layout['title'] = $L->g('Plugins') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/themes.php b/bl-kernel/admin/controllers/themes.php index 43e3dbf3..8b503f06 100644 --- a/bl-kernel/admin/controllers/themes.php +++ b/bl-kernel/admin/controllers/themes.php @@ -21,4 +21,4 @@ checkRole(array('admin')); $themes = buildThemes(); // Title of the page -$layout['title'] .= ' - '.$L->g('Themes'); \ No newline at end of file +$layout['title'] = $L->g('Themes') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/controllers/users.php b/bl-kernel/admin/controllers/users.php index a9a00232..7f1f4ca1 100644 --- a/bl-kernel/admin/controllers/users.php +++ b/bl-kernel/admin/controllers/users.php @@ -1,7 +1,7 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); // ============================================================================ -// Check role +// Authorization // ============================================================================ checkRole(array('admin')); @@ -11,21 +11,8 @@ checkRole(array('admin')); // ============================================================================ // ============================================================================ -// Main after POST +// Main // ============================================================================ -// ============================================================================ -// POST Method -// ============================================================================ - -if( $_SERVER['REQUEST_METHOD'] == 'POST' ) -{ - $site->set($_POST); -} - -// ============================================================================ -// Main after POST -// ============================================================================ - -// Title of the page -$layout['title'] .= ' - '.$L->g('Users'); \ No newline at end of file +// HTML <title> +$layout['title'] = $L->g('Users') . ' - ' . $layout['title']; \ No newline at end of file diff --git a/bl-kernel/admin/themes/booty/html/alerts.php b/bl-kernel/admin/themes/booty/html/alerts.php index 7de14ba1..42cc2dad 100644 --- a/bl-kernel/admin/themes/booty/html/alerts.php +++ b/bl-kernel/admin/themes/booty/html/alerts.php @@ -1,8 +1,7 @@ <div aria-live="polite" aria-atomic="true" class="position-relative"> - <div class="toast-container position-absolute top-0 end-0 p-3" style="z-index:1050;"> - <div id="alert" class="toast d-flex align-items-center text-white border-0" role="alert" aria-live="assertive" aria-atomic="true"> - <div class="toast-body">Hello, I'm a Bludit alert!</div> - <button type="button" class="btn-close btn-close-white ms-auto me-2" data-bs-dismiss="toast" aria-label="Close"></button> + <div class="toast-container position-absolute start-50 translate-middle-x mt-3" style="z-index:1050;"> + <div id="alert" class="toast text-center text-white border-0 p-3" role="alert" aria-live="assertive" aria-atomic="true"> + Hello, I'm a Bludit alert! </div> </div> </div> @@ -10,7 +9,7 @@ <script> function showAlert(text, background='primary') { $('#alert').removeClass('bg-danger bg-warning bg-primary').addClass('bg-'+background); - $('#alert').children('.toast-body').html(text); + $('#alert').html(text); $('#alert').toast('show'); } @@ -22,7 +21,7 @@ function showAlertWarning(text) { showAlert(text, 'warning'); } -function showAlerInfo(text) { +function showAlertInfo(text) { showAlert(text, 'primary'); } diff --git a/bl-kernel/admin/themes/booty/html/sidebar.php b/bl-kernel/admin/themes/booty/html/sidebar.php index c7407daf..ac778679 100644 --- a/bl-kernel/admin/themes/booty/html/sidebar.php +++ b/bl-kernel/admin/themes/booty/html/sidebar.php @@ -3,29 +3,29 @@ <li class="nav-item mb-3"> <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'editor' ?>"> - <i class="bi-plus-circle"></i> + <i class="bi bi-plus-circle"></i> <?php $L->p('New content') ?> </a> </li> <li class="nav-item"> <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'dashboard' ?>"> - <i class="bi-kanban"></i> + <i class="bi bi-kanban"></i> <?php $L->p('Dashboard') ?> </a> </li> <li class="nav-item"> <a class="nav-link" href="<?php echo DOMAIN_BASE ?>"> - <i class="bi-house"></i> + <i class="bi bi-house"></i> <?php $L->p('Website') ?> </a> </li> <?php if (!checkRole(array('admin'),false)): ?> <li class="nav-item"> - <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'content' ?>"><span class="bi-archive"></span><?php $L->p('Content') ?></a> + <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'content' ?>"><span class="bi bi-archive"></span><?php $L->p('Content') ?></a> </li> <li class="nav-item"> - <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'edit-user/'.$login->username() ?>"><span class="bi-user"></span><?php $L->p('Profile') ?></a> + <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'edit-user/'.$login->username() ?>"><span class="bi bi-user"></span><?php $L->p('Profile') ?></a> </li> <?php endif; ?> @@ -36,19 +36,19 @@ </li> <li class="nav-item"> <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'content' ?>"> - <i class="bi-folder"></i> + <i class="bi bi-folder"></i> <?php $L->p('Content') ?> </a> </li> <li class="nav-item"> <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'categories' ?>"> - <i class="bi-bookmark"></i> + <i class="bi bi-bookmark"></i> <?php $L->p('Categories') ?> </a> </li> <li class="nav-item"> <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'users' ?>"> - <i class="bi-people"></i> + <i class="bi bi-people"></i> <?php $L->p('Users') ?> </a> </li> @@ -57,16 +57,16 @@ <h4><?php $L->p('Settings') ?></h4> </li> <li class="nav-item"> - <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'settings' ?>"><?php $L->p('General') ?></a> + <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'settings' ?>"><span class="bi bi-gear"></span><?php $L->p('General') ?></a> </li> <li class="nav-item"> - <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'plugins' ?>"><?php $L->p('Plugins') ?></a> + <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'plugins' ?>"><span class="bi bi-node-plus"></span><?php $L->p('Plugins') ?></a> </li> <li class="nav-item"> - <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'themes' ?>"><?php $L->p('Themes') ?></a> + <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'themes' ?>"><span class="bi bi-display"></span><?php $L->p('Themes') ?></a> </li> <li class="nav-item"> - <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'about' ?>"><?php $L->p('About') ?></a> + <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'about' ?>"><span class="bi bi-info-circle"></span><?php $L->p('About') ?></a> </li> <?php endif; ?> @@ -87,6 +87,6 @@ <?php endif; ?> <li class="nav-item mt-5"> - <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'logout' ?>"><span class="bi-arrow-circle-right"></span><?php $L->p('Logout') ?></a> + <a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'logout' ?>"><span class="bi bi-door-closed"></span><?php $L->p('Logout') ?></a> </li> </ul> diff --git a/bl-kernel/admin/views/add-category.php b/bl-kernel/admin/views/add-category.php index bbf81c27..14b44eaf 100644 --- a/bl-kernel/admin/views/add-category.php +++ b/bl-kernel/admin/views/add-category.php @@ -31,7 +31,7 @@ echo Bootstrap::formTextarea(array( var name = $('#name').val(); if (name.length < 1) { - showAlertError("<?php $L->p('Please complete the name field.') ?>"); + showAlertError("<?php $L->p('Complete all fields') ?>"); return false; } @@ -43,7 +43,6 @@ echo Bootstrap::formTextarea(array( logs('Category created. Key: ' + key); window.location.replace('<?php echo HTML_PATH_ADMIN_ROOT . 'categories' ?>'); }); - showAlertInfo("Category created."); return true; }); }); diff --git a/bl-kernel/admin/views/add-user.php b/bl-kernel/admin/views/add-user.php index fc805e4c..e6ae9d50 100644 --- a/bl-kernel/admin/views/add-user.php +++ b/bl-kernel/admin/views/add-user.php @@ -57,7 +57,7 @@ echo Bootstrap::formInputText(array( var confirmPassword = $('#confirmPassword').val(); if (username.length < 1) { - showAlertError("<?php $L->p('Please complete the username field.') ?>"); + showAlertError("<?php $L->p('Complete all fields') ?>"); return false; } @@ -81,8 +81,6 @@ echo Bootstrap::formInputText(array( logs('User created. Username: ' + username); window.location.replace(HTML_PATH_ADMIN_ROOT + 'users'); }); - - showAlertInfo("User created."); return true; }); }); diff --git a/bl-kernel/admin/views/edit-category.php b/bl-kernel/admin/views/edit-category.php index da29d1f2..bbadb23c 100644 --- a/bl-kernel/admin/views/edit-category.php +++ b/bl-kernel/admin/views/edit-category.php @@ -1,92 +1,85 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); ?> -<?php echo Bootstrap::formOpen(array('id'=>'jsform')); ?> - -<div class="align-middle"> - <div class="float-end mt-1"> - <button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button> - <button type="button" class="btn btn-danger btn-sm" data-toggle="modal" data-target="#jsdeleteModal"><?php $L->p('Delete') ?></button> - <a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'dashboard' ?>" role="button"><?php $L->p('Cancel') ?></a> +<div class="d-flex align-items-center mb-4"> + <h2 class="m-0"><i class="bi bi-bookmark"></i><?php $L->p('Edit category') ?></h2> + <div class="ms-auto"> + <button id="btnSave" type="button" class="btn btn-primary btn-sm"><?php $L->p('Save') ?></button> + <button id="btnDelete" type="button" class="btn btn-danger btn-sm"><?php $L->p('Delete') ?></button> + <a id="btnCancel" class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'categories' ?>" role="button"><?php $L->p('Cancel') ?></a> </div> - <?php echo Bootstrap::pageTitle(array('title'=>$L->g('Edit Category'), 'icon'=>'cog')); ?> </div> <?php - // Token CSRF - echo Bootstrap::formInputHidden(array( - 'name'=>'tokenCSRF', - 'value'=>$security->getTokenCSRF() - )); +echo Bootstrap::formInputHidden(array( + 'id' => 'key', + 'name' => 'key', + 'value' => $categoryMap['key'] +)); - echo Bootstrap::formInputHidden(array( - 'name'=>'action', - 'value'=>'edit' - )); +echo Bootstrap::formInputText(array( + 'id' => 'name', + 'name' => 'name', + 'label' => $L->g('Name'), + 'value' => $categoryMap['name'] +)); - echo Bootstrap::formInputHidden(array( - 'name'=>'oldKey', - 'value'=>$categoryMap['key'] - )); +echo Bootstrap::formTextarea(array( + 'name' => 'description', + 'label' => $L->g('Description'), + 'value' => isset($categoryMap['description']) ? $categoryMap['description'] : '', + 'rows' => 3 +)); - echo Bootstrap::formInputText(array( - 'name'=>'name', - 'label'=>$L->g('Name'), - 'value'=>$categoryMap['name'], - 'class'=>'', - 'placeholder'=>'', - 'tip'=>'' - )); - - echo Bootstrap::formTextarea(array( - 'name'=>'description', - 'label'=>$L->g('Description'), - 'value'=>isset($categoryMap['description'])?$categoryMap['description']:'', - 'class'=>'', - 'placeholder'=>'', - 'tip'=>'', - 'rows'=>3 - )); - - echo Bootstrap::formInputText(array( - 'name'=>'template', - 'label'=>$L->g('Template'), - 'value'=>isset($categoryMap['template'])?$categoryMap['template']:'', - 'class'=>'', - 'placeholder'=>'', - 'tip'=>'' - )); - - echo Bootstrap::formInputText(array( - 'name'=>'newKey', - 'label'=>$L->g('Friendly URL'), - 'value'=>$categoryMap['key'], - 'class'=>'', - 'placeholder'=>'', - 'tip'=>DOMAIN_CATEGORIES.$categoryMap['key'] - )); - -echo Bootstrap::formClose(); +echo Bootstrap::formInputText(array( + 'name' => 'template', + 'label' => $L->g('Template'), + 'value' => isset($categoryMap['template']) ? $categoryMap['template'] : '' +)); +echo Bootstrap::formInputText(array( + 'name' => 'friendlyURL', + 'label' => $L->g('Friendly URL'), + 'value' => $categoryMap['key'], + 'tip' => DOMAIN_CATEGORIES . $categoryMap['key'] +)); ?> -<!-- Modal for delete category --> -<?php - echo Bootstrap::modal(array( - 'buttonPrimary'=>$L->g('Delete'), - 'buttonPrimaryClass'=>'btn-danger jsbuttonDeleteAccept', - 'buttonSecondary'=>$L->g('Cancel'), - 'buttonSecondaryClass'=>'btn-link', - 'modalTitle'=>$L->g('Delete category'), - 'modalText'=>$L->g('Are you sure you want to delete this category?'), - 'modalId'=>'jsdeleteModal' - )); -?> <script> -$(document).ready(function() { - // Delete content - $(".jsbuttonDeleteAccept").on("click", function() { - $("#jsaction").val("delete"); - $("#jsform").submit(); + $(document).ready(function() { + $('#btnSave').on('click', function() { + var name = $('#name').val(); + var friendlyURL = $('#friendlyURL').val(); + + if ((name.length < 1) || (friendlyURL.length < 1)) { + showAlertError("<?php $L->p('Complete all fields') ?>"); + return false; + } + + var args = { + key: $('#key').val(), + name: name, + description: $('#description').val(), + friendlyURL: $('#friendlyURL').val(), + template: $('#template').val() + }; + api.editCategory(args).then(function(key) { + logs('Category edited. Key: ' + key); + showAlertInfo("<?php $L->p('The changes have been saved') ?>"); + }); + return true; + }); + + $('#btnDelete').on('click', function() { + var key = $('#key').val(); + logs('Deleting category. Key: ' + key); + var args = { + key: key + }; + api.deleteCategory(args).then(function(key) { + logs('Category deleted. Key: ' + key); + window.location.replace(HTML_PATH_ADMIN_ROOT + 'categories'); + }); + return true; + }); }); -}); </script> \ No newline at end of file diff --git a/bl-kernel/admin/views/editor.php b/bl-kernel/admin/views/editor.php index f890f8c6..add39f42 100644 --- a/bl-kernel/admin/views/editor.php +++ b/bl-kernel/admin/views/editor.php @@ -89,11 +89,11 @@ } function disableBtnSave() { - $('#btnSave').addClass('btn-primary-disabled').html('<i class="bi bi-check-square"></i><?php $L->p('Saved') ?>'); + $('#btnSave').addClass('btn-primary-disabled').attr('data-current', 'saved').html('<i class="bi bi-check-square"></i><?php $L->p('Saved') ?>'); } function enableBtnSave() { - $('#btnSave').removeClass('btn-primary-disabled').html('<i class="bi bi-save"></i><?php $L->p('Save') ?>'); + $('#btnSave').removeClass('btn-primary-disabled').attr('data-current', 'unsaved').html('<i class="bi bi-save"></i><?php $L->p('Save') ?>'); } // This function is to catch all key press and provides shortcuts @@ -117,6 +117,11 @@ return false; } + // Ctrl+ or Command+ or Alt+ or Shift+ or Option+ + if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) { + return true; + } + enableBtnSave(); return true; } @@ -128,10 +133,21 @@ // Main interface events // ------------------------------------------------------------------------ + + // Catch all keypress for shortcuts or other actions $(this).keydown(function(event) { keypress(event); }); + // Warn the user to save the changes before leave + $(window).bind('beforeunload', function(e) { + if ($('#btnSave').attr('data-current')=='unsaved') { + (e || window.event).returnValue = ''; + return ''; + } + return undefined; // Return undefined to continue the unload + }); + $('#btnSave').on('click', function() { var args = { title: $('#title').val(), @@ -505,7 +521,7 @@ <!-- Toolbar > Save, Preview, Type and Options --> <div id="editorToolbar" class="d-flex align-items-center mb-2"> <div id="editorToolbarLeft"> - <button id="btnSave" type="button" class="btn btn-sm btn-primary btn-primary-disabled"><i class="bi bi-save"></i><?php $L->p('Saved') ?></button> + <button id="btnSave" type="button" data-current="saved" class="btn btn-sm btn-primary btn-primary-disabled"><i class="bi bi-save"></i><?php $L->p('Saved') ?></button> <button id="btnPreview" type="button" class="btn btn-sm btn-primary"><i class="bi bi-box-arrow-up-right"></i><?php $L->p('Preview') ?></button> <span id="btnCurrenType" class="ms-1"> <?php diff --git a/bl-kernel/admin/views/editor/file-manager.php b/bl-kernel/admin/views/editor/file-manager.php index 98f78a44..2e3095c1 100644 --- a/bl-kernel/admin/views/editor/file-manager.php +++ b/bl-kernel/admin/views/editor/file-manager.php @@ -135,7 +135,7 @@ logs('File Manager. Uploading file.'); // Check file type/extension - const validImageTypes = ['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml']; + const validImageTypes = ['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', 'application/pdf']; if (!validImageTypes.includes(file.type)) { logs("File Manager. File type is not supported."); showAlertError("<?php echo $L->g('File type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_EXTENSION']) ?>"); diff --git a/bl-kernel/boot/init.php b/bl-kernel/boot/init.php index e4cdea88..0bd98ae4 100644 --- a/bl-kernel/boot/init.php +++ b/bl-kernel/boot/init.php @@ -211,8 +211,9 @@ define('MARKDOWN_PARSER', $site->markdownParser()); // --- PHP paths with dependency --- // This paths are absolutes for the OS -define('THEME_DIR', PATH_ROOT.'bl-themes'.DS.$site->theme().DS); +define('THEME_DIR', PATH_ROOT.'bl-themes'.DS.$site->theme().DS); define('THEME_DIR_PHP', THEME_DIR.'php'.DS); +define('THEME_DIR_TEMPLATES', THEME_DIR.'templates'.DS); define('THEME_DIR_CSS', THEME_DIR.'css'.DS); define('THEME_DIR_JS', THEME_DIR.'js'.DS); define('THEME_DIR_IMG', THEME_DIR.'img'.DS); diff --git a/bl-kernel/boot/variables.php b/bl-kernel/boot/variables.php index 9fa15e62..3ec91ebd 100644 --- a/bl-kernel/boot/variables.php +++ b/bl-kernel/boot/variables.php @@ -110,4 +110,4 @@ $GLOBALS['DB_TAGS_TYPES'] = array('published','static','sticky'); $GLOBALS['ALLOWED_IMG_EXTENSION'] = array('gif', 'png', 'jpg', 'jpeg', 'svg'); // Allowed image mime types -$GLOBALS['ALLOWED_IMG_MIMETYPES'] = array('image/gif', 'image/png', 'image/jpeg', 'image/svg+xml'); +$GLOBALS['ALLOWED_IMG_MIMETYPES'] = array('image/gif', 'image/png', 'image/jpeg', 'image/svg+xml', 'application/pdf'); diff --git a/bl-kernel/functions.php b/bl-kernel/functions.php index 495ff0f9..1c2d5d2a 100644 --- a/bl-kernel/functions.php +++ b/bl-kernel/functions.php @@ -1,5 +1,16 @@ <?php defined('BLUDIT') or die('Bludit CMS.'); +/* ---------------------------------------------------------------------------- + Global functions + These function provides connectivity beteween differens objects and databases. + These function should provide different checks and logic before add/edit/delete into the databases. + + For example the creation of a user should check: + - if the user already exists + - if the username is not empty + - if the password match with the differents security rules such as min length +/* ---------------------------------------------------------------------------- + /* Create a new page === Bludit v4 @args array The array $args supports all the keys from the variable $dbFields of the class pages.class.php. If you don't pass all the keys, the default values are used. @@ -118,7 +129,7 @@ function deletePage($key) { /* Create a new category === Bludit v4 - @args array The array $args supports all the keys from the variable $dbFields of the class categories.class.php. If you don't pass all the keys, the default values are used. + @args array Array => (name: string, template: string, description: string) @returns string/boolean Returns the category key if the category is successfully created, FALSE otherwise */ function createCategory($args) { @@ -145,6 +156,82 @@ function createCategory($args) { return false; } +/* Edit a category === Bludit v4 + + @args array Array => (key: string, name: string, friendlyURL: string, template: string, description: string) + @returns string/boolean Returns the category key if the category is successfully edited, FALSE otherwise +*/ +function editCategory($args) { + global $pages; + global $categories; + global $syslog; + + if (Text::isEmpty($args['key'])) { + Log::set(__FUNCTION__.LOG_SEP.'The category key is empty.', LOG_TYPE_ERROR); + return false; + } + + if (Text::isEmpty($args['name'])) { + Log::set(__FUNCTION__.LOG_SEP.'The category name is empty.', LOG_TYPE_ERROR); + return false; + } + + if (Text::isEmpty($args['friendlyURL'])) { + Log::set(__FUNCTION__.LOG_SEP.'The category friendlyURL is empty.', LOG_TYPE_ERROR); + return false; + } + + $args['oldKey'] = $args['key']; + $args['newKey'] = $args['friendlyURL']; + $finalKey = $categories->edit($args); + + if ($finalKey==false) { + Log::set(__FUNCTION__.LOG_SEP.'The category already exists.', LOG_TYPE_ERROR); + return false; + } + + // Change the category key inside the pages database + if ($args['key']!==$finalKey) { + $pages->changeCategory($args['key'], $finalKey); + } + + $syslog->add(array( + 'dictionaryKey'=>'category-edited', + 'notes'=>$finalKey + )); + + Log::set(__FUNCTION__.LOG_SEP.'Category edited.', LOG_TYPE_INFO); + return $finalKey; +} + +/* Delete a category === Bludit v4 + + @args array Array => (key: string) + @returns boolean Returns TRUE if the category was deleted, FALSE otherwise +*/ +function deleteCategory($args) { + global $categories; + global $syslog; + + if (Text::isEmpty($args['key'])) { + Log::set(__FUNCTION__.LOG_SEP.'The category key is empty.', LOG_TYPE_ERROR); + return false; + } + + if ($categories->remove($args['key'])===false) { + Log::set(__FUNCTION__.LOG_SEP.'Something happened when you tried to delete the category.', LOG_TYPE_ERROR); + return false; + } + + $syslog->add(array( + 'dictionaryKey'=>'category-deleted', + 'notes'=>$args['key'] + )); + + Log::set(__FUNCTION__.LOG_SEP.'Category deleted.', LOG_TYPE_INFO); + return true; +} + /* Create a new user === Bludit v4 This function should check everthing, such as empty username, emtpy password, password lenght, etc @@ -727,56 +814,9 @@ function checkRole($allowRoles, $redirect=true) { -function editCategory($args) { - global $L; - global $pages; - global $categories; - global $syslog; - if (Text::isEmpty($args['name']) || Text::isEmpty($args['newKey']) ) { - Alert::set($L->g('Empty fields')); - return false; - } - $newCategoryKey = $categories->edit($args); - if ($newCategoryKey==false) { - Alert::set($L->g('The category already exists')); - return false; - } - - // Change the category key in the pages database - $pages->changeCategory($args['oldKey'], $newCategoryKey); - - // Add to syslog - $syslog->add(array( - 'dictionaryKey'=>'category-edited', - 'notes'=>$newCategoryKey - )); - - Alert::set($L->g('The changes have been saved')); - return true; -} - -function deleteCategory($args) { - global $L; - global $categories; - global $syslog; - - // Remove the category by key - $categories->remove($args['oldKey']); - - // Remove the category from the pages ? or keep it if the user want to recovery the category ? - - // Add to syslog - $syslog->add(array( - 'dictionaryKey'=>'category-deleted', - 'notes'=>$args['oldKey'] - )); - - Alert::set($L->g('The changes have been saved')); - return true; -} // Returns an array with all the categories // By default, the database of categories is alphanumeric sorted diff --git a/bl-kernel/helpers/bootstrap.class.php b/bl-kernel/helpers/bootstrap.class.php index 5d1f211d..416649c6 100644 --- a/bl-kernel/helpers/bootstrap.class.php +++ b/bl-kernel/helpers/bootstrap.class.php @@ -2,6 +2,15 @@ class Bootstrap { + public static function formInputHidden($args) + { + $name = $args['name']; + $id = isset($args['id'])?$args['id']:$name; + $value = isset($args['value'])?$args['value']:''; + + return '<input type="hidden" id="'.$id.'" name="'.$name.'" value="'.$value.'">'; + } + // Floating Labels // https://getbootstrap.com/docs/5.0/forms/floating-labels/ public static function formFloatingLabels($args) @@ -399,10 +408,7 @@ EOF; - public static function formInputHidden($args) - { - return '<input type="hidden" id="'.$args['name'].'" name="'.$args['name'].'" value="'.$args['value'].'">'; - } + public static function alert($args) { diff --git a/bl-kernel/js/api.js b/bl-kernel/js/api.js index 9ec56e99..33f86cbb 100644 --- a/bl-kernel/js/api.js +++ b/bl-kernel/js/api.js @@ -194,6 +194,56 @@ class API { } } + /* Edit a category + + @args array Arguments can be any of the fields from a category + @returns string The category key + */ + async editCategory(args) { + var url = this.apiURL + "categories/" + args['key']; + var body = Object.assign({}, this.body, args); + try { + var response = await fetch(url, { + credentials: "same-origin", + method: "PUT", + body: JSON.stringify(body), + headers: new Headers({ + "Content-Type": "application/json" + }) + }); + var json = await response.json(); + return json.data.key; + } catch (err) { + console.log(err); + return true; + } + } + + /* Delete a category + + @args array Array => (key: string) + @returns string The category key deleted + */ + async deleteCategory(args) { + var url = this.apiURL + "categories/" + args['key']; + var body = this.body; + try { + var response = await fetch(url, { + credentials: "same-origin", + method: "DELETE", + body: JSON.stringify(body), + headers: new Headers({ + "Content-Type": "application/json" + }) + }); + var json = await response.json(); + return json.data.key; + } catch (err) { + console.log(err); + return true; + } + } + /* Create a new user @args array Arguments can be any of the fields from a user diff --git a/bl-kernel/pages.class.php b/bl-kernel/pages.class.php index 3f05d252..6a67f33e 100644 --- a/bl-kernel/pages.class.php +++ b/bl-kernel/pages.class.php @@ -785,7 +785,12 @@ class Pages extends dbJSON { return $tmp; } - // Change all pages with the old category key to the new category key + /* Change all pages linked to the old category key to the new category key === Bludit v4 + + @oldCategoryKey string The old category key + @newCategoryKey string The new category key + @returns boolean Returns TRUE if the database was saved, FALSE otherwise + */ public function changeCategory($oldCategoryKey, $newCategoryKey) { foreach ($this->db as $key=>$value) { diff --git a/bl-kernel/pagex.class.php b/bl-kernel/pagex.class.php index 9822ad45..3423108a 100644 --- a/bl-kernel/pagex.class.php +++ b/bl-kernel/pagex.class.php @@ -234,9 +234,17 @@ class Page { } } + /* Returns the template for the page === Bludit v4 + + @returns string/boolean Returns the template for the page or FALSE if the page haven't a template assigned + */ public function template() { - return $this->getValue('template'); + $template = $this->getValue('template'); + if (empty($template)) { + return false; + } + return $template; } // Returns the description field diff --git a/bl-languages/en.json b/bl-languages/en.json index 66f7ea4f..86d4d0ec 100644 --- a/bl-languages/en.json +++ b/bl-languages/en.json @@ -225,7 +225,7 @@ "label": "Label", "links": "Links", "this-title-is-almost-always-used-in-the-sidebar-of-the-site": "This title is almost always used in the sidebar of the site.", - "password-must-be-at-least-6-characters-long": "Password must be at least 6 characters long.", + "password-must-be-at-least-6-characters-long": "Password must be at least 6 characters long", "ip-address-has-been-blocked": "IP address has been blocked", "try-again-in-a-few-minutes": "Try again in a few minutes", "content-published-from-scheduler": "Content published from scheduler", @@ -240,7 +240,7 @@ "delete-the-user-and-all-his-content": "Delete the user and all of their content", "user-disabled": "User disabled", "user-password-changed": "User password changed", - "the-password-and-confirmation-password-do-not-match": "The password and confirmation password do not match.", + "the-password-and-confirmation-password-do-not-match": "The password and confirmation password do not match", "scheduled-content": "Scheduled content", "there-are-no-scheduled-content": "There are no scheduled content.", "new-content-created": "New content created", diff --git a/bl-plugins/api/plugin.php b/bl-plugins/api/plugin.php index d5ef801b..272a4f9f 100644 --- a/bl-plugins/api/plugin.php +++ b/bl-plugins/api/plugin.php @@ -189,6 +189,16 @@ class pluginAPI extends Plugin { elseif ( ($method==='POST') && ($parameters[0]==='categories') && empty($parameters[1]) && $writePermissions ) { $data = $this->createCategory($inputs); } + // (PUT) /api/categories/<key> + elseif ( ($method==='PUT') && ($parameters[0]==='categories') && !empty($parameters[1]) && $writePermissions ) { + $inputs['key'] = $parameters[1]; + $data = $this->editCategory($inputs); + } + // (DELETE) /api/categories/<key> + elseif ( ($method==='DELETE') && ($parameters[0]==='categories') && !empty($parameters[1]) && $writePermissions ) { + $inputs['key'] = $parameters[1]; + $data = $this->deleteCategory($inputs); + } // (GET) /api/users elseif ( ($method==='GET') && ($parameters[0]==='users') && empty($parameters[1]) ) { $data = $this->getUsers(); @@ -644,9 +654,11 @@ class pluginAPI extends Plugin { ); } + /* Create a new category === Bludit v4 + Referer to the function createCategory() from functions.php + */ private function createCategory($args) { - // This function is defined on functions.php $key = createCategory($args); if ($key===false) { return array( @@ -662,6 +674,45 @@ class pluginAPI extends Plugin { ); } + /* Edit a category === Bludit v4 + Referer to the function editCategory() from functions.php + */ + private function editCategory($args) + { + $key = editCategory($args); + if ($key===false) { + return array( + 'status'=>'1', + 'message'=>'An error occurred while trying to edit the category.' + ); + } + + return array( + 'status'=>'0', + 'message'=>'Category edited.', + 'data'=>array('key'=>$key) + ); + } + + /* Delete a category === Bludit v4 + Referer to the function deleteCategory() from functions.php + */ + private function deleteCategory($args) + { + if (deleteCategory($args)) { + return array( + 'status'=>'0', + 'message'=>'Category deleted.', + 'data'=>array('key'=>$args['key']) + ); + } + + return array( + 'status'=>'1', + 'message'=>'An error occurred while trying to delete the category.' + ); + } + /* | Returns the user profile | diff --git a/bl-themes/blogx/index.php b/bl-themes/blogx/index.php index 71645914..4cd54b7d 100755 --- a/bl-themes/blogx/index.php +++ b/bl-themes/blogx/index.php @@ -26,7 +26,12 @@ // If the user is watching a particular page/post the variable takes the value "page" // If the user is watching the frontpage the variable takes the value "home" if ($WHERE_AM_I == 'page') { - include(THEME_DIR_PHP.'page.php'); + $template = $page->template(); + if (($template) && file_exists(THEME_DIR_TEMPLATES.$template)) { + include(THEME_DIR_TEMPLATES.$template); + } else { + include(THEME_DIR_PHP.'page.php'); + } } else { include(THEME_DIR_PHP.'home.php'); }