diff --git a/bl-kernel/admin/controllers/new-content.php b/bl-kernel/admin/controllers/new-content.php index 213e2e07..e1db2d8c 100644 --- a/bl-kernel/admin/controllers/new-content.php +++ b/bl-kernel/admin/controllers/new-content.php @@ -14,26 +14,5 @@ checkRole(array('admin', 'editor', 'author')); // Main // ============================================================================ -// UUID of the page is need it for autosave and media manager -$uuid = $pages->generateUUID(); - -// Images prefix directory -define('PAGE_IMAGES_KEY', $uuid); - -// Images and thubmnails directories -if (IMAGE_RESTRICT) { - define('PAGE_IMAGES_DIRECTORY', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : HTML_PATH_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/')); - define('PAGE_IMAGES_URL', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : DOMAIN_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/')); - define('PAGE_THUMBNAILS_DIRECTORY', PATH_UPLOADS_PAGES.PAGE_IMAGES_KEY.DS.'thumbnails'.DS); - define('PAGE_THUMBNAILS_HTML', HTML_PATH_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/thumbnails/'); - define('PAGE_THUMBNAILS_URL', DOMAIN_UPLOADS_PAGES.PAGE_IMAGES_KEY.'/thumbnails/'); -} else { - define('PAGE_IMAGES_DIRECTORY', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : HTML_PATH_UPLOADS)); - define('PAGE_IMAGES_URL', (IMAGE_RELATIVE_TO_ABSOLUTE? '' : DOMAIN_UPLOADS)); - define('PAGE_THUMBNAILS_DIRECTORY', PATH_UPLOADS_THUMBNAILS); - define('PAGE_THUMBNAILS_HTML', HTML_PATH_UPLOADS_THUMBNAILS); - define('PAGE_THUMBNAILS_URL', DOMAIN_UPLOADS_THUMBNAILS); -} - // View HTML $layout['title'] = $L->g('New content') . ' - ' . $layout['title']; diff --git a/bl-kernel/admin/themes/booty/css/bludit-bootstrap.css b/bl-kernel/admin/themes/booty/css/bludit-bootstrap.css index faa2e6ab..bab2138b 100644 --- a/bl-kernel/admin/themes/booty/css/bludit-bootstrap.css +++ b/bl-kernel/admin/themes/booty/css/bludit-bootstrap.css @@ -5,7 +5,13 @@ a { /* Remove Focus glow */ .btn:focus, -.form-control:focus { +.form-control:focus, +.form-select:focus { outline: none; box-shadow: none; } + +/* Icons */ +.bi { + margin-right: .5rem!important; +} \ No newline at end of file diff --git a/bl-kernel/admin/themes/booty/html/alert.php b/bl-kernel/admin/themes/booty/html/alert.old.php similarity index 100% rename from bl-kernel/admin/themes/booty/html/alert.php rename to bl-kernel/admin/themes/booty/html/alert.old.php diff --git a/bl-kernel/admin/themes/booty/html/alerts.php b/bl-kernel/admin/themes/booty/html/alerts.php new file mode 100644 index 00000000..4334e759 --- /dev/null +++ b/bl-kernel/admin/themes/booty/html/alerts.php @@ -0,0 +1,19 @@ +<div aria-live="polite" aria-atomic="true" class="position-relative"> + <div class="toast-container position-absolute top-0 end-0 p-3"> + <div id="alert" class="toast d-flex align-items-center text-white bg-primary 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> + </div> +</div> + +<script> +function showAlert(text) { + $('#alert').children('.toast-body').html(text); + $('#alert').toast('show'); +} + +function hideAlert(text) { + $('#alert').toast('hide'); +} +</script> \ No newline at end of file diff --git a/bl-kernel/admin/themes/booty/html/file-manager.php b/bl-kernel/admin/themes/booty/html/file-manager.php new file mode 100644 index 00000000..bbc11259 --- /dev/null +++ b/bl-kernel/admin/themes/booty/html/file-manager.php @@ -0,0 +1,156 @@ +<div class="modal" id="modal-fileManager" tabindex="-1"> + <div class="modal-dialog modal-lg"> + <div class="modal-content"> + <div class="modal-body"> + <div class="container-fluid"> + <div class="row"> + <div class="col"> + + <div class="d-flex align-items-center mb-2"> + <h3 class="me-auto m-0 p-0"><i class="bi bi-image"></i><?php $L->p('File Manager'); ?></h3> + <label class="btn btn-primary"><i class="bi bi-upload"></i><?php $L->p('Upload file'); ?><input type="file" id="filesToUpload" name="filesToUpload[]" multiple hidden></label> + <div class="progress d-none"> + <div class="progress-bar" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div> + </div> + </div> + + <table class="table"> + <thead> + <tr> + <th scope="col">Preview</th> + <th scope="col">Filename</th> + <th scope="col">Type</th> + <th scope="col">Size</th> + <th scope="col"></th> + </tr> + </thead> + <tbody id="fmFiles"> + <tr> + <td class="align-middle"> + <img style="width: 32px" src="<?php echo HTML_PATH_CORE_IMG ?>default.svg" /> + </td> + <td class="align-middle">photo.jpg</td> + <td class="align-middle">image/jpeg</td> + <td class="align-middle">300Kb</td> + <td class="align-middle"> + <i class="bi bi-trash"></i><span><?php $L->p('Delete') ?></span> + </td> + </tr> + </tbody> + </table> + + </div> + </div> + </div> + </div> + </div> + </div> +</div> + +<script> + // Open File Manager modal + function fmOpen() { + $('#modal-fileManager').modal('show'); + } + + // Get files for the current page and show them + function fmGetFiles() { + logs('File Manager. Get files for page: ' + _pageKey); + api.getPageFiles({ + 'pageKey': _pageKey + }).then(function(files) { + fmDisplayFiles(files); + }); + } + + // Show the files in the table + function fmDisplayFiles(files) { + $('#fmFiles').empty(); + + if (files.length == 0) { + logs('File Manager. File list empty.'); + return false; + } + + $.each(files, function(key, file) { + var row = '<tr>' + + ' <td class="align-middle">' + + ' <img style="width: 32px" src="<?php echo HTML_PATH_CORE_IMG ?>default.svg" />' + + ' </td>' + + ' <td class="align-middle">' + file.filename + '</td>' + + ' <td class="align-middle">' + file.mime + '</td>' + + ' <td class="align-middle">' + formatBytes(file.size) + '</td>' + + ' <td class="align-middle">' + + ' <i class="bi bi-trash"></i><span><?php $L->p('Delete') ?></span>' + + ' </td>' + + ' </tr>'; + + $('#fmFiles').append(row); + }); + + return true; + } + + // Upload a file for the current page + function fmUploadFile(file) { + logs('File Manager. Uploading file.'); + + // Check file type/extension + const validImageTypes = ['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml']; + if (!validImageTypes.includes(file.type)) { + logs("File Manager. File type is not supported."); + showAlert("<?php echo $L->g('File type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_EXTENSION']) ?>"); + return false; + } + + // Check file size and compare with PHP upload_max_filesize + if (file.size > UPLOAD_MAX_FILESIZE) { + logs("File Manager. File size to big for PHP configuration."); + showAlert("<?php echo $L->g('Maximum load file size allowed:') . ' ' . ini_get('upload_max_filesize') ?>"); + return false; + } + + // Data to send via AJAX + var formData = new FormData(); + formData.append("file", file); + formData.append("token", api.body.token); + formData.append("authentication", api.body.authentication); + + $.ajax({ + url: api.apiURL + 'files/' + _pageKey, + type: "POST", + data: formData, + cache: false, + contentType: false, + processData: false, + xhr: function() { + var xhr = $.ajaxSettings.xhr(); + if (xhr.upload) { + xhr.upload.addEventListener("progress", function(e) { + if (e.lengthComputable) { + var percentComplete = (e.loaded / e.total) * 100; + logs("File Manager. Uploading file, percent complete: " + percentComplete + "%"); + } + }, false); + } + return xhr; + } + }).done(function(data) { + logs("File Manager. File uploaded.") + logs(data); + fmGetFiles(); + }); + } + + $(document).ready(function() { + + // Input file change event + $("#filesToUpload").on("change", function(e) { + var filesToUpload = $("#filesToUpload")[0].files; + for (var i = 0; i < filesToUpload.length; i++) { + fmUploadFile(filesToUpload[i]); + } + }); + + }); +</script> \ No newline at end of file diff --git a/bl-kernel/admin/themes/booty/html/media.php b/bl-kernel/admin/themes/booty/html/media.old.php similarity index 100% rename from bl-kernel/admin/themes/booty/html/media.php rename to bl-kernel/admin/themes/booty/html/media.old.php diff --git a/bl-kernel/admin/themes/booty/index.php b/bl-kernel/admin/themes/booty/index.php index 346df892..ec058dab 100644 --- a/bl-kernel/admin/themes/booty/index.php +++ b/bl-kernel/admin/themes/booty/index.php @@ -1,5 +1,6 @@ <!DOCTYPE html> <html class="h-100"> + <head> <title><?php echo $layout['title'] ?> @@ -12,34 +13,34 @@ @@ -54,11 +55,12 @@ - - -
+ + + +
@@ -72,19 +74,19 @@
- + -
+
- @@ -106,4 +108,5 @@ + \ No newline at end of file diff --git a/bl-kernel/admin/views/login.php b/bl-kernel/admin/views/login.php index 2fa1342f..b0e271ff 100644 --- a/bl-kernel/admin/views/login.php +++ b/bl-kernel/admin/views/login.php @@ -1,6 +1,6 @@ '.$site->title().''; +echo '

'.$site->title().'

'; echo Bootstrap::formOpen(array()); @@ -42,4 +42,4 @@ echo ''; echo '

Powered by Bludit

' -?> +?> \ No newline at end of file diff --git a/bl-kernel/admin/views/new-content.php b/bl-kernel/admin/views/new-content.php index e4f93c75..34d150e5 100644 --- a/bl-kernel/admin/views/new-content.php +++ b/bl-kernel/admin/views/new-content.php @@ -1,253 +1,256 @@ + + + + @@ -412,198 +417,169 @@ $(document).ready(function() {
- - - - - - -
-
-
- - -
-
- -
- -
- - - p('Draft') ?> -
-
- - - -
- -
- - - - - - -
- -
- - -
p('Cover Image') ?>
-
- Cover image preview -
- - - -
p('Images') ?>
- -
- Placeholder32x32 -
-
- photo1.jpg -
-
-
- -
- Placeholder32x32 -
-
- photo2.jpg -
-
-
- - - - - -
-
Category
- -
- - - -
Tags
- - - + + -
-
+
+
+
+ + +
+
+ + + p('Draft') ?> +
+
+ +
+
+ + + +
+ +
+ + + + + + +
+ +
+ + +
p('Cover Image') ?>
+
+ Cover image preview +
+ + + +
Category
+ 'category', + 'name' => 'category', + 'options' => array_merge(array('' => $L->g('Uncategorized')), $categories->getKeyNameArray()) + )); + ?> + + + +
Tags
+ + + + + +
p('Images') ?>
+
+
+ + photo1.jpg +
+
+ + test.txt +
+
+ + test.txt +
+
+ + +
+
+ }); + \ No newline at end of file diff --git a/bl-kernel/functions.php b/bl-kernel/functions.php index bf136a57..e81d936f 100644 --- a/bl-kernel/functions.php +++ b/bl-kernel/functions.php @@ -304,25 +304,14 @@ function execPluginsByHook($hook, $args = array()) { } } -/* - Create a new page +/* Create a new page - The array $args support all the keys from variable $dbFields of the class pages.class.php - If you don't pass all the keys, the default values are used, the default values are from $dbFields in the class pages.class.php + @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. + @returns string/boolean Returns the page key if the page is successfully created, FALSE otherwise */ function createPage($args) { global $pages; global $syslog; - global $L; - - // Check if the autosave page exists for this new page and delete it - if (isset($args['uuid'])) { - $autosaveKey = $pages->getByUUID('autosave-'.$args['uuid']); - if (!empty($autosaveKey)) { - Log::set('Function createPage()'.LOG_SEP.'Autosave deleted for '.$args['title'], LOG_TYPE_INFO); - deletePage($autosaveKey); - } - } // The user is always the one logged $args['username'] = Session::get('username'); @@ -334,8 +323,9 @@ function createPage($args) { $key = $pages->add($args); if ($key) { // Call the plugins after page created - Theme::plugins('afterPageCreate', array($key)); + execPluginsByHook('afterPageCreate', array($key)); + // Reindex categories and tags reindexCategories(); reindexTags(); @@ -345,47 +335,43 @@ function createPage($args) { 'notes'=>(empty($args['title'])?$key:$args['title']) )); + Log::set('Function createPage()'.LOG_SEP.'Page created successfully.', LOG_TYPE_INFO); return $key; } - Log::set('Function createNewPage()'.LOG_SEP.'Error occurred when trying to create the page', LOG_TYPE_ERROR); - Log::set('Function createNewPage()'.LOG_SEP.'Cleaning database...', LOG_TYPE_ERROR); + Log::set('Function createPage()'.LOG_SEP.'Something happened when you tried to create the page.', LOG_TYPE_ERROR); deletePage($key); - Log::set('Function createNewPage()'.LOG_SEP.'Cleaning finished...', LOG_TYPE_ERROR); - return false; } +/* Edit a page + + @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. + @args['key'] string The key of the page to be edited + @returns string/boolean Returns the page key if the page is successfully edited, FALSE otherwise +*/ function editPage($args) { global $pages; global $syslog; - // Check if the autosave/preview page exists for this new page and delete it - if (isset($args['uuid'])) { - $autosaveKey = $pages->getByUUID('autosave-'.$args['uuid']); - if ($autosaveKey) { - Log::set('Function editPage()'.LOG_SEP.'Autosave/Preview deleted for '.$autosaveKey, LOG_TYPE_INFO); - deletePage($autosaveKey); - } - } - // Check if the key is not empty if (empty($args['key'])) { - Log::set('Function editPage()'.LOG_SEP.'Empty key.', LOG_TYPE_ERROR); + Log::set('Function editPage()'.LOG_SEP.'Empty page key.', LOG_TYPE_ERROR); return false; } // Check if the page key exist if (!$pages->exists($args['key'])) { - Log::set('Function editPage()'.LOG_SEP.'Page key does not exist, '.$args['key'], LOG_TYPE_ERROR); + Log::set('Function editPage()'.LOG_SEP.'Page key doesn\'t exist: '.$args['key'], LOG_TYPE_ERROR); return false; } $key = $pages->edit($args); if ($key) { // Call the plugins after page modified - Theme::plugins('afterPageModify', array($key)); + execPluginsByHook('afterPageModify', array($key)); + // Reindex categories and tags reindexCategories(); reindexTags(); @@ -395,21 +381,28 @@ function editPage($args) { 'notes'=>empty($args['title'])?$key:$args['title'] )); + Log::set('Function editPage()'.LOG_SEP.'Page edited successfully.', LOG_TYPE_INFO); return $key; } - Log::set('Function editPage()'.LOG_SEP.'Something happen when try to edit the page.', LOG_TYPE_ERROR); + Log::set('Function editPage()'.LOG_SEP.'Something happened when you tried to edit the page.', LOG_TYPE_ERROR); return false; } +/* Delete a page + + @key string The key of the page to be deleted + @returns string/boolean Returns TRUE if the page is successfully deleted, FALSE otherwise +*/ function deletePage($key) { global $pages; global $syslog; if ($pages->delete($key)) { // Call the plugins after page deleted - Theme::plugins('afterPageDelete', array($key)); + execPluginsByHook('afterPageDelete', array($key)); + // Reindex categories and tags reindexCategories(); reindexTags(); @@ -419,9 +412,11 @@ function deletePage($key) { 'notes'=>$key )); + Log::set('Function deletePage()'.LOG_SEP.'Page deleted successfully.', LOG_TYPE_INFO); return true; } + Log::set('Function deletePage()'.LOG_SEP.'Something happened when you tried to delete the page.', LOG_TYPE_ERROR); return false; } diff --git a/bl-kernel/helpers/bootstrap.class.php b/bl-kernel/helpers/bootstrap.class.php index d46be4e9..e7e0106f 100644 --- a/bl-kernel/helpers/bootstrap.class.php +++ b/bl-kernel/helpers/bootstrap.class.php @@ -8,11 +8,10 @@ class Bootstrap { { $name = $args['name']; $id = isset($args['id'])?$args['id']:$name; - $disabled = empty($args['disabled'])?'':'disabled'; - $readonly = empty($args['readonly'])?'':'readonly'; - $placeholder = isset($args['placeholder'])?$args['placeholder']:''; $value = isset($args['value'])?$args['value']:''; + $type = isset($args['type'])?$args['type']:'text'; + $placeholder = isset($args['placeholder'])?$args['placeholder']:''; $label = isset($args['label'])?$args['label']:$placeholder; $class = 'form-control'; @@ -22,12 +21,36 @@ class Bootstrap { return << - +
EOF; } + public static function formSelect($args) + { + $name = $args['name']; + $id = isset($args['id'])?$args['id']:$name; + + $class = 'form-select'; + if (isset($args['class'])) { + $class = $class.' '.$args['class']; + } + + $html = '
'; + if (isset($args['label'])) { + $html .= ''; + } + $html .= ''; + $html .= '
'; + + return $html; + } + public static function formInputText($args) { $name = $args['name']; @@ -64,7 +87,7 @@ return <<db[$key] ); } - // Create a new page - // This function returns the key of the new page + /* Create a new page + + @args array The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used. + @returns string/boolean Returns the page key if the page is successfully created, FALSE otherwise + */ public function add($args) { $row = array(); @@ -134,20 +137,26 @@ class Pages extends dbJSON { // Create the directory if (Filesystem::mkdir(PATH_PAGES.$key, true) === false) { - Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to create the directory ['.PATH_PAGES.$key.']',LOG_TYPE_ERROR); + Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to create the directory: '.PATH_PAGES.$key, LOG_TYPE_ERROR); + return false; + } + + // Create the upload directory for the page + if (Filesystem::mkdir(PATH_UPLOADS_PAGES.$key, true) === false) { + Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to create the directory: '.PATH_UPLOADS_PAGES.$key, LOG_TYPE_ERROR); return false; } // Create the index.txt and save the file if (file_put_contents(PATH_PAGES.$key.DS.FILENAME, $contentRaw) === false) { - Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to create the content in the file ['.FILENAME.']',LOG_TYPE_ERROR); + Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to create the file: '.FILENAME, LOG_TYPE_ERROR); return false; } // Checksum MD5 $row['md5file'] = md5_file(PATH_PAGES.$key.DS.FILENAME); - // Insert in database + // Insert into database $this->db[$key] = $row; // Sort database @@ -156,18 +165,14 @@ class Pages extends dbJSON { // Save database $this->save(); - // Create symlink for images directory - if (Filesystem::mkdir(PATH_UPLOADS_PAGES.$row['uuid'])) { - symlink(PATH_UPLOADS_PAGES.$row['uuid'], PATH_UPLOADS_PAGES.$key); - } - return $key; } - // Edit a page - // This function do not edit the current row from the table - - // - instead of that the function creates a new row and is completed by the current - - // - values of the page and then the old row is deleted and the new row is inserted. + /* Edit a page + + @args array The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used. + @returns string/boolean Returns the page key if the page is successfully edited, FALSE otherwise + */ public function edit($args) { // This is the new row for the table and is going to replace the old row @@ -248,13 +253,14 @@ class Pages extends dbJSON { // Move the directory from old key to new key only if the keys are different if ($newKey!==$key) { if (Filesystem::mv(PATH_PAGES.$key, PATH_PAGES.$newKey) === false) { - Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to move the directory to '.PATH_PAGES.$newKey); + Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to move the directory '.PATH_PAGES.$newKey); return false; } - // Regenerate the symlink to a proper directory - unlink(PATH_UPLOADS_PAGES.$key); - symlink(PATH_UPLOADS_PAGES.$row['uuid'], PATH_UPLOADS_PAGES.$newKey); + if (Filesystem::mv(PATH_UPLOADS_PAGES.$key, PATH_UPLOADS_PAGES.$newKey) === false) { + Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to move the directory '.PATH_UPLOADS_PAGES.$newKey); + return false; + } } // If the content was passed via arguments replace the content diff --git a/bl-plugins/backup/plugin.php b/bl-plugins/backup/plugin.php index 4c18128d..a73795ce 100644 --- a/bl-plugins/backup/plugin.php +++ b/bl-plugins/backup/plugin.php @@ -142,7 +142,7 @@ class pluginBackup extends Plugin { } $html .= '
'; - $html .= '

'.$name.($count > 0? " ($count)": "").'

'; + $html .= '

'.$name.($count > 0? " ($count)": "").'

'; // Allow download if a zip file if ($this->zip) { $html .= ' '.$L->get('download').''; diff --git a/install.php b/install.php index 88657eee..ab52011a 100644 --- a/install.php +++ b/install.php @@ -597,7 +597,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') {
-

get('Bludit Installer') ?>

+

get('Bludit Installer') ?>