Compare commits

..

37 commits

Author SHA1 Message Date
Diego Najar
84baa2c16b change in metadata for Bludit v4.0, plugin for popeye theme updated, refactor 2021-06-02 22:48:30 +02:00
Diego Najar
1c49bef304 Darkmode for Admin panel and Website, Bootstrap 5.0.1, refactor for Bludit v4 2021-05-17 20:04:59 +02:00
Diego Najar
fca4deb8c9 Add Google Fonts and Dark Mode 2021-05-11 17:56:30 +02:00
Diego Najar
2de6b6a3b1 PopEye theme updates 2021-04-20 23:21:44 +02:00
Diego Najar
ee0adae2d9 Merge branch 'v4.0' of github.com:bludit/bludit into v4.0 2021-04-20 17:32:52 +02:00
Diego Najar
a69aa3edb9 Default logo 2021-04-20 17:32:41 +02:00
dignajar
6688d0bd49 PopEye theme improvments 2021-04-18 17:50:04 +02:00
dignajar
930dd9a01b Enable API when the user login, starting new default theme for Bludit v4 Popeye 2021-04-13 20:28:51 +02:00
Diego Najar
1c5992477f refactor to remove Theme helper 2021-03-19 16:48:04 -03:00
Diego Najar
ae1c99c813 refactor and delete old files 2021-03-19 16:42:17 -03:00
Diego Najar
b455bbb055 doc for bludit v4 2021-03-19 16:06:17 -03:00
Diego Najar
93077d2647 add discord for social media 2021-03-19 16:01:38 -03:00
Diego Najar
adb84d792d plugin position for dashboard, new plugins for welcome message and visits 2021-03-19 15:54:09 -03:00
Diego Najar
fc12ebadc8 Grettings message for Dashboard 2021-03-09 12:29:13 -03:00
Diego Najar
7358a7e0e4 change function name 2021-03-09 12:28:52 -03:00
Diego Najar
a55ab5d2ec Refactor for Site logo 2021-03-09 11:55:08 -03:00
Diego Najar
3570734110 remove maps 2021-03-09 11:54:22 -03:00
Diego Najar
55a7a62780 Update EasyMDE for Bludit v4 2021-03-09 11:53:36 -03:00
Diego Najar
f11eed0a96 TinyMCE 5.7 and plugin updated 2021-03-04 14:50:28 -03:00
Diego Najar
5b64d3b2fa Move vendors to a proper folder, update Bootstrap, Icons and jQuery 2021-03-04 12:27:02 -03:00
Diego Najar
9fb07d918a Minor changes in visits stats and fix notifications in dahsboard 2021-03-04 12:00:54 -03:00
Diego Najar
3c97a31b1b Delete Simple Stats and create Visits stats 2021-03-03 13:31:32 -03:00
dignajar
231a500a52 add some documentation to the readme, now all plugins print the description in the settings form its possible disable as well, clean up css, and refactor Categories plugin 2021-02-07 22:03:53 +01:00
dignajar
f2b8955e96 Add custom template for JS for the views 2021-02-07 18:22:20 +01:00
dignajar
0f71046b92 Deactivate plugin via API 2021-02-07 18:13:25 +01:00
dignajar
cd0446e080 Settings trough API, change user password via API, refactor code 2021-02-07 17:19:24 +01:00
dignajar
71f1742c45 Change user password, Disable user, improve comments on functions 2021-01-26 22:31:12 +01:00
dignajar
3b37cb2905 Refactor main clasess, add new library for manage images 2021-01-23 22:19:47 +01:00
dignajar
993a4f92d6 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 2021-01-16 13:03:16 +01:00
dignajar
38bd6dd551 Create user via API, create category via API, Bootstrap icons v1.3, improve in creation content 2021-01-12 21:46:42 +01:00
dignajar
ff2a51fae8 New approach when the page is created, remove UUID, remove symlinks for upload images, modal for filemanager, and more 2021-01-01 23:13:01 +01:00
dignajar
39de732f3b port to Bootstrap v5 modals and change icons 2020-12-29 18:53:06 +01:00
dignajar
1e143270aa missing name field for floating labels 2020-12-29 14:57:20 +01:00
dignajar
70cefda593 Added floating labels and changed in login form 2020-12-29 14:55:55 +01:00
dignajar
5469ce51b1 bootstrap v5, bootstrap icons, cleaning css, cleaning classes 2020-12-29 14:39:47 +01:00
dignajar
e84df311c2 a few updates for the admin panel 2020-11-30 22:00:54 +01:00
dignajar
226750af09 init branch for Bludit v4 2020-11-01 11:55:34 +01:00
369 changed files with 14506 additions and 21079 deletions

View file

@ -1,5 +1,3 @@
Please follow the next steps. The issue will be closed if the following steps are not completed. Thank you. (You can remove this line).
### Describe your problem
Complete here.
@ -10,9 +8,9 @@ Complete here.
Complete here.
### PHP version
If you do not know remove this line.
If you do not know delete this line.
### PHP logs
If you do not know remove this line.
If you do not know delete this line.
The default settings of the PHP Error Log file varies from OS to OS. The location of the error log file itself can be set manually in the php.ini file. On a Windows server, in IIS, it may be something like `error_log = C:\log_files\php_errors.log` in Linux it may be a value of `/var/log/php_errors.log`.

1
.gitignore vendored
View file

@ -1,7 +1,6 @@
.DS_Store
dbgenerator.php
bl-content/*
!bl-content/.keep
bl-content-migrator
bl-plugins/timemachine
bl-plugins/timemachine-x

View file

@ -1,7 +0,0 @@
{
"semi": true,
"singleQuote": true,
"useTabs": false,
"tabWidth": 2,
"printWidth": 100
}

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015-2023 Diego Najar
Copyright (c) 2015-2021 Diego Najar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -1,52 +1,36 @@
# [Bludit](https://www.bludit.com/)
[Bludit](https://www.bludit.com/)
================================
Bludit the Simple, Fast, and Flexible CMS.
Dear developers
-------
With Bludit, you can build your own website or blog in just seconds. Its completely free, open-source, and easy to use. Bludit stores content in JSON format, eliminating the need for database installation or configuration. All you need is a web server with PHP support.
## Frameworks and libraries included in Bludit v4
Bludit will include the following frameworks, please use them with they native functions.
As a Flat-File CMS, Bludit offers unparalleled flexibility and speed. Plus, with support for both Markdown and HTML code, creating and managing content has never been easier.
Frontend:
- Bootstrap v5.
- Boostrap icons.
- jQuery, you can use vanilla Javascript but for events in the views please use jQuery.
## Resources
Backend:
- `bl-kernel/functions.php` provides the global function for Bludit; These functions provide connectivity between different objects and databases; These functions should provide different checks and logic before add/edit/delete into the databases.
- PHP SimpleImage for processing images: https://github.com/claviska/SimpleImage
- [Plugins](https://plugins.bludit.com)
- [Themes](https://themes.bludit.com)
- [Documentation](https://docs.bludit.com)
- News and announcement on [Twitter](https://twitter.com/bludit), [Facebook](https://www.facebook.com/bluditcms), and [Reddit](https://www.reddit.com/r/bludit/)
- Talk & Chat on [Discord](https://discord.gg/CFaXEdZWds)
- Help and Support on [Forum](https://forum.bludit.org)
- Bugs reports on [Github Issues](https://github.com/bludit/bludit/issues)
## Comments for functions and methods
Please add the following structure commenting what it does the function, also add the stamp `=== Bludit v4` so I know what is new.
```
/* Delete a page === Bludit v4
## Requirements
@key string Array => (key: string)
@return string/bool Returns the page key on successful delete, FALSE otherwise
*/
function deletePage($args) {
...
}
```
- Webserver with PHP support.
- PHP v5.6 or higher version.
- PHP [mbstring](http://php.net/manual/en/book.mbstring.php) module for full UTF-8 support.
- PHP [gd](http://php.net/manual/en/book.image.php) module for image processing.
- PHP [dom](http://php.net/manual/en/book.dom.php) module for DOM manipulation.
- PHP [json](http://php.net/manual/en/book.json.php) module for JSON manipulation.
Documentation for Bludit v4
-------
There is a new branch for the Documentation in english for Bludit v4.
## Installation
1. Download the latest version from the official page: [Bludit.com](https://www.bludit.com)
2. Extract the zip file into a directory, such as `bludit`.
3. Upload the `bludit` directory to your web server or hosting.
4. Visit your domain (e.g., https://example.com/bludit/).
5. Follow the Bludit Installer to set up your website.
## Quick installation for testing
You can use PHP Built-in web server (`php -S localhost:8000`) or [Docker image](https://hub.docker.com/r/bludit/docker/)
## Support Bludit
Bludit is open-source and free to use, but if you find the project useful and would like to support its development, you can contribute on [Patreon](https://www.patreon.com/bePatron?c=921115&rid=2458860). As a token of our appreciation, supporters will receive Bludit PRO.
If you prefer, you can also make a one-time donation to buy us a coffee or beer. Every contribution helps us continue to improve Bludit and provide the best possible experience for our users.
- [PayPal](https://www.paypal.me/bludit/10)
- BTC (Network BTC): bc1qtets5pdj73uyysjpegfh2gar4pfywra4rglcph
- ETH (Network ETH): 0x0d7D58D848aA5f175D75Ce4bC746bAC107f331b7
## License
Bludit is open source software licensed under the [MIT license](https://tldrlegal.com/license/mit-license).
https://github.com/bludit/documentation-english/tree/v4.0

View file

View file

@ -61,7 +61,10 @@ class dbJSON {
return $this->dbFields[$field];
}
// Save the JSON file
/* Save the JSON file
@return boolean Returns TRUE if the file was saved successfully, FALSE otherwise
*/
public function save()
{
$data = '';
@ -79,7 +82,7 @@ class dbJSON {
if (file_put_contents($this->file, $data, LOCK_EX)) {
return true;
} else {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to save the database file.', LOG_TYPE_ERROR);
Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to save the database.', LOG_TYPE_ERROR);
return false;
}
}

View file

@ -75,22 +75,35 @@ class dbList extends dbJSON
return $key;
}
// Add a new item to the dblist
// $args => 'name', 'template', 'description', list'
/* Add a new item to the dblist === Bludit v4
@args array The array $args supports the following keys 'name', 'template', 'description', list'
@return string/boolean Returns the item's key if the item was successfully added, FALSE otherwise
*/
public function add($args)
{
$key = $this->generateKey($args['name']);
$this->db[$key]['name'] = Sanitize::removeTags($args['name']);
$this->db[$key]['template'] = isset($args['template'])?Sanitize::removeTags($args['template']):'';
$this->db[$key]['description'] = isset($args['description'])?Sanitize::removeTags($args['description']):'';
$this->db[$key]['list'] = isset($args['list'])?$args['list']:array();
if ($this->exists($key)) {
Log::set(__METHOD__.LOG_SEP.'The item already exists. Key: '.$key);
return false;
}
$this->db[$key]['name'] = Sanitize::removeTags($args['name']);
$this->db[$key]['template'] = isset($args['template'])?Sanitize::removeTags($args['template']):'';
$this->db[$key]['description'] = isset($args['description'])?Sanitize::removeTags($args['description']):'';
$this->db[$key]['list'] = isset($args['list'])?$args['list']:array();
$this->sortAlphanumeric();
$this->save();
return $key;
}
/* Delete an item from the dblist === Bludit v4
@key string Key of the item to be deleted
@return boolean Returns TRUE if the database was successfully saved, FALSE otherwise
*/
public function remove($key)
{
if (!isset($this->db[$key])) {
@ -176,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
@return 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;
}
}

View file

@ -1,7 +1,6 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
class Plugin
{
class Plugin {
// (string) directory name, just the name
// Ex: sitemap
@ -56,10 +55,10 @@ class Plugin
// Init empty database with default values
$this->db = $this->dbFields;
$this->filenameDb = PATH_PLUGINS_DATABASES . $this->directoryName . DS . 'db.php';
$this->filenameDb = PATH_PLUGINS_DATABASES.$this->directoryName.DS.'db.php';
// --- Metadata ---
$this->filenameMetadata = PATH_PLUGINS . $this->directoryName() . DS . 'metadata.json';
$this->filenameMetadata = PATH_PLUGINS.$this->directoryName().DS.'metadata.json';
$metadataString = file_get_contents($this->filenameMetadata);
$this->metadata = json_decode($metadataString, true);
@ -80,44 +79,44 @@ class Plugin
public function includeCSS($filename)
{
return '<link rel="stylesheet" type="text/css" href="' . $this->domainPath() . 'css/' . $filename . '?version=' . BLUDIT_VERSION . '">' . PHP_EOL;
return '<link rel="stylesheet" type="text/css" href="'.$this->domainPath().'css/'.$filename.'?version='.BLUDIT_VERSION.'">'.PHP_EOL;
}
public function includeJS($filename)
{
return '<script charset="utf-8" src="' . $this->domainPath() . 'js/' . $filename . '?version=' . BLUDIT_VERSION . '"></script>' . PHP_EOL;
return '<script charset="utf-8" src="'.$this->domainPath().'js/'.$filename.'?version='.BLUDIT_VERSION.'"></script>'.PHP_EOL;
}
// Returns absolute URL and path of the plugin directory
// This function helps to include CSS or Javascript files with absolute URL
public function domainPath()
{
return DOMAIN_PLUGINS . $this->directoryName . '/';
return DOMAIN_PLUGINS.$this->directoryName.'/';
}
// Returns relative path of the plugin directory
// This function helps to include CSS or Javascript files with relative URL
public function htmlPath()
{
return HTML_PATH_PLUGINS . $this->directoryName . '/';
return HTML_PATH_PLUGINS.$this->directoryName.'/';
}
// Returns absolute path of the plugin directory
// This function helps to include PHP libraries or some file at server level
public function phpPath()
{
return PATH_PLUGINS . $this->directoryName . DS;
return PATH_PLUGINS.$this->directoryName.DS;
}
public function phpPathDB()
{
return PATH_PLUGINS_DATABASES . $this->directoryName . DS;
return PATH_PLUGINS_DATABASES.$this->directoryName.DS;
}
// Returns the value of the key from the metadata of the plugin, FALSE if the key doesn't exist
public function getMetadata($key)
{
if (isset($this->metadata[$key])) {
if(isset($this->metadata[$key])) {
return $this->metadata[$key];
}
@ -134,7 +133,7 @@ class Plugin
// Returns the value of the field from the database
// (string) $field
// (boolean) $html, TRUE returns the value sanitized, FALSE unsanitized
public function getValue($field, $html = true)
public function getValue($field, $html=true)
{
if (isset($this->db[$field])) {
if ($html) {
@ -171,6 +170,11 @@ class Plugin
return $this->getMetadata('email');
}
public function type()
{
return $this->getMetadata('type');
}
public function website()
{
return $this->getMetadata('website');
@ -205,9 +209,9 @@ class Plugin
{
$bluditRoot = explode('.', BLUDIT_VERSION);
$compatible = explode(',', $this->getMetadata('compatible'));
foreach ($compatible as $version) {
foreach( $compatible as $version ) {
$root = explode('.', $version);
if ($root[0] == $bluditRoot[0] && $root[1] == $bluditRoot[1]) {
if( $root[0]==$bluditRoot[0] && $root[1]==$bluditRoot[1] ) {
return true;
}
}
@ -220,7 +224,7 @@ class Plugin
}
// Return TRUE if the installation success, otherwise FALSE.
public function install($position = 1)
public function install($position=1)
{
if ($this->installed()) {
return false;
@ -231,11 +235,11 @@ class Plugin
mkdir($workspace, DIR_PERMISSIONS, true);
// Create plugin directory for the database
mkdir(PATH_PLUGINS_DATABASES . $this->directoryName, DIR_PERMISSIONS, true);
mkdir(PATH_PLUGINS_DATABASES.$this->directoryName, DIR_PERMISSIONS, true);
$this->dbFields['position'] = $position;
// Sanitize default values to store in the file
foreach ($this->dbFields as $key => $value) {
foreach ($this->dbFields as $key=>$value) {
$value = Sanitize::html($value);
settype($value, gettype($this->dbFields[$key]));
$this->db[$key] = $value;
@ -248,7 +252,7 @@ class Plugin
public function uninstall()
{
// Delete database
$path = PATH_PLUGINS_DATABASES . $this->directoryName;
$path = PATH_PLUGINS_DATABASES.$this->directoryName;
Filesystem::deleteRecursive($path);
// Delete workspace
@ -267,7 +271,7 @@ class Plugin
public function workspace()
{
return PATH_WORKSPACES . $this->directoryName . DS;
return PATH_WORKSPACES.$this->directoryName.DS;
}
public function init()
@ -285,14 +289,11 @@ class Plugin
public function post()
{
$args = $_POST;
foreach ($this->dbFields as $field => $value) {
foreach ($this->dbFields as $field=>$value) {
if (isset($args[$field])) {
$finalValue = Sanitize::html($args[$field]);
if ($finalValue === 'false') {
$finalValue = false;
} elseif ($finalValue === 'true') {
$finalValue = true;
}
$finalValue = Sanitize::html( $args[$field] );
if ($finalValue==='false') { $finalValue = false; }
elseif ($finalValue==='true') { $finalValue = true; }
settype($finalValue, gettype($value));
$this->db[$field] = $finalValue;
}
@ -300,9 +301,18 @@ class Plugin
return $this->save();
}
public function type()
public function configure($args)
{
return $this->getMetadata('type');
foreach ($this->db as $field=>$value) {
if (isset($args[$field])) {
$finalValue = Sanitize::html( $args[$field] );
if ($finalValue==='false') { $finalValue = false; }
elseif ($finalValue==='true') { $finalValue = true; }
settype($finalValue, gettype($value));
$this->db[$field] = $finalValue;
}
}
return $this->save();
}
public function setField($field, $value)
@ -318,7 +328,7 @@ class Plugin
// Returns the parameters after the URI, FALSE if the URI doesn't match with the webhook
// Example: https://www.mybludit.com/api/foo/bar
public function webhook($URI = false, $returnsAfterURI = false, $fixed = true)
public function webhook($URI=false, $returnsAfterURI=false, $fixed=true)
{
global $url;
@ -327,10 +337,10 @@ class Plugin
}
// Check URI start with the webhook
$startString = HTML_PATH_ROOT . $URI;
$startString = HTML_PATH_ROOT.$URI;
$URI = $url->uri();
$length = mb_strlen($startString, CHARSET);
if (mb_substr($URI, 0, $length) != $startString) {
if (mb_substr($URI, 0, $length)!=$startString) {
return false;
}
@ -339,7 +349,7 @@ class Plugin
if ($fixed) {
return false;
}
if ($afterURI[0] != '/') {
if ($afterURI[0]!='/') {
return false;
}
}
@ -348,7 +358,8 @@ class Plugin
return $afterURI;
}
Log::set(__METHOD__ . LOG_SEP . 'Webhook requested.');
Log::set(__METHOD__.LOG_SEP.'Webhook requested.');
return true;
}
}
}

View file

@ -1,4 +1,16 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// Title of the page
// ============================================================================
// Authorization
// ============================================================================
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main
// ============================================================================
// HTML <title>
$layout['title'] = $L->g('About') . ' - ' . $layout['title'];

View file

@ -1,7 +1,7 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// Authorization
// ============================================================================
checkRole(array('admin'));
@ -11,22 +11,8 @@ checkRole(array('admin'));
// ============================================================================
// ============================================================================
// Main before POST
// Main
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (createUser($_POST)) {
Redirect::page('users');
}
}
// ============================================================================
// Main after POST
// ============================================================================
// Title of the page
$layout['title'] .= ' - '.$L->g('Add a new user');
// HTML <title>
$layout['title'] = $L->g('New category') . ' - ' . $layout['title'];

View file

@ -1,7 +1,7 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// Authorization
// ============================================================================
checkRole(array('admin'));
@ -11,22 +11,8 @@ checkRole(array('admin'));
// ============================================================================
// ============================================================================
// Main before POST
// Main
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if (createCategory($_POST)) {
Redirect::page('categories');
}
}
// ============================================================================
// Main after POST
// ============================================================================
// Title of the page
$layout['title'] .= ' - '.$L->g('New category');
// HTML <title>
$layout['title'] = $L->g('New user') . ' - ' . $layout['title'];

View file

@ -1,40 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// ============================================================================
checkRole(array('admin'));
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main before POST
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
// ============================================================================
// Main after POST
// ============================================================================
activatePlugin('pluginAPI');
$apiURL = DOMAIN_BASE.'api/';
$pluginAPI = getPlugin('pluginAPI');
$apiToken = $pluginAPI->getToken();
$username = $login->username();
$admin = new User($username);
$authToken = $admin->tokenAuth();
$output = array(
'apiURL'=>$apiURL,
'username'=>$username,
'apiToken'=>$apiToken,
'authToken'=>$authToken
);
exit(json_encode($output));
?>

View file

@ -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');
// HTML <title>
$layout['title'] = $L->g('Categories') . ' - ' . $layout['title'];

View file

@ -1,53 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// ============================================================================
checkRole(array('admin'));
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main before POST
// ============================================================================
$plugin = false;
$pluginClassName = $layout['parameters'];
// Check if the plugin exists
if (isset($plugins['all'][$pluginClassName])) {
$plugin = $plugins['all'][$pluginClassName];
} else {
Redirect::page('plugins');
}
// Check if the plugin has the method form()
if (!method_exists($plugin, 'form')) {
Redirect::page('plugins');
}
// ============================================================================
// POST Method
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Add to syslog
$syslog->add(array(
'dictionaryKey'=>'plugin-configured',
'notes'=>$plugin->name()
));
// Call the method post of the plugin
$plugin->post();
Alert::set( $L->g('The changes have been saved') );
Redirect::page('configure-plugin/'.$plugin->className());
}
// ============================================================================
// Main after POST
// ============================================================================
// Title of the page
$layout['title'] = $L->g('Plugin').' - '.$plugin->name().' - '.$layout['title'];

View file

@ -1,7 +1,7 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// Authorization
// ============================================================================
checkRole(array('admin', 'editor', 'author'));
@ -10,7 +10,7 @@ checkRole(array('admin', 'editor', 'author'));
// Functions
// ============================================================================
// Returns the content belongs to the current user if the user has the role Editor
// Returns the content belongs to the current logged user
function filterContentOwner($list) {
global $login;
global $pages;
@ -24,15 +24,7 @@ function filterContentOwner($list) {
}
// ============================================================================
// Main before POST
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
// ============================================================================
// Main after POST
// Main
// ============================================================================
$published = $pages->getList($url->pageNumber(), ITEMS_PER_PAGE_ADMIN);
@ -40,9 +32,8 @@ $drafts = $pages->getDraftDB(true);
$scheduled = $pages->getScheduledDB(true);
$static = $pages->getStaticDB(true);
$sticky = $pages->getStickyDB(true);
$autosave = $pages->getAutosaveDB(true);
// If the user is an Author filter the content he/she can edit
// If the user has the role "Author" filter the content so he/she can edit
if (checkRole(array('author'), false)) {
$published = filterContentOwner($published);
$drafts = filterContentOwner($drafts);
@ -51,10 +42,10 @@ if (checkRole(array('author'), false)) {
$sticky = filterContentOwner($sticky);
}
// Check if out of range the pageNumber
// Check if the page number is out of range
if (empty($published) && $url->pageNumber()>1) {
Redirect::page('content');
}
// Title of the page
$layout['title'] .= ' - '.$L->g('Manage content');
// View HTML <title>
$layout['title'] = $L->g('Manage content') . ' - ' . $layout['title'];

View file

@ -1,66 +1,16 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Authorization
// ============================================================================
// ============================================================================
// Functions
// ============================================================================
function updateBludit() {
global $site;
global $syslog;
// New installation
if ($site->currentBuild()==0) {
$site->set(array('currentBuild'=>BLUDIT_BUILD));
}
// Check if Bludit need to be update
if ( ($site->currentBuild() < BLUDIT_BUILD) || isset($_GET['update']) ) {
Log::set('UPDATE SYSTEM - Starting.');
// Updates only for version less than Bludit v3.0 rc-3
if ($site->currentBuild()<='20180910') {
@mkdir(PATH_WORKSPACES, DIR_PERMISSIONS, true);
$plugins = array('simple-stats', 'pluginRSS', 'pluginSitemap', 'pluginTimeMachineX', 'pluginBackup');
foreach ($plugins as $plugin) {
if (pluginActivated($plugin)) {
Log::set('UPDATE SYSTEM - Re-enable plugin: '.$plugin);
deactivatePlugin($plugin);
activatePlugin($plugin);
}
}
}
// Updates only for version less than Bludit v3.1
if ($site->currentBuild()<='20180921') {
@mkdir(PATH_UPLOADS_PAGES, DIR_PERMISSIONS, true);
$site->set(array('imageRelativeToAbsolute'=>true, 'imageRestrict'=>false));
}
// Set the current build number
$site->set(array('currentBuild'=>BLUDIT_BUILD));
Log::set('UPDATE SYSTEM - Finished.');
// Add to syslog
$syslog->add(array(
'dictionaryKey'=>'system-updated',
'notes'=>'Bludit v'.BLUDIT_VERSION
));
}
}
// ============================================================================
// Main before POST
// Main
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
// ============================================================================
// Main after POST
// ============================================================================
// Try update Bludit
updateBludit();
// Title of the page
$layout['title'] .= ' - '.$L->g('Dashboard');
// HTML <title>
$layout['title'] = $L->g('Dashboard') . ' - ' . $layout['title'];

View file

@ -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'] . ' ] ';
// HTML <title>
$layout['title'] = $L->g('Edit Category') . ' [ ' . $categoryMap['name'] . ' ] ' . ' - ' . $layout['title'];

View file

@ -1,86 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// ============================================================================
if (checkRole(array('author'), false)) {
try {
$pageKey = isset($_POST['key']) ? $_POST['key'] : $layout['parameters'];
$page = new Page($pageKey);
} catch (Exception $e) {
Alert::set($L->g('You do not have sufficient permissions'));
Redirect::page('dashboard');
}
if ($page->username()!==$login->username()) {
// Add to syslog
$syslog->add(array(
'dictionaryKey'=>'access-denied',
'notes'=>$login->username()
));
Alert::set($L->g('You do not have sufficient permissions'));
Redirect::page('dashboard');
}
}
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main before POST
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
if ($_POST['type']==='delete') {
if (deletePage($_POST['key'])) {
Alert::set( $L->g('The changes have been saved') );
}
} else {
$key = editPage($_POST);
if ($key!==false) {
Alert::set( $L->g('The changes have been saved') );
Redirect::page('edit-content/'.$key);
}
}
Redirect::page('content');
}
// ============================================================================
// Main after POST
// ============================================================================
try {
$pageKey = $layout['parameters'];
$page = new Page($pageKey);
} catch (Exception $e) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to get the page: '.$pageKey, LOG_TYPE_ERROR);
Redirect::page('content');
}
// Images prefix directory
define('PAGE_IMAGES_KEY', $page->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);
}
// Title of the page
$layout['title'] .= ' - '.$L->g('Edit content').' - '.$page->title();

View file

@ -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'];
// HTML <title>
$layout['title'] = $L->g('Edit user') . ' - ' . $layout['title'];

View file

@ -0,0 +1,29 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Authorization
// ============================================================================
checkRole(array('admin', 'editor', 'author'));
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main
// ============================================================================
$pageKey = false;
if (!empty($layout['parameters'])) {
try {
$pageKey = $layout['parameters'];
$page = new Page($pageKey);
} catch (Exception $e) {
Log::set(__METHOD__.LOG_SEP.'An error occurred while trying to get the page: '.$pageKey, LOG_TYPE_ERROR);
Redirect::page('content');
}
}
// HTML <title>
$layout['title'] = $L->g('New content') . ' - ' . $layout['title'];

View file

@ -1,39 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// ============================================================================
checkRole(array('admin'));
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main before POST
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
// ============================================================================
// Main after POST
// ============================================================================
$pluginClassName = $layout['parameters'];
if (!activatePlugin($pluginClassName)) {
Log::set('Fail when try to activate the plugin.', LOG_TYPE_ERROR);
}
if (isset($plugins['all'][$pluginClassName])) {
$plugin = $plugins['all'][$pluginClassName];
} else {
Redirect::page('plugins');
}
if (method_exists($plugin, 'form')) {
Redirect::page('configure-plugin/'.$pluginClassName);
}
Redirect::page('plugins#'.$pluginClassName);

View file

@ -1,52 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// ============================================================================
checkRole(array('admin', 'editor', 'author'));
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main before POST
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
createPage($_POST);
Redirect::page('content');
}
// ============================================================================
// Main after POST
// ============================================================================
// 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);
}
// Title of the page
$layout['title'] = $L->g('New content').' - '.$layout['title'];

View file

@ -1,7 +1,7 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// Authorization
// ============================================================================
checkRole(array('admin'));
@ -11,19 +11,8 @@ checkRole(array('admin'));
// ============================================================================
// ============================================================================
// Main before POST
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
changePluginsPosition(explode(',',$_POST['plugin-list']));
Redirect::page('plugins-position');
}
// ============================================================================
// POST Method
// Main
// ============================================================================
// ============================================================================
// Main after POST
// ============================================================================
// Title of the page
$layout['title'] .= ' - '.$L->g('Plugins');
// HTML <title>
$layout['title'] = $L->g('Plugin') . ' - ' . $layout['title'];

View file

@ -1,7 +1,7 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Check role
// Authorization
// ============================================================================
checkRole(array('admin'));
@ -11,16 +11,23 @@ checkRole(array('admin'));
// ============================================================================
// ============================================================================
// Main before POST
// Main
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
// ============================================================================
// Main after POST
// ============================================================================
$plugin = false;
$pluginClassName = $layout['parameters'];
deactivatePlugin($pluginClassName);
Redirect::page('plugins');
// Check if the plugin is installed/activated
if (pluginActivated($pluginClassName)) {
$plugin = $plugins['all'][$pluginClassName];
} else {
Redirect::page('plugins');
}
// Check if the plugin has the method form()
if (!method_exists($plugin, 'form')) {
Redirect::page('plugins');
}
// HTML <title>
$layout['title'] = $L->g('Plugin'). ' [ ' .$plugin->name(). ' ] ' . ' - ' . $layout['title'];

View file

@ -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');
// HTML <title>
$layout['title'] = $L->g('Plugins') . ' - ' . $layout['title'];

View file

@ -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') {
editSettings($_POST);
Redirect::page('settings');
}
// ============================================================================
// Main after POST
// ============================================================================
// Title of the page
$layout['title'] .= ' - '.$L->g('Advanced Settings');
// HTML <title>
$layout['title'] = $L->g('Settings') . ' - ' . $layout['title'];

View file

@ -21,4 +21,4 @@ checkRole(array('admin'));
$themes = buildThemes();
// Title of the page
$layout['title'] .= ' - '.$L->g('Themes');
$layout['title'] = $L->g('Themes') . ' - ' . $layout['title'];

View file

@ -1,51 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Functions
// ============================================================================
// ============================================================================
// Main before POST
// ============================================================================
// ============================================================================
// POST Method
// ============================================================================
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
// Prevent non-administrators to change other users
$username = $_POST['username'];
if ($login->role()!=='admin') {
$username = $login->username();
}
if (changeUserPassword(array(
'username'=>$username,
'newPassword'=>$_POST['newPassword'],
'confirmPassword'=>$_POST['confirmPassword']
))) {
if ($login->role()==='admin') {
Redirect::page('users');
}
Redirect::page('edit-user/'.$login->username());
}
}
// ============================================================================
// Main after POST
// ============================================================================
// Prevent non-administrators to change other users
if ($login->role()!=='admin') {
$layout['parameters'] = $login->username();
}
try {
$username = $layout['parameters'];
$user = new User($username);
} catch (Exception $e) {
Redirect::page('users');
}
// Title of the page
$layout['title'] = $L->g('Change password').' - '.$layout['title'];

View file

@ -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');
// HTML <title>
$layout['title'] = $L->g('Users') . ' - ' . $layout['title'];

View file

@ -0,0 +1,40 @@
html {
font-size: 0.9rem;
}
.link {
text-decoration: underline;
}
/*
Left sidebar
*/
div.sidebar .nav-item a {
padding-left: 0;
padding-right: 0;
padding-top: 5px;
padding-bottom: 5px;
}
div.sidebar .nav-item h4 {
font-size: 1.2em;
text-transform: uppercase;
font-weight: 400;
margin-top: 10px;
}
/*
Editor
*/
#btnCurrenType {
cursor: pointer;
}
.link {
cursor: pointer;
text-decoration: underline;
}

View file

@ -0,0 +1,12 @@
/* Remove Focus glow */
.btn:focus,
.form-control:focus,
.form-select:focus {
outline: none !important;
box-shadow: none !important;
}
/* Icons */
.bi {
margin-right: .5rem!important;
}

View file

@ -0,0 +1,142 @@
body {
background-color: #1C1C1E;
color: #b3b3b3;
}
.bg-dark {
background-color: #111111 !important;
}
.bg-light {
background-color: #111111 !important;
}
.bg-info {
background-color: #003c58!important;
}
a,
a.nav-link,
.link,
a.dropdown-menu,
.dropdown-item {
color: #b3b3b3;
}
a:hover,
a.nav-link:hover,
.link:hover {
color: #e2e2e2 !important
}
.form-text {
color: #989899 !important;
}
.form-control:disabled, .form-control[readonly] {
background-color: #444;
}
.color-blue {
color: #688bbd !important;
}
.btn {
color: #e0e0e0;
}
.btn-outline-primary {
color: #688bbd !important;
border-color: #688bbd !important;
}
.btn-outline-primary:hover {
background-color: #1C1C1E !important;
color: #fff !important;
}
.page-link {
color: #688bbd !important;
border-color: #688bbd !important;
background-color: #1C1C1E !important;
}
.form-control,
.form-select {
background-color: #111111;
border-color: #302F33;
color: #b3b3b3;
}
.form-control:focus,
.form-select:focus {
background-color: #111111;
border-color: #302F33;
color: #b3b3b3;
}
.nav-tabs .nav-item.show .nav-link,
.nav-tabs .nav-link.active {
background-color: #1C1C1E !important;
border-color: #302F33 !important;
color: #b3b3b3 !important;
}
.nav-tabs .nav-link:focus,
.nav-tabs .nav-link:hover {
border-color: #302F33 !important;
}
.nav-tabs {
border-bottom-color:#302F33 !important;
}
.table {
color: #b3b3b3 !important;
border-bottom-color:#302F33 !important;
}
.table-striped>tbody>tr:nth-of-type(odd) {
background-color: #171717;
color: #b3b3b3;
}
.border-bottom {
border-bottom-color:#302F33 !important;
}
.alert-primary {
background-color: #191e27;
border-color: #232a35;
color: #b3b3b3;
}
.modal-content {
background-color: #121212 !important;
color: #b3b3b3 !important;
border-color: #2f3233;
}
.modal-footer {
border-top-color: #302F33;
}
.dropdown-menu {
background-color: #121212 !important;
color: #b3b3b3 !important;
}
.list-group-item {
background-color: inherit;
color: #b3b3b3;
border: 0 none;
}
.list-group-item a {
text-decoration: none;
}
.border-top,
.border-bottom {
border-color: #302F33 !important;
}

View file

@ -0,0 +1,36 @@
body {
background-color: #f1f1f1;
}
a {
color: #555;
}
a.nav-link {
color: #555;
}
.form-control:focus,
.form-select:focus {
border-color: #999999;
}
.btn-primary-disabled {
background-color: #4792ff !important;
border-color: #4792ff !important;
}
.nav-tabs .nav-item.show .nav-link,
.nav-tabs .nav-link.active {
background-color: #d8d8d8;
border-color: #dee2e6;
}
.list-group-item {
background-color: inherit;
border: 0 none;
}
.list-group-item a {
text-decoration: none;
}

View file

@ -1,58 +0,0 @@
a {
color: #0078D4;
}
a:hover {
color: #003f6f;
text-decoration: none;
}
.bg-success {
background-color: #8BC34A!important;
}
.text-primary {
color: #0078D4!important;
}
.text-danger {
color: #D40000!important;
}
a.text-danger:focus,
a.text-danger:hover {
color: #790000!important;
}
/* Buttons */
.btn-primary {
background-color: #0078D4;
border-color: #0078D4;
}
.btn-primary:hover {
background-color: #4585CF;
border-color: #4a90e2;
}
.btn-light.focus, .btn-light:focus {
box-shadow: none;
}
.btn.focus, .btn:focus {
box-shadow: none;
}
/* Form */
.form-control:focus {
box-shadow: none;
}
/* Tables */
.table-striped tbody tr:nth-of-type(odd) {
background-color: rgba(0, 0, 0, 0.02);
}
.table thead th {
font-size: 0.8em;
text-transform: uppercase!important;
}

View file

@ -1,367 +0,0 @@
html {
height: 100%;
font-size: 0.9rem;
background: #fcfcfc;
}
body {
background: #fcfcfc;
}
/* Prevent events in iframes */
/* iframe{
pointer-events: none;
} */
/*
ICONS
*/
.fa {
margin-right: .5rem !important;
line-height: inherit;
}
/*
SIDEBAR
*/
div.sidebar .nav-item a {
padding-left: 0;
padding-right: 0;
color: #555;
padding-top: 5px;
padding-bottom: 5px;
}
div.sidebar .nav-item a:hover {
color: #0078D4;
}
div.sidebar .nav-item h4 {
font-size: 1.2em;
text-transform: uppercase;
font-weight: 400;
margin-top: 10px;
}
/*
AUTOCOMPLETE SEARCH
*/
.search-suggestion {
padding: 5px;
}
.search-suggestion-options {
font-size: 0.9em;
padding-top: 2px;
}
/*
BOOTSTRAP Hacks
*/
@media (min-width: 1200px) {
.container {
max-width: 1250px;
}
}
/* for small devices */
@media (max-width: 575.98px) {
#jsmediaManagerButton,
#jscategoryButton,
#jsdescriptionButton {
width: 100%;
text-align: left;
}
}
.btn-light {
color: #212529;
background-color: #f3f3f3;
border-color: #ced4d9;
}
.btn-form {
background-color: #F3F3F3;
border-color: #DDD;
color: #000;
}
.btn-form:hover {
background-color: rgb(228, 228, 228);
border-color: #DDD;
color: #000;
}
code {
padding: 3px 5px 2px;
margin: 0 1px;
background: #eaeaea;
background: rgba(0, 0, 0, .07);
color: #444;
}
.list-group-sortable {
cursor: pointer;
}
.modal-body {
padding: 2rem;
}
.modal-footer {
background-color: rgb(247, 247, 247);
}
.modal-dialog .btn-link {
color: #000;
}
/*
LOGIN
*/
body.login {
background: rgb(255, 255, 255);
background: linear-gradient(0deg, rgba(255, 255, 255, 1) 0%, rgba(250, 250, 250, 1) 53%);
height: 100%;
}
/*
DASHBOARD
*/
#dashboard ul.list-group.list-group-striped li {
border: none;
word-break: break-word;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
#dashboard ul.list-group.list-group-striped li:nth-of-type(even) {
background: #f1f1f1;
}
#dashboard div.quick-links-icons {
font-size: 3em;
width: 100%;
}
#dashboard a.quick-links {
color: #777;
}
#dashboard a.quick-links:hover {
text-decoration: none;
color: #4586d4;
}
#hello-message {
padding: 10px 0;
margin-bottom: 20px;
}
#hello-message span.oi {
top: 3px;
}
.ct-series-a .ct-line {
/* Set the colour of this series line */
stroke: #4a90e2;
/* Control the thikness of your lines */
stroke-width: 2px;
/* Create a dashed line with a pattern */
}
.ct-series-a .ct-point {
/* Colour of your points */
stroke: #4a90e2;
/* Size of your points */
stroke-width: 8px;
}
/*
ALERT
*/
#alert {
display: none;
position: fixed;
text-align: center;
border-radius: 0px;
border: 0;
z-index: 1000;
bottom: 0;
right: 0;
margin: 0;
}
.alert-success {
background-color: #4586d4;
border-left: 6px solid #abd1ff !important;
color: #ffffff;
}
.alert-danger {
background-color: #d44545;
border-left: 6px solid #ff9c9c !important;
color: #ffffff;
}
/*
PLUGINS
*/
.plugin-form label {
display: block;
margin-top: 1rem !important;
}
.plugin-form input[type="text"],
.plugin-form textarea,
.plugin-form select {
display: block;
width: 100%;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
color: #495057;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
border-radius: .25rem;
transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out;
}
.plugin-form textarea {
min-height: 120px;
}
.plugin-form span.tip {
display: block;
font-size: 80%;
font-weight: 400;
margin-top: .25rem;
color: #6c757d !important;
}
/*
Manage > Content
*/
td.child {
padding-left: 30px;
}
/*
Manage > New Content
*/
#jseditor {
background: #fff;
padding: 10px 5% !important;
font-size: 16px;
line-height: 1.5em;
border: 1px solid #ced4da;
}
#jseditorSidebar {
display: none;
height: calc(100% - 45px);
width: 50%;
max-width: 350px;
position: absolute;
z-index: 50;
top: 45px;
right: 15px;
background-color: #fff;
overflow-x: hidden;
transition: 0.5s;
border-left: 1px solid #ccc;
border-right: 1px solid #ccc;
border-top: 1px solid #ccc;
}
@media (max-width: 575.98px) {
#jseditorSidebar {
width: 100%;
max-width: 100%;
right: 0;
}
#jseditorToolbarRight button {
font-size: 0px !important;
}
#jseditorToolbarRight button span {
font-size: 16px !important;
}
.contentTools .btn {
font-size: 0px !important;
margin-right: 5px;
}
.contentTools .btn span {
font-size: 16px !important;
}
}
#jseditorSidebar nav {
background: #f3f3f3;
}
#jseditorSidebar nav a {
color: #000;
}
#jseditorSidebar .nav-tabs .nav-link {
border: none;
}
#jseditorSidebar .nav-link.active {
background: none;
border: none;
border-bottom: 3px solid #ccc;
}
#jsshadow {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(72, 72, 72, 0.7);
z-index: 10;
display: none;
}
img.profilePicture {
width: 30px;
height: 30px;
border-radius: 30px;
border: 1px solid #ccc;
}
/* Switch button */
.switch-button {
font-size: 0.9em;
text-transform: uppercase;
cursor: pointer;
}
.switch-icon-publish {
color: #1cb11c;
}

View file

@ -1,17 +0,0 @@
<script charset="utf-8">
function showAlert(text) {
console.log("[INFO] Function showAlert() called.");
$("#alert").html(text);
$("#alert").slideDown().delay(<?php echo ALERT_DISAPPEAR_IN*1000 ?>).slideUp();
}
<?php if (Alert::defined()): ?>
setTimeout(function(){ showAlert("<?php echo Alert::get() ?>") }, 500);
<?php endif; ?>
$(window).click(function() {
$("#alert").hide();
});
</script>
<div id="alert" class="alert <?php echo (Alert::status()==ALERT_STATUS_FAIL)?'alert-danger':'alert-success' ?>"></div>

View file

@ -0,0 +1,31 @@
<div aria-live="polite" aria-atomic="true" class="position-relative">
<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>
<script>
function showAlert(text, background='primary') {
$('#alert').removeClass('bg-danger bg-warning bg-primary').addClass('bg-'+background);
$('#alert').html(text);
$('#alert').toast('show');
}
function showAlertError(text) {
showAlert(text, 'danger');
}
function showAlertWarning(text) {
showAlert(text, 'warning');
}
function showAlertInfo(text) {
showAlert(text, 'primary');
}
function hideAlert(text) {
$('#alert').toast('hide');
}
</script>

View file

@ -1,262 +0,0 @@
<?php
// Preload the first 10 files to not call via AJAX when the user open the first time the media manager
$listOfFilesByPage = Filesystem::listFiles(PAGE_THUMBNAILS_DIRECTORY, '*', '*', MEDIA_MANAGER_SORT_BY_DATE, MEDIA_MANAGER_NUMBER_OF_FILES);
$preLoadFiles = array();
if (!empty($listOfFilesByPage[0])) {
foreach ($listOfFilesByPage[0] as $file) {
$filename = Filesystem::filename($file);
array_push($preLoadFiles, $filename);
}
}
// Amount of pages for the paginator
$numberOfPages = count($listOfFilesByPage);
?>
<div id="jsmediaManagerModal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="container-fluid">
<div class="row">
<div class="col p-3">
<!--
UPLOAD INPUT
-->
<h3 class="mt-2 mb-3"><i class="fa fa-image"></i> <?php $L->p('Images'); ?></h3>
<div id="jsalertMedia" class="alert alert-warning d-none" role="alert"></div>
<!-- Form and Input file -->
<form name="bluditFormUpload" id="jsbluditFormUpload" enctype="multipart/form-data">
<div class="custom-file">
<input type="file" class="custom-file-input" id="jsimages" name="images[]" multiple>
<label class="custom-file-label" for="jsimages"><?php $L->p('Choose images to upload'); ?></label>
</div>
</form>
<!-- Progress bar -->
<div class="progress mt-3">
<div id="jsbluditProgressBar" class="progress-bar bg-primary" role="progressbar" style="width:0%"></div>
</div>
<!--
IMAGES LIST
-->
<!-- Table for list files -->
<table id="jsbluditMediaTable" class="table mt-3">
<tr>
<td><?php $L->p('There are no images'); ?></td>
</tr>
</table>
<!-- Paginator -->
<nav id="jsbluditMediaTablePagination"></nav>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
<?php
echo 'var preLoadFiles = '.json_encode($preLoadFiles).';';
?>
function openMediaManager() {
$('#jsmediaManagerModal').modal('show');
}
function closeMediaManager() {
$('#jsmediaManagerModal').modal('hide');
}
// Remove all files from the table
function cleanTable() {
$('#jsbluditMediaTable').empty();
}
function showMediaAlert(message) {
$("#jsalertMedia").html(message).removeClass('d-none');
}
function hideMediaAlert() {
$("#jsalertMedia").addClass('d-none');
}
// Show the files in the table
function displayFiles(files, numberOfPages = <?= $numberOfPages ?>) {
if (!Array.isArray(files)) {
return false;
}
// Clean table
cleanTable();
// Regenerate the table
if (files.length > 0) {
$.each(files, function(key, filename) {
var thumbnail = "<?php echo PAGE_THUMBNAILS_URL; ?>"+filename;
var image = "<?php echo PAGE_IMAGES_URL; ?>"+filename;
tableRow = '<tr id="js'+filename+'">'+
'<td style="width:80px"><img class="img-thumbnail" alt="200x200" src="'+thumbnail+'" style="width: 50px; height: 50px;"><\/td>'+
'<td class="information">'+
'<div class="text-secondary pb-2">'+filename+'<\/div>'+
'<div>'+
'<a href="#" class="mr-3 text-primary" onClick="editorInsertMedia(\''+image+'\'); closeMediaManager();"><i class="fa fa-plus-circle"></i><?php $L->p('Insert') ?><\/a>'+
'<a href="#" class="mr-3 text-primary" onClick="editorInsertMedia(\''+thumbnail+'\'); closeMediaManager();"><i class="fa fa-image"></i><?php $L->p('Insert thumbnail') ?><\/a>'+
'<a href="#" class="mr-3 text-primary" onClick="editorInsertLinkedMedia(\''+thumbnail+'\',\''+image+'\'); closeMediaManager();"><i class="fa fa-link"></i><?php $L->p('Insert linked thumbnail') ?><\/a>'+
'<a href="#" class="text-primary" onClick="setCoverImage(\''+filename+'\'); closeMediaManager();"><i class="fa fa-desktop"></i><?php $L->p('Set as cover image') ?><\/button>'+
'<a href="#" class="float-right text-danger" onClick="deleteMedia(\''+filename+'\')"><i class="fa fa-trash-o"></i><?php $L->p('Delete') ?><\/a>'+
'<\/div>'+
'<\/td>'+
'<\/tr>';
$('#jsbluditMediaTable').append(tableRow);
});
mediaPagination = '<ul class="pagination justify-content-center flex-wrap">';
for (var i = 1; i <= numberOfPages; i++) {
mediaPagination += '<li class="page-item"><button type="button" class="btn btn-link page-link" onClick="getFiles('+i+')">'+i+'</button></li>';
}
mediaPagination += '</ul>';
$('#jsbluditMediaTablePagination').html(mediaPagination);
}
if (files.length == 0) {
$('#jsbluditMediaTable').html("<p><?php (IMAGE_RESTRICT ? $L->p('There are no images for the page') : $L->p('There are no images')) ?></p>");
$('#jsbluditMediaTablePagination').html('');
}
}
// Get the list of files via AJAX, filter by the page number
function getFiles(pageNumber) {
$.post(HTML_PATH_ADMIN_ROOT+"ajax/list-images",
{ tokenCSRF: tokenCSRF,
pageNumber: pageNumber,
uuid: "<?php echo PAGE_IMAGES_KEY ?>",
path: "thumbnails" // the paths are defined in ajax/list-images
},
function(data) { // success function
if (data.status==0) {
displayFiles(data.files, data.numberOfPages);
} else {
console.log(data.message);
}
}
);
}
// Delete the file and the thumbnail if exist
function deleteMedia(filename) {
$.post(HTML_PATH_ADMIN_ROOT+"ajax/delete-image",
{ tokenCSRF: tokenCSRF,
filename: filename,
uuid: "<?php echo PAGE_IMAGES_KEY; ?>"
},
function(data) { // success function
if (data.status==0) {
getFiles(1);
} else {
console.log(data.message);
}
}
);
}
function setCoverImage(filename) {
var image = "<?php echo PAGE_IMAGES_URL; ?>"+filename;
$("#jscoverImage").val(filename);
$("#jscoverImagePreview").attr("src", image);
}
function uploadImages() {
// Remove current alerts
hideMediaAlert();
var images = $("#jsimages")[0].files;
for (var i=0; i < images.length; i++) {
// Check file type/extension
const validImageTypes = ['image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', 'image/webp'];
if (!validImageTypes.includes(images[i].type)) {
showMediaAlert("<?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 (images[i].size > UPLOAD_MAX_FILESIZE) {
showMediaAlert("<?php echo $L->g('Maximum load file size allowed:').' '.ini_get('upload_max_filesize') ?>");
return false;
}
};
// Clean progress bar
$("#jsbluditProgressBar").removeClass().addClass("progress-bar bg-primary");
$("#jsbluditProgressBar").width("0");
// Data to send via AJAX
var formData = new FormData($("#jsbluditFormUpload")[0]);
formData.append("uuid", "<?php echo PAGE_IMAGES_KEY ?>");
formData.append("tokenCSRF", tokenCSRF);
$.ajax({
url: HTML_PATH_ADMIN_ROOT+"ajax/upload-images",
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;
$("#jsbluditProgressBar").width(percentComplete+"%");
}
}, false);
}
return xhr;
}
}).done(function(data) {
if (data.status==0) {
$("#jsbluditProgressBar").removeClass("bg-primary").addClass("bg-success");
// Get the files for the first page, this include the files uploaded
getFiles(1);
} else {
$("#jsbluditProgressBar").removeClass("bg-primary").addClass("bg-danger");
showMediaAlert(data.message);
}
});
}
$(document).ready(function() {
// Display the files preloaded for the first time
displayFiles(preLoadFiles);
// Select image event
$("#jsimages").on("change", function(e) {
uploadImages();
});
// Drag and drop image
$(window).on("dragover dragenter", function(e) {
e.preventDefault();
e.stopPropagation();
openMediaManager();
});
// Drag and drop image
$(window).on("drop", function(e) {
e.preventDefault();
e.stopPropagation();
$("#jsimages").prop("files", e.originalEvent.dataTransfer.files);
uploadImages();
});
});
</script>

View file

@ -17,7 +17,7 @@
<?php $L->p('Website') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'new-content' ?>">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'editor' ?>">
<?php $L->p('New content') ?></a>
</li>
<li class="nav-item">
@ -25,10 +25,10 @@
<?php $L->p('Content') ?></a>
</li>
<?php if (!checkRole(array('admin'),false)): ?>
<li class="nav-item">
<li class="nav-item">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'edit-user/'.$login->username() ?>">
<?php $L->p('Profile') ?></a>
</li>
<?php $L->p('Profile') ?></a>
</li>
<?php endif; ?>
<?php if (checkRole(array('admin'),false)): ?>
<li class="nav-item">
@ -57,15 +57,15 @@
</li>
<?php endif; ?>
<?php if (checkRole(array('admin'),false)): ?>
<?php
if (!empty($plugins['adminSidebar'])) {
foreach ($plugins['adminSidebar'] as $pluginSidebar) {
echo '<li class="nav-item">';
echo $pluginSidebar->adminSidebar();
echo '</li>';
<?php
if (!empty($plugins['adminSidebar'])) {
foreach ($plugins['adminSidebar'] as $pluginSidebar) {
echo '<li class="nav-item">';
echo $pluginSidebar->adminSidebar();
echo '</li>';
}
}
}
?>
?>
<?php endif; ?>
<li class="nav-item">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'logout' ?>">

View file

@ -1,27 +1,31 @@
<!-- Use .flex-column to set a vertical direction -->
<ul class="nav flex-column pt-4">
<ul class="nav flex-column">
<li class="nav-item mb-4" style="margin-left: -4px;">
<img src="<?php echo HTML_PATH_CORE_IMG ?>logo.svg" width="20" height="20" alt="bludit-logo"><span class="ml-2 align-middle"><?php echo (defined('BLUDIT_PRO'))?'BLUDIT PRO':'BLUDIT' ?></span>
</li>
<li class="nav-item">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'dashboard' ?>"><span class="fa fa-dashboard"></span><?php $L->p('Dashboard') ?></a>
<li class="nav-item mb-3">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'editor' ?>">
<i class="bi bi-plus-circle"></i>
<?php $L->p('New content') ?>
</a>
</li>
<li class="nav-item">
<a class="nav-link" target="_blank" href="<?php echo HTML_PATH_ROOT ?>"><span class="fa fa-home"></span><?php $L->p('Website') ?></a>
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'dashboard' ?>">
<i class="bi bi-kanban"></i>
<?php $L->p('Dashboard') ?>
</a>
</li>
<li class="nav-item mt-3">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'new-content' ?>"><span style="color: #0078D4;" class="fa fa-plus-circle"></span><?php $L->p('New content') ?></a>
<li class="nav-item">
<a class="nav-link" href="<?php echo DOMAIN_BASE ?>">
<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="fa fa-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="fa fa-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; ?>
@ -31,30 +35,38 @@
<h4><?php $L->p('Manage') ?></h4>
</li>
<li class="nav-item">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'content' ?>"><span class="fa fa-folder"></span><?php $L->p('Content') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'categories' ?>"><span class="fa fa-bookmark"></span><?php $L->p('Categories') ?></a>
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'content' ?>">
<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.'users' ?>"><span class="fa fa-users"></span><?php $L->p('Users') ?></a>
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'categories' ?>">
<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 bi-people"></i>
<?php $L->p('Users') ?>
</a>
</li>
<li class="nav-item mt-3">
<h4><?php $L->p('Settings') ?></h4>
</li>
<li class="nav-item">
<a class="nav-link" href="<?php echo HTML_PATH_ADMIN_ROOT.'settings' ?>"><span class="fa fa-gear"></span><?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' ?>"><span class="fa fa-puzzle-piece"></span><?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' ?>"><span class="fa fa-desktop"></span><?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' ?>"><span class="fa fa-info"></span><?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; ?>
@ -75,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="fa fa-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>

View file

@ -1,98 +1,123 @@
<!DOCTYPE html>
<html>
<html class="h-100">
<head>
<title><?php echo $layout['title'] ?></title>
<meta charset="<?php echo CHARSET ?>">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<meta name="generator" content="Bludit">
<!-- Favicon -->
<link rel="shortcut icon" type="image/x-icon" href="<?php echo HTML_PATH_CORE_IMG.'favicon.png?version='.BLUDIT_VERSION ?>">
<link rel="shortcut icon" type="image/x-icon" href="<?php echo HTML_PATH_CORE_IMG . 'favicon.png?version=' . BLUDIT_VERSION ?>">
<!-- CSS -->
<?php
echo Theme::cssBootstrap();
echo Theme::cssLineAwesome();
echo Theme::css(array(
'bludit.css',
'bludit.bootstrap.css'
echo HTML::cssBootstrap();
echo HTML::cssBootstrapIcons();
echo HTML::css(array(
'01-bludit.css',
'02-bootstrap-hacks.css'
), DOMAIN_ADMIN_THEME_CSS);
echo Theme::css(array(
echo HTML::css(array(
'jquery.datetimepicker.min.css',
'jquery-ui.min.css',
'select2.min.css',
'select2-bootstrap4.min.css'
'select2-bootstrap4.min.css',
'tagsinput-revisited.min.css'
), DOMAIN_CORE_CSS);
if ($site->darkModeAdmin()) {
echo HTML::css(array(
'99-darkmode.css'
), DOMAIN_ADMIN_THEME_CSS);
} else {
echo HTML::css(array(
'99-lightmode.css'
), DOMAIN_ADMIN_THEME_CSS);
}
?>
<!-- Javascript -->
<?php
echo Theme::jquery();
echo Theme::jsBootstrap();
echo Theme::jsSortable();
echo Theme::js(array(
'jquery.datetimepicker.full.min.js',
'select2.full.min.js',
'functions.js'
), DOMAIN_CORE_JS, null);
echo HTML::jquery();
echo HTML::jsBootstrap();
echo HTML::jsSortable();
echo HTML::bootbox();
echo HTML::js(array(
'jquery.datetimepicker.full.min.js',
'jquery-ui.min.js',
'select2.full.min.js',
'tagsinput-revisited.min.js',
'functions.js',
'api.js'
), DOMAIN_CORE_JS);
?>
<!-- Plugins -->
<?php Theme::plugins('adminHead') ?>
<!-- Execute plugins for the admin area inside the HTML <head> tag -->
<?php execPluginsByHook('adminHead') ?>
</head>
<body class="h-100">
<!-- Plugins -->
<?php Theme::plugins('adminBodyBegin') ?>
<!-- Execute plugins for the admin area inside the HTML <body> at the begginig -->
<?php execPluginsByHook('adminBodyBegin') ?>
<!-- Javascript dynamic generated by PHP -->
<?php
echo '<script charset="utf-8">'.PHP_EOL;
include(PATH_CORE_JS.'variables.php');
echo '</script>'.PHP_EOL;
<!-- Javascript global variable generated by PHP -->
<?php include(PATH_CORE_JS . 'variables.php') ?>
echo '<script charset="utf-8">'.PHP_EOL;
include(PATH_CORE_JS.'bludit-ajax.php');
echo '</script>'.PHP_EOL;
?>
<div class="container-fluid p-0 m-0 d-flex flex-column h-100">
<!-- Overlay background -->
<div id="jsshadow"></div>
<!-- Alerts -->
<?php include('html/alerts.php') ?>
<!-- End Alerts -->
<!-- Alert -->
<?php include('html/alert.php'); ?>
<!-- Navbar, only for small devices -->
<?php include('html/navbar.php'); ?>
<div class="container h-100">
<!-- 25%/75% split on large devices, small, medium devices hide -->
<div class="row h-100">
<!-- LEFT SIDEBAR - Display only on large devices -->
<div class="sidebar col-lg-2 d-none d-lg-block">
<?php include('html/sidebar.php'); ?>
<!-- Top Navbar -->
<div class="container-fluid p-0 bg-dark">
<div class="container">
<div class="row">
<nav class="navbar navbar-dark p-1">
<a class="navbar-brand" href="#">
<img src="/bl-kernel/img/logo.svg" alt="" width="30" height="24" class="d-inline-block align-top">
Bludit
</a>
</nav>
</div>
</div>
</div>
<!-- End Top Navbar -->
<!-- RIGHT MAIN -->
<div class="col-lg-10 pt-3 pb-1 h-100">
<?php
if (Sanitize::pathFile(PATH_ADMIN_VIEWS, $layout['view'].'.php')) {
include(PATH_ADMIN_VIEWS.$layout['view'].'.php');
} elseif ($layout['plugin'] && method_exists($layout['plugin'], 'adminView')) {
echo $layout['plugin']->adminView();
} else {
echo '<h1 class="text-center">'.$L->g('Page not found').'</h1>';
echo '<h2 class="text-center">'.$L->g('Choose a page from the sidebar.').'</h2>';
}
?>
<!-- Main -->
<div class="container h-100 flex-grow-1">
<div class="row h-100 flex-grow-1">
<!-- LEFT Main, display only on large devices -->
<div class="sidebar col-lg-2 d-none d-lg-block mt-4">
<?php include('html/sidebar.php'); ?>
</div>
<!-- RIGHT Main -->
<div class="main col-lg-10 mt-2">
<?php
if (Sanitize::pathFile(PATH_ADMIN_VIEWS . $layout['view'] . '.php')) {
include(PATH_ADMIN_VIEWS . $layout['view'] . '.php');
} elseif ($layout['plugin'] && method_exists($layout['plugin'], 'adminView')) {
echo $layout['plugin']->adminView();
} else {
echo '<h1 class="text-center">' . $L->g('Page not found') . '</h1>';
echo '<h2 class="text-center">' . $L->g('Choose a page from the sidebar.') . '</h2>';
}
?>
</div>
</div>
</div>
<!-- End Main -->
</div>
</div>
<!-- Plugins -->
<?php Theme::plugins('adminBodyEnd') ?>
<!-- Execute plugins for the admin area inside the HTML <body> at the end -->
<?php execPluginsByHook('adminBodyEnd') ?>
</body>
</html>
</html>

View file

@ -1,403 +1,9 @@
<?php
<?php defined('BLUDIT') or die('Bludit CMS.');
class Bootstrap
{
// Init scripts for the theme
public static function modal($args)
{
$buttonSecondary = $args['buttonSecondary'];
$buttonSecondaryClass = $args['buttonSecondaryClass'];
$buttonPrimary = $args['buttonPrimary'];
$buttonPrimaryClass = $args['buttonPrimaryClass'];
$modalText = $args['modalText'];
$modalTitle = $args['modalTitle'];
$modalId = $args['modalId'];
return <<<EOF
<div id="$modalId" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<h3>$modalTitle</h3>
<p>$modalText</p>
</div>
<div class="modal-footer">
<button type="button" class="btn $buttonSecondaryClass" data-dismiss="modal">$buttonSecondary</button>
<button type="button" class="btn $buttonPrimaryClass">$buttonPrimary</button>
</div>
</div>
</div>
</div>
EOF;
}
public static function link($args)
{
$options = 'href="' . $args['href'] . '"';
if (isset($args['class'])) {
$options .= ' class="' . $args['class'] . '"';
}
if (isset($args['target'])) {
$options .= ' target="' . $args['target'] . '"';
}
if (isset($args['icon'])) {
return '<a ' . $options . '><span class="fa fa-' . $args['icon'] . '"></span>' . $args['title'] . '</a>';
}
return '<a ' . $options . '>' . $args['title'] . '</a>';
}
public static function pageTitle($args)
{
$icon = $args['icon'];
$title = $args['title'];
return <<<EOF
<h2 class="mt-0 mb-3">
<span class="fa fa-$icon" style="font-size: 0.9em;"></span><span>$title</span>
</h2>
EOF;
}
public static function formOpen($args)
{
$class = empty($args['class']) ? '' : 'class="' . $args['class'] . '"';
$id = empty($args['id']) ? '' : 'id="' . $args['id'] . '"';
$enctype = empty($args['enctype']) ? '' : 'enctype="' . $args['enctype'] . '"';
$action = empty($args['action']) ? 'action=""' : 'action="' . $args['action'] . '"';
$method = empty($args['method']) ? 'method="post"' : 'method="' . $args['method'] . '"';
$style = empty($args['style']) ? '' : 'style="' . $args['style'] . '"';
return <<<EOF
<form $class $enctype $id $method $action $style autocomplete="off">
EOF;
}
public static function formClose()
{
return <<<EOF
</form>
<script>
$(document).ready(function() {
// Prevent the form submit when press enter key.
$("form").keypress(function(e) {
if ((e.which == 13) && (e.target.type !== "textarea")) {
return false;
}
});
});
</script>
EOF;
}
public static function formTitle($args)
{
$title = $args['title'];
return <<<EOF
<h6 class="mt-4 mb-2 pb-2 border-bottom text-uppercase">$title</h6>
EOF;
}
public static function formInputTextBlock($args)
{
$name = $args['name'];
$disabled = empty($args['disabled']) ? '' : 'disabled';
$placeholder = isset($args['placeholder']) ? $args['placeholder'] : '';
$value = isset($args['value']) ? $args['value'] : '';
$id = 'js' . $name;
if (isset($args['id'])) {
$id = $args['id'];
}
$tip = '';
if (!empty($args['tip'])) {
$tip = '<small class="form-text text-muted">' . $args['tip'] . '</small>';
}
$class = 'form-group m-0';
if (isset($args['class'])) {
$class = $args['class'];
}
$labelClass = 'mt-4 mb-2 pb-2 border-bottom text-uppercase w-100';
if (isset($args['labelClass'])) {
$labelClass = $args['labelClass'];
}
$label = '';
if (!empty($args['label'])) {
$label = '<label class="' . $labelClass . '" for="' . $id . '">' . $args['label'] . '</label>';
}
$type = 'text';
if (isset($args['type'])) {
$type = $args['type'];
}
return <<<EOF
<div class="$class">
$label
<input type="text" dir="auto" value="$value" class="form-control" id="$id" name="$name" placeholder="$placeholder" $disabled>
$tip
</div>
EOF;
}
public static function formInputFile($args)
{
$id = 'js' . $args['name'];
if (isset($args['id'])) {
$id = $args['id'];
}
$class = 'custom-file';
if (isset($args['class'])) {
$class = $class . ' ' . $args['class'];
}
$html = '<div class="' . $class . '">';
$html .= '<input type="file" class="custom-file-input" id="' . $id . '">';
$html .= '<label class="custom-file-label" for="' . $id . '">' . $args['label'] . '</label>';
$html .= '</div>';
return $html;
}
public static function formTextarea($args)
{
$id = 'js' . $args['name'];
if (isset($args['id'])) {
$id = $args['id'];
}
$class = 'form-control';
if (isset($args['class'])) {
$class = $class . ' ' . $args['class'];
}
$html = '<div class="form-group row">';
if (!empty($args['label'])) {
$html .= '<label for="' . $id . '" class="col-sm-2 col-form-label">' . $args['label'] . '</label>';
}
$html .= '<div class="col-sm-10">';
$html .= '<textarea class="' . $class . '" id="' . $id . '" name="' . $args['name'] . '" rows="' . $args['rows'] . '" placeholder="' . $args['placeholder'] . '">' . $args['value'] . '</textarea>';
if (isset($args['tip'])) {
$html .= '<small class="form-text text-muted">' . $args['tip'] . '</small>';
}
$html .= '</div>';
$html .= '</div>';
return $html;
}
public static function formTextareaBlock($args)
{
$id = 'js' . $args['name'];
if (isset($args['id'])) {
$id = $args['id'];
}
$class = 'form-control';
if (!empty($args['class'])) {
$class = $class . ' ' . $args['class'];
}
$html = '<div class="form-group m-0">';
if (!empty($args['label'])) {
$html .= '<label class="mt-4 mb-2 pb-2 border-bottom text-uppercase w-100" for="' . $id . '">' . $args['label'] . '</label>';
}
$html .= '<textarea class="' . $class . '" id="' . $id . '" name="' . $args['name'] . '" rows="' . $args['rows'] . '" placeholder="' . $args['placeholder'] . '">' . $args['value'] . '</textarea>';
if (!empty($args['tip'])) {
$html .= '<small class="form-text text-muted">' . $args['tip'] . '</small>';
}
$html .= '</div>';
return $html;
}
public static function formInputText($args)
{
$name = $args['name'];
$disabled = empty($args['disabled']) ? '' : 'disabled';
$readonly = empty($args['readonly']) ? '' : 'readonly';
$placeholder = isset($args['placeholder']) ? $args['placeholder'] : '';
$value = isset($args['value']) ? $args['value'] : '';
$id = 'js' . $name;
if (isset($args['id'])) {
$id = $args['id'];
}
$tip = '';
if (isset($args['tip'])) {
$tip = '<small class="form-text text-muted">' . $args['tip'] . '</small>';
}
$label = '';
if (isset($args['label'])) {
$label = '<label for="' . $id . '" class="col-sm-2 col-form-label">' . $args['label'] . '</label>';
}
$class = 'form-control';
if (isset($args['class'])) {
$class = $class . ' ' . $args['class'];
}
$type = 'text';
if (isset($args['type'])) {
$type = $args['type'];
}
return <<<EOF
<div class="form-group row">
$label
<div class="col-sm-10">
<input class="$class" id="$id" name="$name" value="$value" placeholder="$placeholder" type="$type" dir="auto" $disabled $readonly>
$tip
</div>
</div>
EOF;
}
public static function formCheckbox($args)
{
$labelForCheckbox = isset($args['labelForCheckbox']) ? $args['labelForCheckbox'] : '';
$placeholder = isset($args['placeholder']) ? $args['placeholder'] : '';
$tip = isset($args['tip']) ? '<small class="form-text text-muted">' . $args['tip'] . '</small>' : '';
$value = isset($args['value']) ? $args['value'] : '';
$name = $args['name'];
$id = 'js' . $name;
if (isset($args['id'])) {
$id = $args['id'];
}
$disabled = isset($args['disabled']) ? 'disabled' : '';
$class = 'form-group m-0';
if (isset($args['class'])) {
$class = $args['class'];
}
$labelClass = 'mt-4 mb-2 pb-2 border-bottom text-uppercase w-100';
if (isset($args['labelClass'])) {
$labelClass = $args['labelClass'];
}
$type = 'text';
if (isset($args['type'])) {
$type = $args['type'];
}
$label = '';
if (!empty($args['label'])) {
$label = '<label class="' . $labelClass . '">' . $args['label'] . '</label>';
}
$checked = $args['checked'] ? 'checked' : '';
$value = $checked ? '1' : '0';
return <<<EOF
<div class="$class">
$label
<div class="form-check">
<input type="hidden" name="$name" value="$value"><input id="$id" type="checkbox" class="form-check-input" onclick="this.previousSibling.value=1-this.previousSibling.value" $checked>
<label class="form-check-label" for="$id">$labelForCheckbox</label>
$tip
</div>
</div>
EOF;
}
public static function formSelect($args)
{
$id = 'js' . $args['name'];
if (isset($args['id'])) {
$id = $args['id'];
}
$class = 'custom-select';
if (isset($args['class'])) {
$class = $class . ' ' . $args['class'];
}
$html = '<div class="form-group row">';
if (isset($args['label'])) {
$html .= '<label for="' . $id . '" class="col-sm-2 col-form-label">' . $args['label'] . '</label>';
}
$html .= '<div class="col-sm-10">';
$html .= '<select id="' . $id . '" name="' . $args['name'] . '" class="' . $class . '">';
foreach ($args['options'] as $key => $value) {
$html .= '<option ' . (($key == $args['selected']) ? 'selected' : '') . ' value="' . $key . '">' . $value . '</option>';
}
$html .= '</select>';
if (isset($args['tip'])) {
$html .= '<small class="form-text text-muted">' . $args['tip'] . '</small>';
}
$html .= '</div>';
$html .= '</div>';
return $html;
}
public static function formSelectBlock($args)
{
$id = 'js' . $args['name'];
if (isset($args['id'])) {
$id = $args['id'];
}
$class = 'custom-select';
if (!empty($args['class'])) {
$class = $class . ' ' . $args['class'];
}
$html = '<div class="form-group m-0">';
if (!empty($args['label'])) {
$html .= '<label class="mt-4 mb-2 pb-2 border-bottom text-uppercase w-100" for="' . $id . '">' . $args['label'] . '</label>';
}
$html .= '<select id="' . $id . '" name="' . $args['name'] . '" class="' . $class . '">';
if (!empty($args['emptyOption'])) {
$html .= '<option value="">' . $args['emptyOption'] . '</option>';
}
foreach ($args['options'] as $key => $value) {
$html .= '<option ' . (($key == $args['selected']) ? 'selected' : '') . ' value="' . $key . '">' . $value . '</option>';
}
$html .= '</select>';
if (!empty($args['tip'])) {
$html .= '<small class="form-text text-muted">' . $args['tip'] . '</small>';
}
$html .= '</div>';
return $html;
}
public static function formInputHidden($args)
{
return '<input type="hidden" id="js' . $args['name'] . '" name="' . $args['name'] . '" value="' . $args['value'] . '">';
}
public static function alert($args)
{
$class = 'alert';
if (!empty($args['class'])) {
$class = $class . ' ' . $args['class'];
}
$text = $args['text'];
return <<<EOF
<div class="$class" role="alert">$text</div>
EOF;
}
// This theme use the API to work
if (!pluginActivated('pluginAPI')) {
activatePlugin('pluginAPI');
}
$plugins['all']['pluginAPI']->newToken();

View file

@ -1,57 +1,63 @@
<!DOCTYPE html>
<html>
<html class="h-100">
<head>
<title>Bludit</title>
<meta charset="<?php echo CHARSET ?>">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="robots" content="noindex,nofollow">
<title><?php echo $layout['title'] ?></title>
<meta charset="<?php echo CHARSET ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<meta name="generator" content="Bludit">
<!-- Favicon -->
<link rel="shortcut icon" type="image/x-icon" href="<?php echo HTML_PATH_CORE_IMG . 'favicon.png?version=' . BLUDIT_VERSION ?>">
<!-- Favicon -->
<link rel="shortcut icon" type="image/x-icon" href="<?php echo HTML_PATH_CORE_IMG . 'favicon.png?version=' . BLUDIT_VERSION ?>">
<!-- CSS -->
<?php
echo Theme::cssBootstrap();
echo Theme::css(array(
'bludit.css',
'bludit.bootstrap.css'
), DOMAIN_ADMIN_THEME_CSS);
?>
<!-- CSS -->
<?php
echo HTML::cssBootstrap();
echo HTML::cssBootstrapIcons();
echo HTML::css(array(
'01-bludit.css',
'02-bootstrap-hacks.css'
), DOMAIN_ADMIN_THEME_CSS);
<!-- Javascript -->
<?php
echo Theme::jquery();
echo Theme::jsBootstrap();
?>
if ($site->darkModeAdmin()) {
echo HTML::css(array(
'99-darkmode.css'
), DOMAIN_ADMIN_THEME_CSS);
} else {
echo HTML::css(array(
'99-lightmode.css'
), DOMAIN_ADMIN_THEME_CSS);
}
?>
<!-- Plugins -->
<?php Theme::plugins('loginHead') ?>
<!-- Javascript -->
<?php
echo HTML::jquery();
echo HTML::jsBootstrap();
?>
<!-- Execute plugins for the login page inside the HTML <head> tag -->
<?php execPluginsByHook('loginHead') ?>
</head>
<body class="h-100 bg-light">
<body class="login">
<!-- Execute plugins for the login page inside the HTML <body> at the begginig -->
<?php execPluginsByHook('loginBodyBegin') ?>
<!-- Plugins -->
<?php Theme::plugins('loginBodyBegin') ?>
<div class="container h-100">
<div class="row h-100 justify-content-center align-items-center">
<div class="col-8 col-md-6 col-lg-4">
<?php
if (Sanitize::pathFile(PATH_ADMIN_VIEWS.$layout['view'].'.php')) {
include(PATH_ADMIN_VIEWS.$layout['view'].'.php');
}
?>
</div>
</div>
</div>
<!-- Alert -->
<?php include('html/alert.php'); ?>
<div class="container">
<div class="row justify-content-md-center pt-5">
<div class="col-md-4 mt-5 p-5 shadow-sm bg-white rounded border">
<?php
if (Sanitize::pathFile(PATH_ADMIN_VIEWS, $layout['view'] . '.php')) {
include(PATH_ADMIN_VIEWS . $layout['view'] . '.php');
}
?>
</div>
</div>
</div>
<!-- Plugins -->
<?php Theme::plugins('loginBodyEnd') ?>
<!-- Execute plugins for the login page inside the HTML <body> at the end -->
<?php execPluginsByHook('loginBodyEnd') ?>
</body>
</html>
</html>

View file

@ -1,3 +1,29 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// No events for the view yet
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('About'), 'icon'=>'info-circle'));
@ -8,37 +34,37 @@ echo '
';
echo '<tr>';
echo '<td>Bludit Edition</td>';
echo '<td class="pt-4 pb-4">Bludit Edition</td>';
if (defined('BLUDIT_PRO')) {
echo '<td>PRO - '.$L->g('Thanks for supporting Bludit').' <span class="fa fa-heart" style="color: #ffc107"></span></td>';
echo '<td class="pt-4 pb-4">PRO - '.$L->g('Thanks for supporting Bludit').' <span class="bi-heart" style="color: #ffc107"></span></td>';
} else {
echo '<td>Standard - <a target="_blank" href="https://pro.bludit.com">'.$L->g('Upgrade to Bludit PRO').'</a></td>';
echo '<td class="pt-4 pb-4">Standard - <a target="_blank" href="https://pro.bludit.com">'.$L->g('Upgrade to Bludit PRO').'</a></td>';
}
echo '</tr>';
echo '<tr>';
echo '<td>Bludit Version</td>';
echo '<td>'.BLUDIT_VERSION.'</td>';
echo '<td class="pt-4 pb-4">Bludit Version</td>';
echo '<td class="pt-4 pb-4">'.BLUDIT_VERSION.'</td>';
echo '</tr>';
echo '<tr>';
echo '<td>Bludit Codename</td>';
echo '<td>'.BLUDIT_CODENAME.'</td>';
echo '<td class="pt-4 pb-4">Bludit Codename</td>';
echo '<td class="pt-4 pb-4">'.BLUDIT_CODENAME.'</td>';
echo '</tr>';
echo '<tr>';
echo '<td>Bludit Build Number</td>';
echo '<td>'.BLUDIT_BUILD.'</td>';
echo '<td class="pt-4 pb-4">Bludit Build Number</td>';
echo '<td class="pt-4 pb-4">'.BLUDIT_BUILD.'</td>';
echo '</tr>';
echo '<tr>';
echo '<td>Disk usage</td>';
echo '<td>'.Filesystem::bytesToHumanFileSize(Filesystem::getSize(PATH_ROOT)).'</td>';
echo '<td class="pt-4 pb-4">Disk usage</td>';
echo '<td class="pt-4 pb-4">'.Filesystem::bytesToHumanFileSize(Filesystem::getSize(PATH_ROOT)).'</td>';
echo '</tr>';
echo '<tr>';
echo '<td><a href="'.HTML_PATH_ADMIN_ROOT.'developers'.'">Bludit Developers</a></td>';
echo '<td></td>';
echo '<td class="pt-4 pb-4"><a href="'.HTML_PATH_ADMIN_ROOT.'developers'.'">Bludit Developers</a></td>';
echo '<td class="pt-4 pb-4"></td>';
echo '</tr>';
echo '

View file

@ -0,0 +1,74 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
$('#btnSave').on('click', function() {
var name = $('#name').val();
if (name.length < 1) {
showAlertError("<?php $L->p('Complete all fields') ?>");
return false;
}
var args = {
name: name,
description: $('#description').val()
};
api.createCategory(args).then(function(response) {
if (response.status == 0) {
logs('Category created. Key: ' + response.data.key);
window.location.replace('<?php echo HTML_PATH_ADMIN_ROOT . 'categories' ?>');
} else {
logs("An error occurred while trying to create the category.");
showAlertError(response.message);
}
});
return true;
});
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-bookmark"></i><?php $L->p('New category') ?></h2>
<div class="ms-auto">
<button id="btnSave" type="button" class="btn btn-primary btn-sm"><?php $L->p('Save') ?></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>
</div>
<?php
echo Bootstrap::formInputText(array(
'id' => 'name',
'name' => 'name',
'label' => $L->g('Name'),
'value' => isset($_POST['category']) ? $_POST['category'] : ''
));
echo Bootstrap::formTextarea(array(
'id' => 'description',
'name' => 'description',
'label' => $L->g('Description'),
'value' => isset($_POST['description']) ? $_POST['description'] : '',
'rows' => 5
));
?>

View file

@ -0,0 +1,112 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
$('#btnSave').on('click', function() {
var username = $('#username').val();
var password = $('#password').val();
var confirmPassword = $('#confirmPassword').val();
if (username.length < 1) {
showAlertError("<?php $L->p('Complete all fields') ?>");
return false;
}
if (password.length < PASSWORD_LENGTH) {
showAlertError("<?php $L->p('Password must be at least 6 characters long') ?>");
return false;
}
if (password !== confirmPassword) {
showAlertError("<?php $L->p('The password and confirmation password do not match') ?>");
return false;
}
var args = {
username: username,
password: password,
role: $('#role').val(),
email: $('#email').val()
};
api.createUser(args).then(function(response) {
if (response.status == 0) {
logs('User created. Username: ' + response.data.username);
window.location.replace(HTML_PATH_ADMIN_ROOT + 'users');
} else {
logs('An error occurred while trying to create the user.');
showAlertError(response.message);
}
});
return true;
});
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-person"></i><?php $L->p('New user') ?></h2>
<div class="ms-auto">
<button id="btnSave" type="button" class="btn btn-primary btn-sm"><?php $L->p('Save') ?></button>
<a id="btnCancel" class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'users' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
</div>
<?php
echo Bootstrap::formInputText(array(
'id' => 'username',
'name' => 'username',
'label' => $L->g('Username'),
'value' => ''
));
echo Bootstrap::formInputText(array(
'id' => 'password',
'name' => 'password',
'type' => 'password',
'label' => $L->g('Password'),
'value' => ''
));
echo Bootstrap::formInputText(array(
'id' => 'confirmPassword',
'name' => 'confirmPassword',
'type' => 'password',
'label' => $L->g('Confirm Password'),
'value' => ''
));
echo Bootstrap::formSelect(array(
'name' => 'role',
'label' => $L->g('Role'),
'options' => array('author' => $L->g('Author'), 'editor' => $L->g('Editor'), 'admin' => $L->g('Administrator')),
'selected' => 'Author',
'tip' => $L->g('author-can-write-and-edit-their-own-content')
));
echo Bootstrap::formInputText(array(
'id' => 'email',
'name' => 'email',
'type' => 'email',
'label' => $L->g('Email'),
'value' => ''
));
?>

View file

@ -1,59 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'themes' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Blocks'), 'icon'=>'box')); ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
foreach ($blocks->getAll() as $block) {
echo Bootstrap::formTitle(array('title'=>$block->title()));
if (Text::isNotEmpty( $block->description() )) {
echo Bootstrap::alert(array('class'=>'alert-primary', 'text'=>$block->description()));
}
echo Bootstrap::formInputText(array(
'name'=>'key[]',
'label'=>$L->g('Key'),
'value'=>$block->key(),
'class'=>'',
'placeholder'=>'',
'tip'=>'',
'readonly'=>true
));
echo Bootstrap::formInputText(array(
'name'=>'title[]',
'label'=>$L->g('title'),
'value'=>$block->title(),
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formTextarea(array(
'name'=>'value[]',
'label'=>$L->g('Value'),
'value'=>$block->value(),
'class'=>'',
'placeholder'=>'',
'tip'=>'',
'rows'=>5
));
}
echo Bootstrap::formClose();
?>

View file

@ -1,18 +1,44 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
echo Bootstrap::pageTitle(array('title'=>$L->g('Categories'), 'icon'=>'tags'));
<script>
// ============================================================================
// Variables for the view
// ============================================================================
echo Bootstrap::link(array(
'title'=>$L->g('Add a new category'),
'href'=>HTML_PATH_ADMIN_ROOT.'new-category',
'icon'=>'plus'
));
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// No events for the view yet
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-bookmark"></i><?php $L->p('Categories') ?></h2>
<div class="ms-auto">
<a id="btnNew" class="btn btn-primary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'add-category' ?>" role="button"><i class="bi bi-plus-circle"></i><?php $L->p('Add a new category') ?></a>
</div>
</div>
<?php
echo '
<table class="table table-striped mt-3">
<thead>
<tr>
<th class="border-bottom-0" scope="col">'.$L->g('Name').'</th>
<th class="border-bottom-0" scope="col">'.$L->g('Description').'</th>
<th class="border-bottom-0" scope="col">'.$L->g('URL').'</th>
</tr>
</thead>
@ -20,14 +46,19 @@ echo '
';
foreach ($categories->keys() as $key) {
$category = new Category($key);
echo '<tr>';
echo '<td><a href="'.HTML_PATH_ADMIN_ROOT.'edit-category/'.$key.'">'.$category->name().'</a></td>';
echo '<td><a href="'.$category->permalink().'">'.$url->filters('category', false).$key.'</a></td>';
echo '</tr>';
try {
$category = new Category($key);
echo '<tr>';
echo '<td class="pt-4 pb-4"><a href="'.HTML_PATH_ADMIN_ROOT.'edit-category/'.$key.'">'.$category->name().'</a></td>';
echo '<td class="pt-4 pb-4"><span>'.$category->description().'</span></td>';
echo '<td class="pt-4 pb-4"><a href="'.$category->permalink().'">'.$category->permalink().'</a></td>';
echo '</tr>';
} catch (Exception $e) {
// Continue
}
}
echo '
</tbody>
</table>
';
';

View file

@ -1,26 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'plugin-form')); ?>
<div class="align-middle">
<?php if ($plugin->formButtons()): ?>
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php endif; ?>
<?php echo Bootstrap::pageTitle(array('title'=>$plugin->name(), 'icon'=>'cog')); ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
// Print the plugin form
echo $plugin->form();
?>
<?php echo Bootstrap::formClose(); ?>

View file

@ -1,8 +1,64 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
$(".btnDeletePage").on("click", function() {
var key = $(this).data('key');
logs('Deleting page. Key: ' + key);
bootbox.confirm({
message: '<?php $L->p('Are you sure you want to delete this page') ?>',
buttons: {
cancel: {
label: '<i class="fa fa-times"></i><?php $L->p('Cancel') ?>',
className: 'btn-sm btn-secondary'
},
confirm: {
label: '<i class="fa fa-check"></i><?php $L->p('Confirm') ?>',
className: 'btn-sm btn-primary'
}
},
closeButton: false,
callback: function(result) {
if (result) {
// delete page
}
}
});
});
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-folder"></i><?php $L->p('Content') ?></h2>
<div class="ms-auto">
<a id="btnNew" class="btn btn-primary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'editor' ?>" role="button"><i class="bi bi-plus-circle"></i><?php $L->p('Add a new page') ?></a>
</div>
</div>
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('Content'), 'icon'=>'archive'));
function table($type) {
function table($type)
{
global $url;
global $L;
global $published;
@ -10,130 +66,100 @@ function table($type) {
global $scheduled;
global $static;
global $sticky;
global $autosave;
if ($type=='published') {
if ($type == 'published') {
$list = $published;
if (empty($list)) {
echo '<p class="mt-4 text-muted">';
echo '<p class="text-muted p-4">';
echo $L->g('There are no pages at this moment.');
echo '</p>';
return false;
}
} elseif ($type=='draft') {
} elseif ($type == 'draft') {
$list = $drafts;
if (empty($list)) {
echo '<p class="mt-4 text-muted">';
echo '<p class="text-muted p-4">';
echo $L->g('There are no draft pages at this moment.');
echo '</p>';
return false;
}
} elseif ($type=='scheduled') {
} elseif ($type == 'scheduled') {
$list = $scheduled;
if (empty($list)) {
echo '<p class="mt-4 text-muted">';
echo '<p class="text-muted p-4">';
echo $L->g('There are no scheduled pages at this moment.');
echo '</p>';
return false;
}
} elseif ($type=='static') {
} elseif ($type == 'static') {
$list = $static;
if (empty($list)) {
echo '<p class="mt-4 text-muted">';
echo '<p class="text-muted p-4">';
echo $L->g('There are no static pages at this moment.');
echo '</p>';
return false;
}
} elseif ($type=='sticky') {
} elseif ($type == 'sticky') {
$list = $sticky;
if (empty($list)) {
echo '<p class="mt-4 text-muted">';
echo '<p class="text-muted p-4">';
echo $L->g('There are no sticky pages at this moment.');
echo '</p>';
return false;
}
} elseif ($type=='autosave') {
$list = $autosave;
}
echo '
<table class="table mt-3">
<thead>
<tr>
<th class="border-0" scope="col">'.$L->g('Title').'</th>
';
echo '<table class="table table-striped"><tbody><tr></tr>';
if ($type=='published' || $type=='static' || $type=='sticky') {
echo '<th class="border-0 d-none d-lg-table-cell" scope="col">'.$L->g('URL').'</th>';
}
echo ' <th class="border-0 text-center d-sm-table-cell" scope="col">'.$L->g('Actions').'</th>
</tr>
</thead>
<tbody>
';
if ( (ORDER_BY=='position') || $type=='static' ) {
if ((ORDER_BY == 'position') || $type == 'static') {
foreach ($list as $pageKey) {
try {
$page = new Page($pageKey);
if (!$page->isChild()) {
echo '<tr>
<td>
<div>
<a style="font-size: 1.1em" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$page->key().'">'
.($page->title()?$page->title():'<span class="label-empty-title">'.$L->g('Empty title').'</span> ')
.'</a>
</div>
<div>
<p style="font-size: 0.8em" class="m-0 text-uppercase text-muted">'.( ((ORDER_BY=='position') || ($type!='published'))?$L->g('Position').': '.$page->position():$page->date(MANAGE_CONTENT_DATE_FORMAT) ).'</p>
</div>
echo '<tr>';
echo '<td class="pt-4 pb-4">
<div>
<span>' . ($page->title() ? $page->title() : '<span class="text-muted">' . $L->g('Empty title') . '</span> ') . '</span>
</div>
<div class="mt-1">
<a class="me-2" target="_blank" href="' . $page->permalink() . '">' . $L->g('View') . '</a>
<a class="me-2" href="' . HTML_PATH_ADMIN_ROOT . 'editor/' . $page->key() . '">' . $L->g('Edit') . '</a>
';
if (count($page->children()) == 0) {
echo '<span class="link btnDeletePage" data-key="' . $page->key() . '">Delete</span>';
}
echo '
</div>
</td>';
if ($type=='published' || $type=='static' || $type=='sticky') {
$friendlyURL = Text::isEmpty($url->filters('page')) ? '/'.$page->key() : '/'.$url->filters('page').'/'.$page->key();
echo '<td class="d-none d-lg-table-cell"><a target="_blank" href="'.$page->permalink().'">'.$friendlyURL.'</a></td>';
}
echo '<td class="pt-4 pb-4 d-none d-lg-table-cell">' . $L->get('Category') . ': ' . ($page->category() ? $page->category() : $L->get('uncategorized')) . '</td>';
echo '<td class="contentTools pt-3 text-center d-sm-table-cell">'.PHP_EOL;
echo '<a class="text-secondary d-none d-md-inline" target="_blank" href="'.$page->permalink().'"><i class="fa fa-desktop"></i>'.$L->g('View').'</a>'.PHP_EOL;
echo '<a class="text-secondary d-none d-md-inline ml-2" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$page->key().'"><i class="fa fa-edit"></i>'.$L->g('Edit').'</a>'.PHP_EOL;
if (count($page->children())==0) {
echo '<a href="#" class="ml-2 text-danger deletePageButton d-block d-sm-inline" data-toggle="modal" data-target="#jsdeletePageModal" data-key="'.$page->key().'"><i class="fa fa-trash"></i>'.$L->g('Delete').'</a>'.PHP_EOL;
}
echo '</td>';
echo '<td class="pt-4 text-center d-sm-table-cell">' . (((ORDER_BY == 'position') || ($type != 'published')) ? $L->g('Position') . ': ' . $page->position() : $page->date(MANAGE_CONTENT_DATE_FORMAT)) . '</td>';
echo '</tr>';
foreach ($page->children() as $child) {
//if ($child->published()) {
echo '<tr>
<td class="child">
<div>
<a style="font-size: 1.1em" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$child->key().'">'
.($child->title()?$child->title():'<span class="label-empty-title">'.$L->g('Empty title').'</span> ')
.'</a>
</div>
<div>
<p style="font-size: 0.8em" class="m-0 text-uppercase text-muted">'.( ((ORDER_BY=='position') || ($type!='published'))?$L->g('Position').': '.$child->position():$child->date(MANAGE_CONTENT_DATE_FORMAT) ).'</p>
</div>
echo '<tr>';
echo '<td class="ps-3 pt-4 pb-4">
<div>
<span>' . ($child->title() ? $child->title() : '<span class="text-muted">' . $L->g('Empty title') . '</span> ') . '</span>
</div>
<div class="mt-1">
<a class="me-2" target="_blank" href="' . $child->permalink() . '">' . $L->g('View') . '</a>
<a class="me-2" href="' . HTML_PATH_ADMIN_ROOT . 'editor/' . $child->key() . '">' . $L->g('Edit') . '</a>
<span class="link btnDeletePage" data-key="' . $child->key() . '">Delete</span>
</div>
</td>';
if ($type=='published' || $type=='static' || $type=='sticky') {
$friendlyURL = Text::isEmpty($url->filters('page')) ? '/'.$child->key() : '/'.$url->filters('page').'/'.$child->key();
echo '<td class="d-none d-lg-table-cell"><a target="_blank" href="'.$child->permalink().'">'.$friendlyURL.'</a></td>';
}
echo '<td class="pt-4 d-none d-lg-table-cell">' . $L->get('Category') . ': ' . ($child->category() ? $child->category() : $L->get('uncategorized')) . '</td>';
echo '<td class="contentTools pt-3 text-center d-sm-table-cell">'.PHP_EOL;
if ($type=='published' || $type=='static' || $type=='sticky') {
echo '<a class="text-secondary d-none d-md-inline" target="_blank" href="'.$child->permalink().'"><i class="fa fa-desktop"></i>'.$L->g('View').'</a>'.PHP_EOL;
}
echo '<a class="text-secondary d-none d-md-inline ml-2" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$child->key().'"><i class="fa fa-edit"></i>'.$L->g('Edit').'</a>'.PHP_EOL;
echo '<a class="ml-2 text-danger deletePageButton d-block d-sm-inline" href="#" data-toggle="modal" data-target="#jsdeletePageModal" data-key="'.$child->key().'"><i class="fa fa-trash"></i>'.$L->g('Delete').'</a>'.PHP_EOL;
echo '</td>';
echo '<td class="pt-4 text-center d-sm-table-cell">' . (((ORDER_BY == 'position') || ($type != 'published')) ? $L->g('Position') . ': ' . $child->position() : $child->date(MANAGE_CONTENT_DATE_FORMAT)) . '</td>';
echo '</tr>';
//}
}
}
} catch (Exception $e) {
@ -145,31 +171,21 @@ function table($type) {
try {
$page = new Page($pageKey);
echo '<tr>';
echo '<td class="pt-3">
echo '<td class="pt-4 pb-4">
<div>
<a style="font-size: 1.1em" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$page->key().'">'
.($page->title()?$page->title():'<span class="label-empty-title">'.$L->g('Empty title').'</span> ')
.'</a>
' . ($page->title() ? $page->title() : '<span class="text-muted">' . $L->g('Empty title') . '</span> ') . '
</div>
<div>
<p style="font-size: 0.8em" class="m-0 text-uppercase text-muted">'.( ($type=='scheduled')?$L->g('Scheduled').': '.$page->date(SCHEDULED_DATE_FORMAT):$page->date(MANAGE_CONTENT_DATE_FORMAT) ).'</p>
<div class="mt-1">
<a class="me-2" target="_blank" href="' . $page->permalink() . '">' . $L->g('View') . '</a>
<a class="me-2" href="' . HTML_PATH_ADMIN_ROOT . 'editor/' . $page->key() . '">' . $L->g('Edit') . '</a>
<span class="link btnDeletePage" data-key="' . $page->key() . '">Delete</span>
</div>
</td>';
if ($type=='published' || $type=='static' || $type=='sticky') {
$friendlyURL = Text::isEmpty($url->filters('page')) ? '/'.$page->key() : '/'.$url->filters('page').'/'.$page->key();
echo '<td class="pt-3 d-none d-lg-table-cell"><a target="_blank" href="'.$page->permalink().'">'.$friendlyURL.'</a></td>';
}
echo '<td class="pt-4 d-none d-lg-table-cell">' . $L->get('Category') . ': ' . ($page->category() ? $page->category() : $L->get('uncategorized')) . '</td>';
echo '<td class="contentTools pt-3 text-center d-sm-table-cell">'.PHP_EOL;
if ($type=='published' || $type=='static' || $type=='sticky') {
echo '<a class="text-secondary d-none d-md-inline" target="_blank" href="'.$page->permalink().'"><i class="fa fa-desktop"></i>'.$L->g('View').'</a>'.PHP_EOL;
}
echo '<a class="text-secondary d-none d-md-inline ml-2" href="'.HTML_PATH_ADMIN_ROOT.'edit-content/'.$page->key().'"><i class="fa fa-edit"></i>'.$L->g('Edit').'</a>'.PHP_EOL;
if (count($page->children())==0) {
echo '<a href="#" class="ml-2 text-danger deletePageButton d-block d-sm-inline" data-toggle="modal" data-target="#jsdeletePageModal" data-key="'.$page->key().'"><i class="fa fa-trash"></i>'.$L->g('Delete').'</a>'.PHP_EOL;
}
echo '</td>';
echo '<td class="pt-4 text-center d-sm-table-cell"> ' . (((ORDER_BY == 'position') || ($type != 'published')) ? $L->g('Position') . ': ' . $page->position() : $page->date(MANAGE_CONTENT_DATE_FORMAT)) . '</td>';
echo '</tr>';
} catch (Exception $e) {
@ -186,142 +202,88 @@ function table($type) {
?>
<!-- TABS -->
<ul class="nav nav-tabs" role="tablist">
<!-- Tabs -->
<ul class="nav nav-tabs ps-3" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pages-tab" data-toggle="tab" href="#pages" role="tab"><?php $L->p('Pages') ?></a>
<a class="nav-link active" id="pages-tab" data-bs-toggle="tab" href="#pages" role="tab" aria-controls="pages" aria-selected="true"><?php $L->p('Pages') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="static-tab" data-toggle="tab" href="#static" role="tab"><?php $L->p('Static') ?></a>
<a class="nav-link" id="static-tab" data-bs-toggle="tab" href="#static" role="tab" aria-controls="static" aria-selected="true"><?php $L->p('Static') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="sticky-tab" data-toggle="tab" href="#sticky" role="tab"><?php $L->p('Sticky') ?></a>
<a class="nav-link" id="sticky-tab" data-bs-toggle="tab" href="#sticky" role="tab" aria-controls="sticky" aria-selected="true"><?php $L->p('Sticky') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="scheduled-tab" data-toggle="tab" href="#scheduled" role="tab"><?php $L->p('Scheduled') ?> <?php if (count($scheduled)>0) { echo '<span class="badge badge-danger">'.count($scheduled).'</span>'; } ?></a>
<a class="nav-link" id="scheduled-tab" data-bs-toggle="tab" href="#scheduled" role="tab" aria-controls="scheduled" aria-selected="true"><?php $L->p('Scheduled') ?>
<?php if (count($scheduled) > 0) {
echo '<span class="badge badge-danger">' . count($scheduled) . '</span>';
} ?>
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="draft-tab" data-toggle="tab" href="#draft" role="tab"><?php $L->p('Draft') ?></a>
<a class="nav-link" id="draft-tab" data-bs-toggle="tab" href="#draft" role="tab" aria-controls="draft" aria-selected="true"><?php $L->p('Draft') ?></a>
</li>
<?php if (!empty($autosave)): ?>
<li class="nav-item">
<a class="nav-link" id="autosave-tab" data-toggle="tab" href="#autosave" role="tab"><?php $L->p('Autosave') ?></a>
</li>
<?php endif; ?>
</ul>
<div class="tab-content">
<!-- TABS PAGES -->
<div class="tab-pane show active" id="pages" role="tabpanel">
<!-- End Tabs -->
<!-- Content -->
<div class="tab-content">
<!-- Tab pages -->
<div class="tab-pane show active" id="pages" role="tabpanel">
<?php table('published'); ?>
<?php if (Paginator::numberOfPages() > 1): ?>
<!-- Paginator -->
<nav class="paginator">
<ul class="pagination flex-wrap justify-content-center">
<!-- The paginator is defined in the rule 99.paginator.php for the admin area -->
<?php if (Paginator::numberOfPages() > 1) : ?>
<nav class="mt-4 mb-4">
<ul class="pagination flex-wrap justify-content-center">
<!-- First button -->
<li class="page-item <?php if (!Paginator::showPrev()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::firstPageUrl() ?>"><i class="bi bi-arrow-left-circle"></i><?php echo $L->get('First'); ?></a>
</li>
<!-- First button -->
<li class="page-item <?php if (!Paginator::showPrev()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::firstPageUrl() ?>"><span class="align-middle fa fa-media-skip-backward"></span> <?php echo $L->get('First'); ?></a>
</li>
<!-- Previous button -->
<li class="page-item <?php if (!Paginator::showPrev()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::previousPageUrl() ?>"><?php echo $L->get('Previous'); ?></a>
</li>
<!-- Previous button -->
<li class="page-item <?php if (!Paginator::showPrev()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::previousPageUrl() ?>"><?php echo $L->get('Previous'); ?></a>
</li>
<li class="page-item"><span class="page-link text-muted"><?php echo Paginator::currentPage() ?> / <?php echo Paginator::numberOfPages() ?></span></li>
<!-- Next button -->
<li class="page-item <?php if (!Paginator::showNext()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::nextPageUrl() ?>"><?php echo $L->get('Next'); ?></a>
</li>
<!-- Next button -->
<li class="page-item <?php if (!Paginator::showNext()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::nextPageUrl() ?>"><?php echo $L->get('Next'); ?></a>
</li>
<!-- Last button -->
<li class="page-item <?php if (!Paginator::showNext()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::lastPageUrl() ?>"><?php echo $L->get('Last'); ?> <span class="align-middle fa fa-media-skip-forward"></span></a>
</li>
</ul>
</nav>
<!-- Last button -->
<li class="page-item <?php if (!Paginator::showNext()) echo 'disabled' ?>">
<a class="page-link" href="<?php echo Paginator::lastPageUrl() ?>"><?php echo $L->get('Last'); ?><i class="ms-2 bi bi-arrow-right-circle"></i></a>
</li>
</ul>
</nav>
<?php endif; ?>
<!-- End Paginator -->
</div>
<!-- End Tab pages -->
<!-- TABS STATIC -->
<div class="tab-pane" id="static" role="tabpanel">
<?php table('static'); ?>
<?php table('static'); ?>
</div>
<!-- TABS STICKY -->
<div class="tab-pane" id="sticky" role="tabpanel">
<?php table('sticky'); ?>
<?php table('sticky'); ?>
</div>
<!-- TABS SCHEDULED -->
<div class="tab-pane" id="scheduled" role="tabpanel">
<?php table('scheduled'); ?>
<?php table('scheduled'); ?>
</div>
<!-- TABS DRAFT -->
<div class="tab-pane" id="draft" role="tabpanel">
<?php table('draft'); ?>
<?php table('draft'); ?>
</div>
<!-- TABS AUTOSAVE -->
<?php if (!empty($autosave)): ?>
<div class="tab-pane" id="autosave" role="tabpanel">
<?php table('autosave'); ?>
</div>
<?php endif; ?>
</div>
<!-- Modal for delete page -->
<?php
echo Bootstrap::modal(array(
'buttonPrimary'=>$L->g('Delete'),
'buttonPrimaryClass'=>'btn-danger deletePageModalAcceptButton',
'buttonSecondary'=>$L->g('Cancel'),
'buttonSecondaryClass'=>'btn-link',
'modalTitle'=>$L->g('Delete content'),
'modalText'=>$L->g('Are you sure you want to delete this page'),
'modalId'=>'jsdeletePageModal'
));
?>
<script>
$(document).ready(function() {
var key = false;
// Button for delete a page in the table
$(".deletePageButton").on("click", function() {
key = $(this).data('key');
});
// Event from button accept from the modal
$(".deletePageModalAcceptButton").on("click", function() {
var form = jQuery('<form>', {
'action': HTML_PATH_ADMIN_ROOT+'edit-content/'+key,
'method': 'post',
'target': '_top'
}).append(jQuery('<input>', {
'type': 'hidden',
'name': 'tokenCSRF',
'value': tokenCSRF
}).append(jQuery('<input>', {
'type': 'hidden',
'name': 'key',
'value': key
}).append(jQuery('<input>', {
'type': 'hidden',
'name': 'type',
'value': 'delete'
}))));
form.hide().appendTo("body").submit();
});
});
</script>
<script>
// Open the tab defined in the URL
const anchor = window.location.hash;
$(`a[href="${anchor}"]`).tab('show');
</script>
<!-- End Content -->

View file

@ -1,140 +1,62 @@
<div id="dashboard" class="container">
<div class="row">
<div class="col-md-7">
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<!-- Good message -->
<div>
<h2 id="hello-message" class="pt-0">
<?php
$username = $login->username();
$user = new User($username);
$name = '';
if ($user->nickname()) {
$name = $user->nickname();
} elseif ($user->firstName()) {
$name = $user->firstName();
}
?>
<span class="fa fa-hand-spock-o"></span><span><?php echo $L->g('welcome') ?></span>
</h2>
<script>
$(document).ready(function() {
$("#hello-message").fadeOut(2400, function() {
var date = new Date()
var hours = date.getHours()
if (hours >= 6 && hours < 12) {
$(this).html('<span class="fa fa-sun-o"></span><?php echo $L->g('good-morning') . ', ' . $name ?>');
} else if (hours >= 12 && hours < 18) {
$(this).html('<span class="fa fa-sun-o"></span><?php echo $L->g('good-afternoon') . ', ' . $name ?>');
} else if (hours >= 18 && hours < 22) {
$(this).html('<span class="fa fa-moon-o"></span><?php echo $L->g('good-evening') . ', ' . $name ?>');
} else {
$(this).html('<span class="fa fa-moon-o"></span><span><?php echo $L->g('good-night') . ', ' . $name ?></span>');
}
}).fadeIn(1000);
});
</script>
</div>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
<!-- Quick Links -->
<div class="container pb-5" id="jsclippyContainer">
// ============================================================================
// Functions for the view
// ============================================================================
<div class="row">
<div class="col p-0">
<div class="form-group">
<select id="jsclippy" class="clippy" name="state"></select>
</div>
</div>
</div>
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// No events for the view yet
});
<script>
$(document).ready(function() {
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
var clippy = $("#jsclippy").select2({
placeholder: "<?php $L->p('Start typing to see a list of suggestions') ?>",
allowClear: true,
width: "100%",
theme: "bootstrap4",
minimumInputLength: 2,
dropdownParent: "#jsclippyContainer",
language: {
inputTooShort: function() {
return '';
}
},
ajax: {
url: HTML_PATH_ADMIN_ROOT + "ajax/clippy",
data: function(params) {
var query = {
query: params.term
}
return query;
},
processResults: function(data) {
return data;
}
},
templateResult: function(data) {
// console.log(data);
var html = '';
if (data.type == 'menu') {
html += '<a href="' + data.url + '"><div class="search-suggestion">';
html += '<span class="fa fa-' + data.icon + '"></span>' + data.text + '</div></a>';
} else {
if (typeof data.id === 'undefined') {
return '';
}
html += '<div class="search-suggestion">';
html += '<div class="search-suggestion-item">' + data.text + ' <span class="badge badge-pill badge-light">' + data.type + '</span></div>';
html += '<div class="search-suggestion-options">';
html += '<a target="_blank" href="' + DOMAIN_PAGES + data.id + '"><?php $L->p('view') ?></a>';
html += '<a class="ml-2" href="' + DOMAIN_ADMIN + 'edit-content/' + data.id + '"><?php $L->p('edit') ?></a>';
html += '</div></div>';
}
<div id="dashboard" class="container-fluid">
<div class="row">
<div class="col-7">
<?php execPluginsByHook('dashboard') ?>
</div>
return html;
},
escapeMarkup: function(markup) {
return markup;
}
}).on("select2:closing", function(e) {
e.preventDefault();
}).on("select2:closed", function(e) {
clippy.select2("open");
});
clippy.select2("open");
<div class="col-5">
});
</script>
</div>
<!-- Notifications -->
<ul class="list-group">
<li class="list-group-item">
<h4 class="m-0 p-0"><i class="bi bi-bell"></i><?php $L->p('Notifications') ?></h4>
</li>
<?php
$logs = array_slice($syslog->db, 0, NOTIFICATIONS_AMOUNT);
foreach ($logs as $log) {
echo '<li class="list-group-item">';
echo '<div>';
echo $L->g($log['dictionaryKey']);
if (!empty($log['notes'])) {
echo ' « <b>'.$log['notes'].'</b> »';
}
echo '</div>';
echo '<div class="form-text">';
echo Date::format($log['date'], DB_DATE_FORMAT, NOTIFICATIONS_DATE_FORMAT);
echo ' [ '.$log['username'] .' ]';
echo '</div>';
echo '</li>';
}
?>
</ul>
<!-- End Notifications -->
<?php Theme::plugins('dashboard') ?>
</div>
<div class="col-md-5">
<!-- Notifications -->
<ul class="list-group list-group-striped b-0">
<li class="list-group-item pt-0">
<h4 class="m-0"><?php $L->p('Notifications') ?></h4>
</li>
<?php
$logs = array_slice($syslog->db, 0, NOTIFICATIONS_AMOUNT);
foreach ($logs as $log) {
$phrase = $L->g($log['dictionaryKey']);
echo '<li class="list-group-item">';
echo $phrase;
if (!empty($log['notes'])) {
echo ' « <b>' . $log['notes'] . '</b> »';
}
echo '<br><span class="notification-date"><small>';
echo Date::format($log['date'], DB_DATE_FORMAT, NOTIFICATIONS_DATE_FORMAT);
echo ' [ ' . $log['username'] . ' ]';
echo '</small></span>';
echo '</li>';
}
?>
</ul>
</div>
</div>
</div>
</div>
</div>

View file

@ -1,3 +1,29 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// No events for the view yet
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('Developers'), 'icon'=>'gears'));

View file

@ -1,92 +1,135 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform')); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
<div class="align-middle">
<div class="float-right 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>
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(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(response) {
if (response.status == 0) {
logs('Category edited. Key: ' + response.data.key);
showAlertInfo("<?php $L->p('The changes have been saved') ?>");
$('#key').val(response.data.key);
} else {
logs('An error occurred while trying to edit the category.');
showAlertError(response.message);
}
});
return true;
});
$('#btnDelete').on('click', function() {
var key = $('#key').val();
logs('Deleting category. Key: ' + key);
bootbox.confirm({
message: '<?php $L->p('Are you sure you want to delete this category') ?>',
buttons: {
cancel: {
label: '<i class="fa fa-times"></i><?php $L->p('Cancel') ?>',
className: 'btn-sm btn-secondary'
},
confirm: {
label: '<i class="fa fa-check"></i><?php $L->p('Confirm') ?>',
className: 'btn-sm btn-primary'
}
},
closeButton: false,
callback: function(result) {
if (result) {
var args = {
key: key
};
api.deleteCategory(args).then(function(response) {
if (response.status == 0) {
logs('Category deleted. Key: ' + response.data.key);
window.location.replace(HTML_PATH_ADMIN_ROOT + 'categories');
} else {
logs('An error occurred while trying to delete the category.');
showAlertError(response.message);
}
});
return true;
}
}
});
});
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<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();
});
});
</script>

View file

@ -1,563 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php
// FORM START
echo Bootstrap::formOpen(array(
'id' => 'jsform',
'class' => 'd-flex flex-column h-100'
));
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
// UUID
// The UUID is generated in the controller
echo Bootstrap::formInputHidden(array(
'name' => 'uuid',
'value' => $page->uuid()
));
// Type = published, draft, sticky, static
echo Bootstrap::formInputHidden(array(
'name' => 'type',
'value' => $page->type()
));
// Cover image
echo Bootstrap::formInputHidden(array(
'name' => 'coverImage',
'value' => $page->coverImage(false)
));
// Content
echo Bootstrap::formInputHidden(array(
'name' => 'content',
'value' => ''
));
// Current page key
echo Bootstrap::formInputHidden(array(
'name' => 'key',
'value' => $page->key()
));
?>
<!-- TOOLBAR -->
<div id="jseditorToolbar" class="mb-1">
<div id="jseditorToolbarRight" class="btn-group btn-group-sm float-right" role="group" aria-label="Toolbar right">
<button type="button" class="btn btn-light" id="jsmediaManagerOpenModal" data-toggle="modal" data-target="#jsmediaManagerModal"><span class="fa fa-image"></span> <?php $L->p('Images') ?></button>
<button type="button" class="btn btn-light" id="jsoptionsSidebar" style="z-index:30"><span class="fa fa-cog"></span> <?php $L->p('Options') ?></button>
</div>
<div id="jseditorToolbarLeft">
<button type="button" class="btn btn-sm btn-primary" id="jsbuttonSave"><?php echo $L->g('Save') ?></button>
<button id="jsbuttonPreview" type="button" class="btn btn-sm btn-secondary"><?php $L->p('Preview') ?></button>
<span id="jsswitchButton" data-switch="<?php echo ($page->draft() ? 'draft' : 'publish') ?>" class="ml-2 text-secondary switch-button"><i class="fa fa-square switch-icon-<?php echo ($page->draft() ? 'draft' : 'publish') ?>"></i> <?php echo ($page->draft() ? $L->g('Draft') : $L->g('Publish')) ?></span>
</div>
<?php if ($page->scheduled()) : ?>
<div class="alert alert-warning p-1 mt-1 mb-0"><?php $L->p('scheduled') ?>: <?php echo $page->date(SCHEDULED_DATE_FORMAT) ?></div>
<?php endif; ?>
</div>
<script>
$(document).ready(function() {
$("#jsoptionsSidebar").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
$("#jsshadow").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
});
</script>
<!-- SIDEBAR OPTIONS -->
<div id="jseditorSidebar">
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-link active show" id="nav-general-tab" data-toggle="tab" href="#nav-general" role="tab" aria-controls="general"><?php $L->p('General') ?></a>
<a class="nav-link" id="nav-advanced-tab" data-toggle="tab" href="#nav-advanced" role="tab" aria-controls="advanced"><?php $L->p('Advanced') ?></a>
<?php if (!empty($site->customFields())) : ?>
<a class="nav-link" id="nav-custom-tab" data-toggle="tab" href="#nav-custom" role="tab" aria-controls="custom"><?php $L->p('Custom') ?></a>
<?php endif ?>
<a class="nav-link" id="nav-seo-tab" data-toggle="tab" href="#nav-seo" role="tab" aria-controls="seo"><?php $L->p('SEO') ?></a>
</div>
</nav>
<div class="tab-content pr-3 pl-3 pb-3">
<div id="nav-general" class="tab-pane fade show active" role="tabpanel" aria-labelledby="general-tab">
<?php
// Category
echo Bootstrap::formSelectBlock(array(
'name' => 'category',
'label' => $L->g('Category'),
'selected' => $page->categoryKey(),
'class' => '',
'emptyOption' => '- ' . $L->g('Uncategorized') . ' -',
'options' => $categories->getKeyNameArray()
));
// Description
echo Bootstrap::formTextareaBlock(array(
'name' => 'description',
'label' => $L->g('Description'),
'selected' => '',
'class' => '',
'value' => $page->description(),
'rows' => 5,
'placeholder' => $L->get('this-field-can-help-describe-the-content')
));
?>
<!-- Cover Image -->
<?php
$coverImage = $page->coverImage(false);
$externalCoverImage = '';
if (filter_var($coverImage, FILTER_VALIDATE_URL)) {
$coverImage = '';
$externalCoverImage = $page->coverImage(false);
}
?>
<label class="mt-4 mb-2 pb-2 border-bottom text-uppercase w-100"><?php $L->p('Cover Image') ?></label>
<div>
<img id="jscoverImagePreview" class="mx-auto d-block w-100" alt="Cover image preview" src="<?php echo (empty($coverImage) ? HTML_PATH_CORE_IMG . 'default.svg' : $page->coverImage()) ?>" />
</div>
<div class="mt-2 text-center">
<button type="button" id="jsbuttonSelectCoverImage" class="btn btn-primary btn-sm"><?php echo $L->g('Select cover image') ?></button>
<button type="button" id="jsbuttonRemoveCoverImage" class="btn btn-secondary btn-sm"><?php echo $L->g('Remove cover image') ?></button>
</div>
<script>
$(document).ready(function() {
$("#jscoverImagePreview").on("click", function() {
openMediaManager();
});
$("#jsbuttonSelectCoverImage").on("click", function() {
openMediaManager();
});
$("#jsbuttonRemoveCoverImage").on("click", function() {
$("#jscoverImage").val('');
$("#jscoverImagePreview").attr('src', HTML_PATH_CORE_IMG + 'default.svg');
});
});
</script>
</div>
<div id="nav-advanced" class="tab-pane fade" role="tabpanel" aria-labelledby="advanced-tab">
<?php
// Date
echo Bootstrap::formInputTextBlock(array(
'name' => 'date',
'label' => $L->g('Date'),
'placeholder' => '',
'value' => $page->dateRaw(),
'tip' => $L->g('date-format-format')
));
// Type
echo Bootstrap::formSelectBlock(array(
'name' => 'typeSelector',
'label' => $L->g('Type'),
'selected' => $page->type(),
'options' => array(
'published' => '- ' . $L->g('Default') . ' -',
'sticky' => $L->g('Sticky'),
'static' => $L->g('Static')
),
'tip' => ''
));
// Position
echo Bootstrap::formInputTextBlock(array(
'name' => 'position',
'label' => $L->g('Position'),
'tip' => $L->g('Field used when ordering content by position'),
'value' => $page->position()
));
// Tags
echo Bootstrap::formInputTextBlock(array(
'name' => 'tags',
'label' => $L->g('Tags'),
'placeholder' => '',
'tip' => $L->g('Write the tags separated by comma'),
'value' => $page->tags()
));
// Parent
try {
$options = array();
$parentKey = $page->parent();
if (!empty($parentKey)) {
$parent = new Page($parentKey);
$options = array($parentKey => $parent->title());
}
} catch (Exception $e) {
// continue
}
echo Bootstrap::formSelectBlock(array(
'name' => 'parent',
'label' => $L->g('Parent'),
'options' => $options,
'selected' => false,
'class' => '',
'tip' => $L->g('Start typing a page title to see a list of suggestions.'),
));
?>
<script>
$(document).ready(function() {
var parent = $("#jsparent").select2({
placeholder: "",
allowClear: true,
theme: "bootstrap4",
minimumInputLength: 2,
ajax: {
url: HTML_PATH_ADMIN_ROOT + "ajax/get-published",
data: function(params) {
var query = {
checkIsParent: true,
query: params.term
}
return query;
},
processResults: function(data) {
return data;
}
},
escapeMarkup: function(markup) {
return markup;
},
templateResult: function(data) {
var html = data.text
if (data.type == "static") {
html += '<span class="badge badge-pill badge-light">' + data.type + '</span>';
}
return html;
}
});
});
</script>
<?php
// Template
echo Bootstrap::formInputTextBlock(array(
'name' => 'template',
'label' => $L->g('Template'),
'placeholder' => '',
'value' => $page->template(),
'tip' => $L->g('Write a template name to filter the page in the theme and change the style of the page.')
));
echo Bootstrap::formInputTextBlock(array(
'name' => 'externalCoverImage',
'label' => $L->g('External cover image'),
'placeholder' => "https://",
'value' => $externalCoverImage,
'tip' => $L->g('Set a cover image from external URL, such as a CDN or some server dedicated for images.')
));
// Username
echo Bootstrap::formInputTextBlock(array(
'name' => '',
'label' => $L->g('Author'),
'placeholder' => '',
'value' => $page->username(),
'tip' => '',
'disabled' => true
));
?>
<script>
$(document).ready(function() {
// Changes in External cover image input
$("#jsexternalCoverImage").change(function() {
$("#jscoverImage").val($(this).val());
});
// Datepicker
$("#jsdate").datetimepicker({
format: DB_DATE_FORMAT
});
});
</script>
</div>
<?php if (!empty($site->customFields())) : ?>
<div id="nav-custom" class="tab-pane fade" role="tabpanel" aria-labelledby="custom-tab">
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (!isset($options['position'])) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'value' => $page->custom($field)
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => $page->custom($field),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : '')
));
}
}
}
?>
</div>
<?php endif ?>
<div id="nav-seo" class="tab-pane fade" role="tabpanel" aria-labelledby="seo-tab">
<?php
// Friendly URL
echo Bootstrap::formInputTextBlock(array(
'name' => 'slug',
'tip' => $L->g('URL associated with the content'),
'label' => $L->g('Friendly URL'),
'placeholder' => $L->g('Leave empty for autocomplete by Bludit.'),
'value' => $page->slug()
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noindex',
'label' => 'Robots',
'labelForCheckbox' => $L->g('apply-code-noindex-code-to-this-page'),
'placeholder' => '',
'checked' => $page->noindex(),
'tip' => $L->g('This tells search engines not to show this page in their search results.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'nofollow',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-nofollow-code-to-this-page'),
'placeholder' => '',
'checked' => $page->nofollow(),
'tip' => $L->g('This tells search engines not to follow links on this page.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noarchive',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-noarchive-code-to-this-page'),
'placeholder' => '',
'checked' => $page->noarchive(),
'tip' => $L->g('This tells search engines not to save a cached copy of this page.')
));
?>
</div>
</div>
</div>
<!-- Custom fields: TOP -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'top')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => $page->custom($field),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => $page->custom($field),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
<!-- Title -->
<div class="form-group mb-1">
<input id="jstitle" name="title" type="text" dir="auto" class="form-control form-control-lg rounded-0" value="<?php echo $page->title() ?>" placeholder="<?php $L->p('Enter title') ?>">
</div>
<!-- Editor -->
<textarea id="jseditor" class="editable h-100" style=""><?php echo $page->contentRaw(true) ?></textarea>
<!-- Custom fields: BOTTOM -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'bottom')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => $page->custom($field),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => $page->custom($field),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
</form>
<!-- Modal for Delete page -->
<div id="jsdeletePageModal" class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<h3><?php $L->p('Delete content') ?></h3>
<p><?php $L->p('Are you sure you want to delete this page') ?></p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-link" data-dismiss="modal"><?php $L->p('Cancel') ?></button>
<button type="button" class="btn btn-danger" data-dismiss="modal" id="jsbuttonDeleteAccept"><?php $L->p('Delete') ?></button>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$("#jsbuttonDeleteAccept").on("click", function() {
$("#jstype").val("delete");
$("#jscontent").val("");
$("#jsform").submit();
});
});
</script>
</div>
<!-- Modal for Media Manager -->
<?php include(PATH_ADMIN_THEMES . 'booty/html/media.php'); ?>
<script>
$(document).ready(function() {
// Define function if they doesn't exist
// This helps if the user doesn't activate any plugin as editor
if (typeof editorGetContent != "function") {
window.editorGetContent = function() {
return $("#jseditor").val();
};
}
if (typeof editorInsertMedia != "function") {
window.editorInsertMedia = function(filename) {
$("#jseditor").val($('#jseditor').val() + '<img src="' + filename + '" alt="">');
};
}
if (typeof editorInsertLinkedMedia != "function") {
window.editorInsertLinkedMedia = function(filename, link) {
$("#jseditor").val($('#jseditor').val() + '<a href="' + link + '"><img src="' + filename + '" alt=""></a>');
};
}
// Button switch
$("#jsswitchButton").on("click", function() {
if ($(this).data("switch") == "publish") {
$(this).html('<i class="fa fa-square switch-icon-draft"></i> <?php $L->p('Draft') ?>');
$(this).data("switch", "draft");
} else {
$(this).html('<i class="fa fa-square switch-icon-publish"></i> <?php $L->p('Publish') ?>');
$(this).data("switch", "publish");
}
});
// Button preview
$("#jsbuttonPreview").on("click", function() {
var uuid = $("#jsuuid").val();
var title = $("#jstitle").val();
var content = editorGetContent();
var ajax = new bluditAjax();
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
var preview = window.open("<?php echo DOMAIN_PAGES . 'autosave-' . $page->uuid() . '?preview=' . md5('autosave-' . $page->uuid()) ?>", "bludit-preview");
preview.focus();
});
});
// Button Save
$("#jsbuttonSave").on("click", function() {
// If the switch is setted to "published", get the value from the selector
if ($("#jsswitchButton").data("switch") == "publish") {
var value = $("#jstypeSelector option:selected").val();
$("#jstype").val(value);
} else {
$("#jstype").val("draft");
}
// Get the content
$("#jscontent").val(editorGetContent());
// Submit the form
$("#jsform").submit();
});
// Button Save as draft
$("#jsbuttonDraft").on("click", function() {
// Set the type as draft
$("#jstype").val("draft");
// Get the content
$("#jscontent").val(editorGetContent());
// Submit the form
$("#jsform").submit();
});
// Autosave
var currentContent = editorGetContent();
setInterval(function() {
var uuid = $("#jsuuid").val();
var title = $("#jstitle").val() + "[<?php $L->p('Autosave') ?>]";
var content = editorGetContent();
// Autosave when content has at least 100 characters
if (content.length < 100) {
return false;
}
// Autosave only when the user change the content
if (currentContent != content) {
currentContent = content;
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
if (data.status == 0) {
showAlert("<?php $L->p('Autosave') ?>");
}
});
}
}, 1000 * 60 * AUTOSAVE_INTERVAL);
});
</script>

View file

@ -1,52 +1,276 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id' => 'jsform', 'class' => 'tab-content')); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'users' ?>" role="button"><?php $L->p('Cancel') ?></a>
// ============================================================================
// Functions for the view
// ============================================================================
function changePassword() {
var newPassword = $('#newPassword').val();
var confirmPassword = $('#confirmPassword').val();
if (newPassword.length < PASSWORD_LENGTH) {
showAlertError("<?php $L->p('Password must be at least 6 characters long') ?>");
return false;
}
if (newPassword !== confirmPassword) {
showAlertError("<?php $L->p('The password and confirmation password do not match') ?>");
return false;
}
bootbox.confirm({
message: '<?php $L->p('Are you sure you want to change the password') ?>',
buttons: {
cancel: {
label: '<i class="fa fa-times"></i><?php $L->p('Cancel') ?>',
className: 'btn-sm btn-secondary'
},
confirm: {
label: '<i class="fa fa-check"></i><?php $L->p('Confirm') ?>',
className: 'btn-sm btn-primary'
}
},
closeButton: false,
callback: function(result) {
if (result) {
// The user accepted the action to change the password
var args = {
username: $('#username').val(),
password: $('#newPassword').val()
};
api.editUser(args).then(function(response) {
if (response.status == 0) {
logs('User password changed. Username: ' + response.data.key);
showAlertInfo("<?php $L->p('The changes have been saved') ?>");
} else {
logs('An error occurred while trying to change the user password.');
showAlertError(response.message);
}
});
}
$('#newPassword').val('');
$('#confirmPassword').val('');
return true;
}
});
}
function save() {
let args = {
username: $('#username').val(),
role: $('#role').val()
};
$('input[data-save="true"]').each(function() {
var key = $(this).attr('name');
var value = $(this).val();
args[key] = value;
});
$('select[data-save="true"]').each(function() {
var key = $(this).attr('name');
var value = $(this).val();
args[key] = value;
});
$('textarea[data-save="true"]').each(function() {
var key = $(this).attr('name');
var value = $(this).val();
args[key] = value;
});
api.editUser(args).then(function(response) {
if (response.status == 0) {
logs('User edited. Username: ' + response.data.key);
showAlertInfo("<?php $L->p('The changes have been saved') ?>");
} else {
logs('An error occurred while trying to edit the user.');
showAlertError(response.message);
}
});
}
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
$('#btnSave').on('click', function() {
// Change the password if the user write a new one in the input
if ($('#newPassword').val()) {
changePassword();
} else {
// Save the edited fields
save();
}
});
$('#inputProfilePicture').on("change", function(e) {
var inputProfilePicture = $('#inputProfilePicture')[0].files;
var username = $('#username').val();
var formData = new FormData();
formData.append("file", inputProfilePicture[0]);
formData.append("token", api.body.token);
formData.append("authentication", api.body.authentication);
$.ajax({
url: api.apiURL + 'users/picture/' + username,
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('Uploading profile image: ' + percentComplete + '%');
}
}, false);
}
return xhr;
}
}).done(function(response) {
logs(response);
if (response.status == 0) {
logs("Profile picture uploaded.");
showAlertInfo("<?php $L->p('The changes have been saved') ?>");
$('#profilePicturePreview').attr('src', response.data.absoluteURL);
} else {
logs("An error occurred while trying to upload the profile picture.");
showAlertError(response.message);
}
});
return true;
});
$('#btnRemoveProfilePicture').on('click', function() {
var username = $('#username').val();
logs('Deleting profile picture. Username: ' + username);
bootbox.confirm({
message: '<?php $L->p('Are you sure you want to delete the profile picture') ?>',
buttons: {
cancel: {
label: '<i class="fa fa-times"></i><?php $L->p('Cancel') ?>',
className: 'btn-sm btn-secondary'
},
confirm: {
label: '<i class="fa fa-check"></i><?php $L->p('Confirm') ?>',
className: 'btn-sm btn-primary'
}
},
closeButton: false,
callback: function(result) {
if (result) {
var args = {
username: username
};
api.deleteProfilePicture(args).then(function(response) {
if (response.status == 0) {
logs('Profile picture deleted. Username: ' + response.data.key);
showAlertInfo("<?php $L->p('The changes have been saved') ?>");
$('#profilePicturePreview').attr('src', '<?php echo HTML_PATH_CORE_IMG . 'default.svg' ?>');
} else {
logs("An error occurred while trying to delete the profile picture.");
showAlertError(response.message);
}
});
return true;
}
}
});
});
$('#btnDisableUser').on('click', function() {
var username = $('#username').val();
logs('Disabling user. Username: ' + username);
bootbox.confirm({
message: '<?php $L->p('Are you sure you want to disable this user') ?>',
buttons: {
cancel: {
label: '<i class="fa fa-times"></i><?php $L->p('Cancel') ?>',
className: 'btn-sm btn-secondary'
},
confirm: {
label: '<i class="fa fa-check"></i><?php $L->p('Confirm') ?>',
className: 'btn-sm btn-primary'
}
},
closeButton: false,
callback: function(result) {
if (result) {
var args = {
username: $('#username').val(),
disable: true
};
api.editUser(args).then(function(response) {
if (response.status == 0) {
logs('User disabled. Username: ' + response.data.key);
window.location.replace(HTML_PATH_ADMIN_ROOT + 'users');
} else {
logs("An error occurred while trying to disable the user.");
showAlertError(response.message);
}
});
}
}
});
});
});
// ============================================================================
// Initlization for the view
// ============================================================================
$(document).ready(function() {
// nothing here yet
// how do you hang your toilet paper ? over or under ?
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-person"></i><?php $L->p('Edit user') ?></h2>
<div class="ms-auto">
<button id="btnSave" type="button" class="btn btn-primary btn-sm"><?php $L->p('Save') ?></button>
<a id="btnCancel" class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'users' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title' => $L->g('Edit user'), 'icon' => 'user')); ?>
</div>
<!-- TABS -->
<nav class="mb-3">
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-item nav-link active" id="nav-profile-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="nav-profile" aria-selected="false"><?php $L->p('Profile') ?></a>
<a class="nav-item nav-link" id="nav-picture-tab" data-toggle="tab" href="#picture" role="tab" aria-controls="nav-picture" aria-selected="false"><?php $L->p('Profile picture') ?></a>
<a class="nav-item nav-link" id="nav-security-tab" data-toggle="tab" href="#security" role="tab" aria-controls="nav-security" aria-selected="false"><?php $L->p('Security') ?></a>
<a class="nav-item nav-link" id="nav-social-tab" data-toggle="tab" href="#social" role="tab" aria-controls="nav-social" aria-selected="false"><?php $L->p('Social Networks') ?></a>
</div>
</nav>
<!-- Tabs -->
<ul class="nav nav-tabs ps-3 mb-3" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="profile-tab" data-bs-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="true"><?php $L->p('Profile') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="picture-tab" data-bs-toggle="tab" href="#picture" role="tab" aria-controls="picture" aria-selected="false"><?php $L->p('Profile picture') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="security-tab" data-bs-toggle="tab" href="#security" role="tab" aria-controls="security" aria-selected="false"><?php $L->p('Security') ?></a>
</li>
<li class="nav-item">
<a class="nav-link" id="social-tab" data-bs-toggle="tab" href="#social" role="tab" aria-controls="social" aria-selected="false"><?php $L->p('Social Networks') ?></a>
</li>
</ul>
<!-- End Tabs -->
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
<!-- Content -->
<div class="tab-content" id="tabContent">
// Username
echo Bootstrap::formInputHidden(array(
'name' => 'username',
'value' => $user->username()
));
?>
<div class="tab-content" id="nav-tabContent">
<!-- Profile tab -->
<div class="tab-pane fade show active" id="profile" role="tabpanel" aria-labelledby="nav-profile-tab">
<!-- Tab profile -->
<div class="tab-pane show active" id="profile" role="tabpanel">
<?php
// Display username but disable the field
echo Bootstrap::formInputText(array(
'name' => 'usernameDisabled',
'name' => 'username',
'label' => $L->g('Username'),
'value' => $user->username(),
'class' => '',
'placeholder' => '',
'disabled' => true,
'tip' => ''
'disabled' => true
));
if ($login->role() === 'admin') {
@ -55,7 +279,6 @@ echo Bootstrap::formInputHidden(array(
'label' => $L->g('Role'),
'options' => array('author' => $L->g('Author'), 'editor' => $L->g('Editor'), 'admin' => $L->g('Administrator')),
'selected' => $user->role(),
'class' => '',
'tip' => $L->g('author-can-write-and-edit-their-own-content')
));
}
@ -64,107 +287,61 @@ echo Bootstrap::formInputHidden(array(
'name' => 'email',
'label' => $L->g('Email'),
'value' => $user->email(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'nickname',
'label' => $L->g('Nickname'),
'value' => $user->nickname(),
'class' => '',
'placeholder' => '',
'tip' => $L->g('The nickname is almost used in the themes to display the author of the content')
'tip' => $L->g('The nickname is almost used in the themes to display the author of the content'),
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'firstName',
'label' => $L->g('First Name'),
'value' => $user->firstName(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'lastName',
'label' => $L->g('Last Name'),
'value' => $user->lastName(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formTextarea(array(
'name' => 'bio',
'label' => $L->g('Bio'),
'value' => $user->bio(),
'rows' => 4,
'data' => array('save' => 'true')
));
?>
</div>
<!-- End Tab profile -->
<!-- Profile picture tab -->
<div class="tab-pane fade" id="picture" role="tabpanel" aria-labelledby="nav-picture-tab">
<!-- Tab profile picture -->
<div class="tab-pane" id="picture" role="tabpanel">
<div class="container">
<div class="row">
<div class="col-lg-4 col-sm-12 p-0 pr-2">
<div class="custom-file">
<input type="file" class="custom-file-input" id="jsprofilePictureInputFile" name="profilePictureInputFile">
<label class="custom-file-label" for="jsprofilePictureInputFile"><?php $L->p('Upload image'); ?></label>
</div>
<!-- <button id="jsbuttonRemovePicture" type="button" class="btn btn-primary w-100 mt-4 mb-4"><i class="fa fa-trash"></i> Remove picture</button> -->
<div class="col-8">
<img id="profilePicturePreview" class="img-fluid img-thumbnail" alt="Profile picture preview" src="<?php echo ($user->profilePicture() ? $user->profilePicture() . '?version=' . time() : HTML_PATH_CORE_IMG . 'default.svg') ?>" />
</div>
<div class="col-lg-8 col-sm-12 p-0 text-center">
<img id="jsprofilePicturePreview" class="img-fluid img-thumbnail" alt="Profile picture preview" src="<?php echo (Sanitize::pathFile(PATH_UPLOADS_PROFILES . $user->username() . '.png') ? DOMAIN_UPLOADS_PROFILES . $user->username() . '.png?version=' . time() : HTML_PATH_CORE_IMG . 'default.svg') ?>" />
<div class="col-4">
<label id="btnUploadProfilePicture" class="btn btn-primary"><i class="bi bi-upload"></i><?php $L->p('Upload image'); ?><input type="file" id="inputProfilePicture" name="inputProfilePicture" hidden></label>
<button id="btnRemoveProfilePicture" type="button" class="btn btn-secondary"><i class="bi bi-trash"></i><?php $L->p('Remove image'); ?></button>
</div>
</div>
</div>
<script>
// $("#jsbuttonRemovePicture").on("click", function() {
// var username = $("#jsusername").val();
// bluditAjax.removeProfilePicture(username);
// $("#jsprofilePicturePreview").attr("src", "<?php echo HTML_PATH_CORE_IMG . 'default.svg' ?>");
// });
$("#jsprofilePictureInputFile").on("change", function() {
var formData = new FormData();
formData.append('tokenCSRF', tokenCSRF);
formData.append('profilePictureInputFile', $(this)[0].files[0]);
formData.append('username', $("#jsusername").val());
$.ajax({
url: HTML_PATH_ADMIN_ROOT + "ajax/profile-picture-upload",
type: "POST",
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function(data) {
if (data.status == 0) {
$("#jsprofilePicturePreview").attr('src', data.absoluteURL + "?time=" + Math.random());
} else {
showAlert(data.message);
}
});
});
</script>
</div>
<!-- End Tab profile picture -->
<!-- Security tab -->
<div class="tab-pane fade" id="security" role="tabpanel" aria-labelledby="nav-security-tab">
<!-- Tab security -->
<div class="tab-pane" id="security" role="tabpanel">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Password')));
echo '
<div class="form-group">
<a href="' . HTML_PATH_ADMIN_ROOT . 'user-password/' . $user->username() . '" class="btn btn-primary mr-2">' . $L->g('Change password') . '</a>
</div>
';
echo Bootstrap::formTitle(array('title' => $L->g('Authentication Token')));
echo Bootstrap::formInputText(array(
'name' => 'tokenAuth',
'label' => $L->g('Token'),
'value' => $user->tokenAuth(),
'class' => '',
'tip' => $L->g('this-token-is-similar-to-a-password-it-should-not-be-shared')
));
if (checkRole(array('admin'), false)) {
echo Bootstrap::formTitle(array('title' => $L->g('Status')));
@ -172,145 +349,145 @@ echo Bootstrap::formInputHidden(array(
'name' => 'status',
'label' => $L->g('Current status'),
'value' => $user->enabled() ? $L->g('Enabled') : $L->g('Disabled'),
'class' => '',
'disabled' => true,
'tip' => $user->enabled() ? '' : $L->g('To enable the user you must set a new password')
));
echo Bootstrap::formInputText(array(
'name' => 'registered',
'label' => $L->g('Registered'),
'value' => Date::format($user->registered(), DB_DATE_FORMAT, ADMIN_PANEL_DATE_FORMAT),
'disabled' => true
));
if ($user->enabled()) {
echo '
<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-10">
<button type="submit" class="btn btn-warning mr-2" id="jsdisableUser" name="disableUser">' . $L->g('Disable user') . '</button>
<button type="submit" class="btn btn-danger mr-2" id="jsdeleteUserAndKeepContent" name="deleteUserAndKeepContent">' . $L->g('Delete user and keep content') . '</button>
<button type="submit" class="btn btn-danger mr-2" id="jsdeleteUserAndDeleteContent" name="deleteUserAndDeleteContent">' . $L->g('Delete user and delete content') . '</button>
<button type="button" class="btn btn-warning me-2" id="btnDisableUser"><i class="bi bi-slash-circle"></i>' . $L->g('Disable user') . '</button>
<button type="button" class="btn btn-danger me-2" id="btnDeleteUserAndKeepContent"><i class="bi bi-trash"></i>' . $L->g('Delete user and keep content') . '</button>
<button type="button" class="btn btn-danger" id="btnDeleteUserAndContent"><i class="bi bi-trash"></i>' . $L->g('Delete user and delete content') . '</button>
</div>
</div>
';
}
}
echo Bootstrap::formTitle(array('title' => $L->g('Authentication Token')));
echo Bootstrap::formInputText(array(
'name' => 'tokenAuth',
'label' => $L->g('Token'),
'value' => $user->tokenAuth(),
'tip' => $L->g('this-token-is-similar-to-a-password-it-should-not-be-shared')
));
echo Bootstrap::formTitle(array('title' => $L->g('Change password')));
echo Bootstrap::formInputText(array(
'name' => 'newPassword',
'label' => $L->g('New password'),
'type' => 'password',
'value' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'confirmPassword',
'label' => $L->g('Confirm password'),
'type' => 'password',
'value' => ''
));
?>
</div>
<!-- End Tab security -->
<!-- Social Networks tab -->
<div class="tab-pane fade" id="social" role="tabpanel" aria-labelledby="nav-social-tab">
<div class="tab-pane" id="social" role="tabpanel">
<?php
echo Bootstrap::formInputText(array(
'name' => 'youtube',
'label' => 'Youtube',
'value' => $user->youtube(),
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'twitter',
'label' => 'Twitter',
'value' => $user->twitter(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'facebook',
'label' => 'Facebook',
'value' => $user->facebook(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'discord',
'label' => 'Discord',
'value' => $user->discord(),
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'codepen',
'label' => 'CodePen',
'value' => $user->codepen(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'instagram',
'label' => 'Instagram',
'value' => $user->instagram(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'gitlab',
'label' => 'GitLab',
'value' => $user->gitlab(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'github',
'label' => 'GitHub',
'value' => $user->github(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'linkedin',
'label' => 'LinkedIn',
'value' => $user->linkedin(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'xing',
'label' => 'Xing',
'value' => $user->xing(),
'class' => '',
'placeholder' => '',
'tip' => ''
));
echo Bootstrap::formInputText(array(
'name' => 'telegram',
'label' => 'Telegram',
'value' => $user->telegram(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'mastodon',
'label' => 'Mastodon',
'value' => $user->mastodon(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
echo Bootstrap::formInputText(array(
'name' => 'vk',
'label' => 'VK',
'value' => $user->vk(),
'class' => '',
'placeholder' => '',
'tip' => ''
'data' => array('save' => 'true')
));
?>
</div>
</div>
<?php echo Bootstrap::formClose(); ?>
<script>
// Open current tab after refresh page
$(function() {
$('a[data-toggle="tab"]').on('click', function(e) {
window.localStorage.setItem('activeTab', $(e.target).attr('href'));
console.log($(e.target).attr('href'));
});
var activeTab = window.localStorage.getItem('activeTab');
if (activeTab) {
$('#nav-tab a[href="' + activeTab + '"]').tab('show');
//window.localStorage.removeItem("activeTab");
}
});
</script>

View file

@ -0,0 +1,679 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
var _pageKey = <?php echo $pageKey ? '"' . $pageKey . '"' : 'null' ?>;
// ============================================================================
// Functions for the view
// ============================================================================
// Default function for the editor
// These functions work if the user does not activate any plugin
if (typeof editorGetContent != 'function') {
window.editorGetContent = function() {
return $('#editor').val();
};
}
if (typeof editorInsertContent != 'function') {
window.editorInsertContent = function(content, type = '') {
if (type == 'image') {
var html = '<img src="' + content + '" alt="" />';
} else {
var html = content;
}
$('#editor').val($('#editor').val() + html);
};
}
// Create the a page
// This function set the global variable "_pageKey"
function createPage() {
logs('Creating page.');
api.createPage().then(function(response) {
if (response.status == 0) {
logs('Page created. Key: ' + response.data.key);
// Set the global variable with the page key
_pageKey = response.data.key;
// Set Friendly URL
$('#friendlyURL').val(response.data.key);
// Get current files
fmGetFiles();
} else {
logs("An error occurred while trying to create the page.");
showAlertError(response.message);
}
});
return true;
}
// Set the page in the editor
function setPage() {
logs('Setting up the page');
// Get current files
fmGetFiles();
return true;
}
// Save the current page
// This function set the global variable "_pageKey"
function savePage(args) {
logs('Saving page.');
if (_pageKey == null) {
logs('Error, page not created.');
showAlertError("Error, page not created.");
return false;
}
args['pageKey'] = _pageKey;
api.savePage(args).then(function(response) {
if (response.status == 0) {
logs('Page saved. Old key: ' + _pageKey + ' / New key: ' + response.data.key);
// Set the global variable with the page key
// The page key can change after save the page so you need to set again the variable
_pageKey = response.data.key;
// Set friendly URL with the key
$('#friendlyURL').val(response.data.key);
} else {
logs('An error occurred while trying to save the current page.');
showAlertError(response.message);
}
});
return true;
}
// Open the modal and store the current value
// The current value is store to recover it if the user click on the button "Cancel"
function openModal(fieldName) {
var value = $('#' + fieldName).val();
localStorage.setItem(fieldName, value);
$('#modal-' + fieldName).modal('show');
}
// Close the modal when the user click in the button "Cancel"
// The function also recover the old value
function closeModal(fieldName) {
var value = localStorage.getItem(fieldName);
$('#' + fieldName).val(value);
$('#modal-' + fieldName).modal('hide');
}
function disableBtnSave() {
$('#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').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
// The editor plugin need to call this function for the event "keydown"
function keypress(event) {
logs(event);
// Shortcuts
// ------------------------------------------------------------------------
// Ctrl+S or Command+S
if ((event.ctrlKey || event.metaKey) && event.which == 83) {
event.preventDefault();
var args = {
title: $('#title').val(),
content: editorGetContent(),
category: $('#category option:selected').val(),
tags: $('#tags').val()
}
savePage(args);
disableBtnSave();
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;
}
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// 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(),
content: editorGetContent(),
category: $('#category option:selected').val(),
tags: $("#tags option:selected").map(function() {
return this.value
}).get().join(",")
}
savePage(args);
disableBtnSave();
});
$('#btnCurrenType').on('click', function() {
openModal('type');
});
$('#category').on("change", function() {
enableBtnSave();
});
// Modal description events
// ------------------------------------------------------------------------
$('#btnSaveDescription').on('click', function() {
var args = {
description: $('#description').val()
};
savePage(args);
disableBtnSave();
closeModal('description');
});
$('#btnCancelDescription').on('click', function() {
closeModal('description');
});
// Modal date events
// ------------------------------------------------------------------------
$('#btnSaveDate').on('click', function() {
var args = {
date: $('#date').val()
};
savePage(args);
disableBtnSave();
closeModal('date');
});
$('#btnCancelDate').on('click', function() {
closeModal('date');
});
// Modal friendly-url events
// ------------------------------------------------------------------------
$('#btnSaveFriendlyURL').on('click', function() {
var args = {
slug: $('#friendlyURL').val()
};
savePage(args);
disableBtnSave();
closeModal('friendlyURL');
});
$('#btnCancelFriendlyURL').on('click', function() {
closeModal('friendlyURL');
});
$('#btnGenURLFromTitle').on('click', function() {
var args = {
text: $('#title').val(),
parentKey: $('#parent').val(),
pageKey: _pageKey
}
api.friendlyURL(args).then(function(response) {
if (response.status == 0) {
logs('Friendly URL created: ' + response.data.slug);
$('#friendlyURL').val(response.data.slug);
} else {
logs('An error occurred while trying to generate a friendly URL for the page.');
showAlertError(response.message);
}
});
});
// Modal type events
// ------------------------------------------------------------------------
$('#btnSaveType').on('click', function() {
var args = {
type: $('input[name="type"]:checked').val()
};
savePage(args);
disableBtnSave();
closeModal('type');
if (args['type'] == 'draft') {
$('#btnCurrenType').html('<i class="bi bi-circle"></i><?php $L->p('Draft') ?>');
} else if (args['type'] == 'published') {
$('#btnCurrenType').html('<i class="bi bi-check2-circle"></i><?php $L->p('Published') ?>');
} else if (args['type'] == 'unlisted') {
$('#btnCurrenType').html('<i class="bi bi-check2-circle"></i><?php $L->p('Unlisted') ?>');
} else if (args['type'] == 'sticky') {
$('#btnCurrenType').html('<i class="bi bi-check2-circle"></i><?php $L->p('Sticky') ?>');
} else if (args['type'] == 'static') {
$('#btnCurrenType').html('<i class="bi bi-check2-circle"></i><?php $L->p('Static') ?>');
}
});
$('#btnCancelType').on('click', function() {
closeModal('type');
});
// Modal SEO events
// ------------------------------------------------------------------------
$('#btnSaveSeo').on('click', function() {
var args = {
parent: $('#parent').val()
};
savePage(args);
disableBtnSave();
closeModal('seo');
});
$('#btnCancelSeo').on('click', function() {
closeModal('seo');
});
// Modal parent events
// ------------------------------------------------------------------------
$('#btnSaveParent').on('click', function() {
var args = {
parent: $('#parent').val()
};
savePage(args);
disableBtnSave();
closeModal('parent');
});
$('#btnCancelParent').on('click', function() {
closeModal('parent');
});
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// How do you hang your toilet paper ? over or under ?
// Create the page or set the page
if (_pageKey == null) {
createPage();
} else {
setPage();
}
// Autosave
setInterval(function() {
var content = editorGetContent();
// Autosave when content has at least 100 characters
if (content.length < 100) {
return false;
}
savePage();
disableBtnSave();
}, 1000 * 60 * AUTOSAVE_INTERVAL);
});
</script>
<!-- File manager -->
<?php include(PATH_ADMIN_VIEWS . 'editor' . DS . 'file-manager.php') ?>
<!-- End File manager -->
<!-- Modal Description -->
<div class="modal" id="modal-description" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="m-0">
<label for="parent" class="fw-bold mb-2">Page description</label>
<textarea id="description" name="description" class="form-control" rows="3"><?php echo ($pageKey ? $page->description() : '') ?></textarea>
<div class="form-text"><?php echo $L->get('this-field-can-help-describe-the-content') ?></div>
</div>
</div>
<div class="modal-footer ps-2 pe-2 pt-1 pb-1">
<button id="btnCancelDescription" type="button" class="btn btn-cancel fw-bold me-auto"><i class="bi bi-x-square"></i>Cancel</button>
<button id="btnSaveDescription" type="button" class="btn btn-save fw-bold text-success"><i class="bi bi-check-square"></i>Save</button>
</div>
</div>
</div>
</div>
<!-- End Modal Description -->
<!-- Modal Date -->
<div class="modal" id="modal-date" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="m-0">
<label for="date" class="fw-bold mb-2">Publish date</label>
<input id="date" name="date" type="text" class="form-control" value="<?php echo ($pageKey ? $page->dateRaw() : Date::current(DB_DATE_FORMAT)) ?>">
<div class="form-text"><?php echo $L->g('date-format-format') ?></div>
</div>
</div>
<div class="modal-footer ps-2 pe-2 pt-1 pb-1">
<button id="btnCancelDate" type="button" class="btn btn-cancel fw-bold me-auto"><i class="bi bi-x-square"></i>Cancel</button>
<button id="btnSaveDate" type="button" class="btn btn-save fw-bold text-success"><i class="bi bi-check-square"></i>Save</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
$("#date").datetimepicker({
format: DB_DATE_FORMAT
});
});
</script>
<!-- End Modal Date -->
<!-- Modal friendly URL -->
<div class="modal" id="modal-friendlyURL" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="m-0">
<div class="d-flex mb-2">
<label for="friendlyURL" class="p-0 m-0 me-auto fw-bold">Page URL</label>
<button id="btnGenURLFromTitle" type="button" class="btn p-0 m-0 text-primary"><i class="bi bi-hammer"></i>Generate from page title</button>
</div>
<input id="friendlyURL" name="friendlyURL" type="text" class="form-control" value="<?php echo ($pageKey ? $page->slug() : '') ?>">
<div class="form-text">https://www.varlogdiego.com/my-page-about-k8s</div>
</div>
</div>
<div class="modal-footer ps-2 pe-2 pt-1 pb-1">
<button id="btnCancelFriendlyURL" type="button" class="btn btn-cancel fw-bold me-auto"><i class="bi bi-x-square"></i>Cancel</button>
<button id="btnSaveFriendlyURL" type="button" class="btn btn-save fw-bold text-success"><i class="bi bi-check-square"></i>Save</button>
</div>
</div>
</div>
</div>
<!-- End Modal friendly URL -->
<!-- Modal Type -->
<div class="modal" id="modal-type" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="m-0">
<label class="fw-bold mb-2">Page type</label>
</div>
<div class="form-check mb-2">
<input id="statusDraft" name="type" class="form-check-input" type="radio" value="draft" <?php echo ((($pageKey && $page->draft()) || !$pageKey) ? 'checked' : '') ?>>
<label class="form-check-label" for="statusDraft">Draft</label>
<div class="form-text">Page as draft, is not visible for visitors.</div>
</div>
<div class="form-check mb-2">
<input id="statusPublish" name="type" class="form-check-input" type="radio" value="published" <?php echo (($pageKey && $page->published()) ? 'checked' : '') ?>>
<label class="form-check-label" for="statusPublish">Publish</label>
<div class="form-text">Publish the page, everyone can see it.</div>
</div>
<hr>
<div class="form-check mb-2">
<input id="statusSticky" name="type" class="form-check-input" type="radio" value="sticky" <?php echo (($pageKey && $page->sticky()) ? 'checked' : '') ?>>
<label class="form-check-label" for="statusSticky">Publish as sticky</label>
<div class="form-text">The page can be seen by everyone in the top of the main page.</div>
</div>
<div class="form-check mb-2">
<input id="statusStatic" name="type" class="form-check-input" type="radio" value="static" <?php echo (($pageKey && $page->isStatic()) ? 'checked' : '') ?>>
<label class="form-check-label" for="statusStatic">Publish as static</label>
<div class="form-text">The page can be seen by everyone as static page.</div>
</div>
<div class="form-check mb-2">
<input id="statusUnlisted" name="type" class="form-check-input" type="radio" value="unlisted" <?php echo (($pageKey && $page->unlisted()) ? 'checked' : '') ?>>
<label class="form-check-label" for="statusUnlisted">Publish as unlisted</label>
<div class="form-text">The page can be seen and shared by anyone with the link.</div>
</div>
</div>
<div class="modal-footer ps-2 pe-2 pt-1 pb-1">
<button id="btnCancelType" type="button" class="btn btn-cancel fw-bold me-auto"><i class="bi bi-x-square"></i>Cancel</button>
<button id="btnSaveType" type="button" class="btn btn-save fw-bold text-success"><i class="bi bi-check-square"></i>Save</button>
</div>
</div>
</div>
</div>
<!-- End Modal Type -->
<!-- Modal SEO -->
<div class="modal" id="modal-seo" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="m-0">
<label class="fw-bold mb-2">SEO features</label>
</div>
<div class="form-check mb-2">
<input id="noindex" name="noindex" class="form-check-input" type="checkbox" value="noindex" <?php echo (($pageKey && $page->noindex()) ? 'checked' : '') ?>>
<label class="form-check-label" for="noindex"><?php echo $L->g('apply-code-noindex-code-to-this-page') ?></label>
<div class="form-text"><?php echo $L->g('This tells search engines not to show this page in their search results.') ?></div>
</div>
<div class="form-check mb-2">
<input id="nofollow" name="nofollow" class="form-check-input" type="checkbox" value="nofollow" <?php echo (($pageKey && $page->nofollow()) ? 'checked' : '') ?>>
<label class="form-check-label" for="nofollow"><?php echo $L->g('apply-code-nofollow-code-to-this-page') ?></label>
<div class="form-text"><?php echo $L->g('This tells search engines not to follow links on this page.') ?></div>
</div>
<div class="form-check mb-2">
<input id="noarchive" name="noarchive" class="form-check-input" type="checkbox" value="noarchive" <?php echo (($pageKey && $page->noarchive()) ? 'checked' : '') ?>>
<label class="form-check-label" for="noarchive"><?php echo $L->g('apply-code-noarchive-code-to-this-page') ?></label>
<div class="form-text"><?php echo $L->g('This tells search engines not to save a cached copy of this page.') ?></div>
</div>
</div>
<div class="modal-footer ps-2 pe-2 pt-1 pb-1">
<button id="btnCancelSeo" type="button" class="btn btn-cancel fw-bold me-auto"><i class="bi bi-x-square"></i>Cancel</button>
<button id="btnSaveSeo" type="button" class="btn btn-save fw-bold text-success"><i class="bi bi-check-square"></i>Save</button>
</div>
</div>
</div>
</div>
<!-- End Modal SEO -->
<!-- Modal Parent -->
<div class="modal" id="modal-parent" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<div class="m-0">
<label for="parent" class="fw-bold mb-2">Parent page</label>
<select id="parent" name="parent" class="custom-select"></select>
<div class="form-text"><?php echo $L->g('Start typing a page title to see a list of suggestions.') ?></div>
</div>
</div>
<div class="modal-footer ps-2 pe-2 pt-1 pb-1">
<button id="btnCancelParent" type="button" class="btn btn-cancel fw-bold me-auto"><i class="bi bi-x-square"></i>Cancel</button>
<button id="btnSaveParent" type="button" class="btn btn-save fw-bold text-success"><i class="bi bi-check-square"></i>Save</button>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function() {
var parent = $("#parent").select2({
placeholder: "",
allowClear: true,
theme: "bootstrap4",
minimumInputLength: 2,
ajax: {
url: HTML_PATH_ADMIN_ROOT + "ajax/get-published",
data: function(params) {
var query = {
checkIsParent: true,
query: params.term
}
return query;
},
processResults: function(data) {
return data;
}
},
escapeMarkup: function(markup) {
return markup;
},
templateResult: function(data) {
var html = data.text;
if (data.type == "static") {
html += '<span class="badge badge-pill badge-light">' + data.type + '</span>';
}
return html;
}
});
});
</script>
<!-- End Modal Parent -->
<div class="container-fluid h-100">
<div class="row h-100">
<div class="col-sm-9 d-flex flex-column h-100">
<!-- 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" 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>
</div>
<div id="editorToolbarRight" class="ms-auto">
<span id="btnCurrenType" class="ms-1 text-uppercase">
<?php
if ($pageKey) {
if ($page->draft()) {
echo '<i class="bi bi-circle"></i><span>' . $L->g('Draft') . '</span>';
} elseif ($page->published()) {
echo '<i class="bi bi-check2-circle"></i><span>' . $L->g('Published') . '</span>';
} elseif ($page->sticky()) {
echo '<i class="bi bi-check2-circle"></i><span>' . $L->g('Sticky') . '</span>';
} elseif ($page->isStatic()) {
echo '<i class="bi bi-check2-circle"></i><span>' . $L->g('Static') . '</span>';
} elseif ($page->unlisted()) {
echo '<i class="bi bi-check2-circle"></i><span>' . $L->g('Unlisted') . '</span>';
}
} else {
echo '<i class="bi bi-circle"></i><span>' . $L->g('Draft') . '</span>';
}
?>
</span>
</div>
</div>
<!-- End Toolbar > Save, Preview, Type and Options -->
<!-- Title -->
<div class="mb-2">
<input id="title" name="title" type="text" class="form-control form-control-lg" value="<?php echo ($pageKey ? $page->title() : '') ?>" placeholder="<?php $L->p('Enter title') ?>">
</div>
<!-- End Title -->
<!-- Editor -->
<textarea class="form-control flex-grow-1" placeholder="" id="editor"><?php echo ($pageKey ? $page->contentRaw() : '') ?></textarea>
<!-- End Editor -->
</div> <!-- End <div class="col-sm-9 h-100"> -->
<div class="col-sm-3 h-100 mt-2">
<!-- Cover Image -->
<h6 class="text-uppercase"><?php $L->p('Cover Image') ?></h6>
<div>
<img id="jscoverImagePreview" class="mx-auto d-block w-100" alt="Cover image preview" src="<?php echo (($pageKey && $page->coverImage()) ? $page->coverImage() : HTML_PATH_CORE_IMG . 'default.svg') ?>" />
</div>
<!-- End Cover Image -->
<!-- Category -->
<h6 class="text-uppercase mt-4">Category</h6>
<?php
echo Bootstrap::formSelect(array(
'id' => 'category',
'name' => 'category',
'selected' => ($pageKey ? $page->categoryKey() : ''),
'options' => array_merge(array('' => $L->g('Uncategorized')), $categories->getKeyNameArray())
));
?>
<!-- End Category -->
<!-- Tags -->
<h6 class="text-uppercase mt-4">Tags</h6>
<div class="mb-1">
<input id="addTag" name="addTag" type="text" class="form-control" value="" placeholder="<?php $L->p('Add tag') ?>">
</div>
<select id="tags" size="5" class="form-select" multiple aria-label="multiple select">
<?php
foreach ($tags->db as $key => $fields) {
echo '<option value="' . $key . '" ' . ($pageKey && in_array($key, $page->tags(true)) ? 'selected' : '') . '>' . $fields['name'] . '</option>';
}
?>
</select>
<script>
$(document).ready(function() {
$('#addTag').keypress(function(e) {
if (e.which == 13) {
var value = $(this).val();
if ($("#tags option[value='" + value + "']").length > 0) {
$("#tags option[value='" + value + "']").prop('selected', true);
} else {
$('#tags').prepend($('<option>', {
value: $(this).val(),
text: $(this).val(),
selected: true
}));
}
$(this).val('');
return false;
}
});
$("#tags").on("mousedown", 'option', function(e) {
e.preventDefault();
$(this).prop('selected', !$(this).prop('selected'));
enableBtnSave();
return false;
});
});
</script>
<!-- End Tags -->
<h6 class="text-uppercase mt-4">More options</h6>
<ul class="list-group">
<li class="list-group-item p-0 pt-3"><a onclick="fmOpen()" href="#"><i class="bi bi-files"></i>Files & images</a></li>
<li class="list-group-item p-0 pt-3"><a onclick="openModal('description')" href="#"><i class="bi bi-info-square"></i>Description</a></li>
<li class="list-group-item p-0 pt-3"><a onclick="openModal('date')" href="#"><i class="bi bi-calendar"></i>Publish date</a></li>
<li class="list-group-item p-0 pt-3"><a onclick="openModal('friendlyURL')" href="#"><i class="bi bi-link"></i>Change URL</a></li>
<li class="list-group-item p-0 pt-3"><a onclick="openModal('type')" href="#"><i class="bi bi-eye"></i>Type</a></li>
<li class="list-group-item p-0 pt-3"><a onclick="openModal('seo')" href="#"><i class="bi bi-compass"></i>SEO features</a></li>
<li class="list-group-item p-0 pt-3"><a onclick="openModal('parent')" href="#"><i class="bi bi-diagram-2"></i>Parent page</a></li>
</ul>
<!-- Quick files
<h6 class="text-uppercase mt-4"><?php $L->p('Quick files') ?></h6>
<div id="quickFiles">
<div class="d-flex align-items-center mb-1">
<i class="bi bi-image" style="font-size: 1.6rem;"></i>
<span>photo1.jpg</span>
</div>
<div class="d-flex align-items-center mb-1">
<i class="bi bi-image" style="font-size: 1.6rem;"></i>
<span>test.txt</span>
</div>
<div class="d-flex align-items-center mb-1">
<i class="bi bi-image" style="font-size: 1.6rem;"></i>
<span>test.txt</span>
</div>
</div>
End Quick files
-->
</div> <!-- End <div class="col-sm-3 h-100"> -->
</div> <!-- End <div class="row h-100"> -->
</div> <!-- End <div class="container-fluid h-100"> -->

View file

@ -0,0 +1,223 @@
<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-4">
<h3 class="me-auto m-0 p-0"><i class="bi bi-image"></i><?php $L->p('File Manager'); ?></h3>
<label id="btnUploadFile" 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 id="progressUploadFile" class="progress w-25 d-none">
<div class="progress-bar" role="progressbar" style="width: 0%" 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">
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="fileOptions" data-bs-toggle="dropdown" aria-expanded="false">
Options
</button>
<ul class="dropdown-menu" aria-labelledby="fileOptions">
<li><a class="dropdown-item" href="#">Insert</a></li>
<li><a class="dropdown-item" href="#">Set as cover image</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#"><?php $L->p('Delete') ?></a></li>
</ul>
</div>
</td>
</tr> -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
// Open File Manager modal
function fmOpen() {
$('#modal-fileManager').modal('show');
}
// Close File Manager modal
function fmClose() {
$('#modal-fileManager').modal('hide');
}
// Insert HTML code in the Editor content
function fmInsertFile(filename, absoluteURL, mime) {
if (mime == 'image/jpeg' || mime == 'image/png') {
editorInsertContent(absoluteURL, 'image');
} else {
editorInsertContent('<a href="' + absoluteURL + '">' + filename + '</a>');
}
}
// Get the files for the current page and show them
function fmGetFiles() {
logs('File Manager. Getting files for the current page: ' + _pageKey);
api.getPageFiles({
'pageKey': _pageKey
}).then(function(response) {
if (response.status == 0) {
fmDisplayFiles(response.data);
} else {
logs("File Manager. An error occurred while trying to get the files for the current page.");
showAlertError(response.message);
}
});
}
// Displays the files in the table
function fmDisplayFiles(files) {
$('#fmFiles').empty();
if (files.length == 0) {
logs('File Manager. There are not files for the current page.');
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 text-center">' +
'<div class="dropdown">' +
' <button class="btn btn-sm btn-secondary dropdown-toggle" type="button" id="fileOptions" data-bs-toggle="dropdown" aria-expanded="false"><i class="bi bi-gear"></i>Options</button>' +
' <ul class="dropdown-menu" aria-labelledby="fileOptions">' +
' <li><a class="dropdown-item" href="#" onClick="fmInsertFile(\'' + file.filename + '\', \'' + file.absoluteURL + '\', \'' + file.mime + '\'); fmClose();"><i class="bi bi-plus-circle"></i><?php $L->p('Insert') ?></a></li>' +
' <li><a class="dropdown-item" href="#"><i class="bi bi-image"></i>Set as cover image</a></li>' +
' <li><hr class="dropdown-divider"></li>' +
' <li><a class="dropdown-item" href="#"><i class="bi bi-trash"></i><?php $L->p('Delete') ?></a></li>' +
' </ul>' +
'</div>' +
'</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', '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_EXTENSIONS']) ?>");
return false;
}
// Check file size and compare with PHP upload_max_filesize
if (file.size > UPLOAD_MAX_FILESIZE) {
logs("File Manager. File size is to big for PHP configuration.");
showAlertError("<?php echo $L->g('Maximum load file size allowed:') . ' ' . ini_get('upload_max_filesize') ?>");
return false;
}
// Start progress bar
$('#btnUploadFile').addClass('d-none');
$('#progressUploadFile').removeClass('d-none');
$('#progressUploadFile').children('.progress-bar').width('0');
// 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 + 'pages/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;
$('#progressUploadFile').children('.progress-bar').width(percentComplete + '%');
}
}, false);
}
return xhr;
}
}).done(function(response) {
if (response.status == 0) {
logs("File Manager. File uploaded.");
// Progress bar
$('#progressUploadFile').addClass('d-none');
$('#btnUploadFile').removeClass('d-none');
// Get current files
fmGetFiles();
} else {
logs("File Manager. An error occurred while trying to upload the file.");
// Progress bar
$('#progressUploadFile').children('.progress-bar').addClass('bg-danger');
// Alert the user about the error
showAlertError('File Manager. ' + response.message);
}
});
}
// Initlization and events for the File Manager
$(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]);
}
});
// Drag and drop files to upload them
$(window).on("dragover dragenter", function(e) {
e.preventDefault();
e.stopPropagation();
fmOpen();
});
$(window).on("drop", function(e) {
e.preventDefault();
e.stopPropagation();
$('#filesToUpload').prop('files', e.originalEvent.dataTransfer.files);
$('#filesToUpload').trigger('change');
});
});
</script>

View file

@ -1,37 +1,71 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
echo '<h1 class="text-center mb-3 mt-3 font-weight-normal" style="color: #555;">' . $site->title() . '</h1>';
<script>
// ============================================================================
// Variables for the view
// ============================================================================
echo Bootstrap::formOpen(array());
// ============================================================================
// Functions for the view
// ============================================================================
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// No events for the view yet
});
echo '
<div class="form-group">
<input type="text" dir="auto" value="' . (isset($_POST['username']) ? Sanitize::html($_POST['username']) : '') . '" class="form-control form-control-lg" id="jsusername" name="username" placeholder="' . $L->g('Username') . '" autofocus>
</div>
';
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
echo '
<div class="form-group">
<input type="password" class="form-control form-control-lg" id="jspassword" name="password" placeholder="' . $L->g('Password') . '">
</div>
';
<?php
echo '
echo '<h1 class="text-center fw-normal mb-5">'.$site->title().'</h1>';
echo Bootstrap::formOpen(array('name'=>'login'));
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
echo Bootstrap::formFloatingLabels(array(
'id'=>'username',
'name'=>'username',
'type'=>'text',
'value'=>(isset($_POST['username'])?Sanitize::html($_POST['username']):''),
'class'=>'form-control-lg',
'placeholder'=>$L->g('Username')
));
echo Bootstrap::formFloatingLabels(array(
'id'=>'password',
'name'=>'password',
'type'=>'password',
'value'=>'',
'class'=>'form-control-lg',
'placeholder'=>$L->g('Password')
));
echo '
<div class="form-check">
<input class="form-check-input" type="checkbox" value="true" id="jsremember" name="remember">
<label class="form-check-label" for="jsremember">' . $L->g('Remember me') . '</label>
<label class="form-check-label" for="jsremember">'.$L->g('Remember me').'</label>
</div>
<div class="form-group mt-3">
<button type="submit" class="btn btn-primary btn-lg mr-2 w-100" name="save">' . $L->g('Login') . '</button>
<div class="mt-4">
<button type="submit" class="btn btn-primary btn-lg me-2 w-100" name="save">'.$L->g('Login').'</button>
</div>
';
echo '</form>';
echo '<p class="mt-3 text-right">' . $L->g('Powered by Bludit') . ((defined('BLUDIT_PRO')) ? ' PRO' : '') . '</p>';
echo '<p class="mt-5 text-end">Powered by <a href="https://www.bludit.com">Bludit</a></p>'
?>

View file

@ -1,39 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a 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('New category'), 'icon'=>'tag')); ?>
</div>
<?php
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
echo Bootstrap::formInputText(array(
'name'=>'name',
'label'=>$L->g('Name'),
'value'=>isset($_POST['category'])?$_POST['category']:'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formTextarea(array(
'name'=>'description',
'label'=>$L->g('Description'),
'value'=>isset($_POST['description'])?$_POST['description']:'',
'class'=>'',
'placeholder'=>'',
'tip'=>'',
'rows'=>3
));
?>
<?php echo Bootstrap::formClose(); ?>

View file

@ -1,511 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php
// Start form
echo Bootstrap::formOpen(array(
'id' => 'jsform',
'class' => 'd-flex flex-column h-100'
));
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name' => 'tokenCSRF',
'value' => $security->getTokenCSRF()
));
// UUID
// The UUID is generated in the controller
echo Bootstrap::formInputHidden(array(
'name' => 'uuid',
'value' => $uuid
));
// Type = published, draft, sticky, static
echo Bootstrap::formInputHidden(array(
'name' => 'type',
'value' => 'published'
));
// Cover image
echo Bootstrap::formInputHidden(array(
'name' => 'coverImage',
'value' => ''
));
// Content
echo Bootstrap::formInputHidden(array(
'name' => 'content',
'value' => ''
));
?>
<!-- TOOLBAR -->
<div id="jseditorToolbar" class="mb-1">
<div id="jseditorToolbarRight" class="btn-group btn-group-sm float-right" role="group" aria-label="Toolbar right">
<button type="button" class="btn btn-light" id="jsmediaManagerOpenModal" data-toggle="modal" data-target="#jsmediaManagerModal"><span class="fa fa-image"></span> <?php $L->p('Images') ?></button>
<button type="button" class="btn btn-light" id="jsoptionsSidebar" style="z-index:30"><span class="fa fa-cog"></span> <?php $L->p('Options') ?></button>
</div>
<div id="jseditorToolbarLeft">
<button id="jsbuttonSave" type="button" class="btn btn-sm btn-primary"><?php $L->p('Save') ?></button>
<button id="jsbuttonPreview" type="button" class="btn btn-sm btn-secondary"><?php $L->p('Preview') ?></button>
<span id="jsbuttonSwitch" data-switch="publish" class="ml-2 text-secondary switch-button"><i class="fa fa-square switch-icon-publish"></i> <?php $L->p('Publish') ?></span>
</div>
</div>
<script>
$(document).ready(function() {
$("#jsoptionsSidebar").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
$("#jsshadow").on("click", function() {
$("#jseditorSidebar").toggle();
$("#jsshadow").toggle();
});
});
</script>
<!-- SIDEBAR OPTIONS -->
<div id="jseditorSidebar">
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-link active show" id="nav-general-tab" data-toggle="tab" href="#nav-general" role="tab" aria-controls="general"><?php $L->p('General') ?></a>
<a class="nav-link" id="nav-advanced-tab" data-toggle="tab" href="#nav-advanced" role="tab" aria-controls="advanced"><?php $L->p('Advanced') ?></a>
<?php if (!empty($site->customFields())) : ?>
<a class="nav-link" id="nav-custom-tab" data-toggle="tab" href="#nav-custom" role="tab" aria-controls="custom"><?php $L->p('Custom') ?></a>
<?php endif ?>
<a class="nav-link" id="nav-seo-tab" data-toggle="tab" href="#nav-seo" role="tab" aria-controls="seo"><?php $L->p('SEO') ?></a>
</div>
</nav>
<div class="tab-content pr-3 pl-3 pb-3">
<div id="nav-general" class="tab-pane fade show active" role="tabpanel" aria-labelledby="general-tab">
<?php
// Category
echo Bootstrap::formSelectBlock(array(
'name' => 'category',
'label' => $L->g('Category'),
'selected' => '',
'class' => '',
'emptyOption' => '- ' . $L->g('Uncategorized') . ' -',
'options' => $categories->getKeyNameArray()
));
// Description
echo Bootstrap::formTextareaBlock(array(
'name' => 'description',
'label' => $L->g('Description'),
'selected' => '',
'class' => '',
'value' => '',
'rows' => 5,
'placeholder' => $L->get('this-field-can-help-describe-the-content')
));
?>
<!-- Cover Image -->
<label class="mt-4 mb-2 pb-2 border-bottom text-uppercase w-100"><?php $L->p('Cover Image') ?></label>
<div>
<img id="jscoverImagePreview" class="mx-auto d-block w-100" alt="Cover image preview" src="<?php echo HTML_PATH_CORE_IMG ?>default.svg" />
</div>
<div class="mt-2 text-center">
<button type="button" id="jsbuttonSelectCoverImage" class="btn btn-primary btn-sm"><?php echo $L->g('Select cover image') ?></button>
<button type="button" id="jsbuttonRemoveCoverImage" class="btn btn-secondary btn-sm"><?php echo $L->g('Remove cover image') ?></button>
</div>
<script>
$(document).ready(function() {
$("#jscoverImagePreview").on("click", function() {
openMediaManager();
});
$("#jsbuttonSelectCoverImage").on("click", function() {
openMediaManager();
});
$("#jsbuttonRemoveCoverImage").on("click", function() {
$("#jscoverImage").val('');
$("#jscoverImagePreview").attr('src', HTML_PATH_CORE_IMG + 'default.svg');
});
});
</script>
</div>
<div id="nav-advanced" class="tab-pane fade" role="tabpanel" aria-labelledby="advanced-tab">
<?php
// Date
echo Bootstrap::formInputTextBlock(array(
'name' => 'date',
'label' => $L->g('Date'),
'placeholder' => '',
'value' => Date::current(DB_DATE_FORMAT),
'tip' => $L->g('date-format-format')
));
// Type
echo Bootstrap::formSelectBlock(array(
'name' => 'typeSelector',
'label' => $L->g('Type'),
'selected' => '',
'options' => array(
'published' => '- ' . $L->g('Default') . ' -',
'sticky' => $L->g('Sticky'),
'static' => $L->g('Static')
),
'tip' => ''
));
// Position
echo Bootstrap::formInputTextBlock(array(
'name' => 'position',
'label' => $L->g('Position'),
'tip' => $L->g('Field used when ordering content by position'),
'value' => $pages->nextPositionNumber()
));
// Tags
echo Bootstrap::formInputTextBlock(array(
'name' => 'tags',
'label' => $L->g('Tags'),
'placeholder' => '',
'tip' => $L->g('Write the tags separated by comma')
));
// Parent
echo Bootstrap::formSelectBlock(array(
'name' => 'parent',
'label' => $L->g('Parent'),
'options' => array(),
'selected' => false,
'class' => '',
'tip' => $L->g('Start typing a page title to see a list of suggestions.'),
));
?>
<script>
$(document).ready(function() {
var parent = $("#jsparent").select2({
placeholder: "",
allowClear: true,
theme: "bootstrap4",
minimumInputLength: 2,
ajax: {
url: HTML_PATH_ADMIN_ROOT + "ajax/get-published",
data: function(params) {
var query = {
checkIsParent: true,
query: params.term
}
return query;
},
processResults: function(data) {
return data;
}
},
escapeMarkup: function(markup) {
return markup;
},
templateResult: function(data) {
var html = data.text;
if (data.type == "static") {
html += '<span class="badge badge-pill badge-light">' + data.type + '</span>';
}
return html;
}
});
});
</script>
<?php
// Template
echo Bootstrap::formInputTextBlock(array(
'name' => 'template',
'label' => $L->g('Template'),
'placeholder' => '',
'value' => '',
'tip' => $L->g('Write a template name to filter the page in the theme and change the style of the page.')
));
echo Bootstrap::formInputTextBlock(array(
'name' => 'externalCoverImage',
'label' => $L->g('External cover image'),
'placeholder' => "https://",
'value' => '',
'tip' => $L->g('Set a cover image from external URL, such as a CDN or some server dedicated for images.')
));
// Username
echo Bootstrap::formInputTextBlock(array(
'name' => '',
'label' => $L->g('Author'),
'placeholder' => '',
'value' => $login->username(),
'tip' => '',
'disabled' => true
));
?>
<script>
$(document).ready(function() {
// Changes in External cover image input
$("#jsexternalCoverImage").change(function() {
$("#jscoverImage").val($(this).val());
});
// Generate slug when the user type the title
$("#jstitle").keyup(function() {
var text = $(this).val();
var parent = $("#jsparent").val();
var currentKey = "";
var ajax = new bluditAjax();
var callBack = $("#jsslug");
ajax.generateSlug(text, parent, currentKey, callBack);
});
// Datepicker
$("#jsdate").datetimepicker({
format: DB_DATE_FORMAT
});
});
</script>
</div>
<?php if (!empty($site->customFields())) : ?>
<div id="nav-custom" class="tab-pane fade" role="tabpanel" aria-labelledby="custom-tab">
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (!isset($options['position'])) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : '')
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => (isset($options['checked']) ? true : false),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : '')
));
}
}
}
?>
</div>
<?php endif ?>
<div id="nav-seo" class="tab-pane fade" role="tabpanel" aria-labelledby="seo-tab">
<?php
// Friendly URL
echo Bootstrap::formInputTextBlock(array(
'name' => 'slug',
'tip' => $L->g('URL associated with the content'),
'label' => $L->g('Friendly URL'),
'placeholder' => $L->g('Leave empty for autocomplete by Bludit.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noindex',
'label' => 'Robots',
'labelForCheckbox' => $L->g('apply-code-noindex-code-to-this-page'),
'placeholder' => '',
'checked' => false,
'tip' => $L->g('This tells search engines not to show this page in their search results.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'nofollow',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-nofollow-code-to-this-page'),
'placeholder' => '',
'checked' => false,
'tip' => $L->g('This tells search engines not to follow links on this page.')
));
// Robots
echo Bootstrap::formCheckbox(array(
'name' => 'noarchive',
'label' => '',
'labelForCheckbox' => $L->g('apply-code-noarchive-code-to-this-page'),
'placeholder' => '',
'checked' => false,
'tip' => $L->g('This tells search engines not to save a cached copy of this page.')
));
?>
</div>
</div>
</div>
<!-- Custom fields: TOP -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'top')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => (isset($options['checked']) ? true : false),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mb-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
<!-- Title -->
<div id="jseditorTitle" class="form-group mb-1">
<input id="jstitle" name="title" type="text" dir="auto" class="form-control form-control-lg rounded-0" value="" placeholder="<?php $L->p('Enter title') ?>">
</div>
<!-- Editor -->
<textarea id="jseditor" class="editable h-100 mb-1"></textarea>
<!-- Custom fields: BOTTOM -->
<?php
$customFields = $site->customFields();
foreach ($customFields as $field => $options) {
if (isset($options['position']) && ($options['position'] == 'bottom')) {
if ($options['type'] == "string") {
echo Bootstrap::formInputTextBlock(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'value' => (isset($options['default']) ? $options['default'] : ''),
'tip' => (isset($options['tip']) ? $options['tip'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
} elseif ($options['type'] == "bool") {
echo Bootstrap::formCheckbox(array(
'name' => 'custom[' . $field . ']',
'label' => (isset($options['label']) ? $options['label'] : ''),
'placeholder' => (isset($options['placeholder']) ? $options['placeholder'] : ''),
'checked' => (isset($options['checked']) ? true : false),
'labelForCheckbox' => (isset($options['tip']) ? $options['tip'] : ''),
'class' => 'mt-2',
'labelClass' => 'mb-2 pb-2 border-bottom text-uppercase w-100'
));
}
}
}
?>
</form>
<!-- Modal for Media Manager -->
<?php include(PATH_ADMIN_THEMES . 'booty/html/media.php'); ?>
<script>
$(document).ready(function() {
// Define function if they doesn't exist
// This helps if the user doesn't activate any plugin as editor
if (typeof editorGetContent != "function") {
window.editorGetContent = function() {
return $("#jseditor").val();
};
}
if (typeof editorInsertMedia != "function") {
window.editorInsertMedia = function(filename) {
$("#jseditor").val($('#jseditor').val() + '<img src="' + filename + '" alt="">');
};
}
if (typeof editorInsertLinkedMedia != "function") {
window.editorInsertLinkedMedia = function(filename, link) {
$("#jseditor").val($('#jseditor').val() + '<a href="' + link + '"><img src="' + filename + '" alt=""></a>');
};
}
// Button switch
$("#jsbuttonSwitch").on("click", function() {
if ($(this).data("switch") == "publish") {
$(this).html('<i class="fa fa-square switch-icon-draft"></i> <?php $L->p('Draft') ?>');
$(this).data("switch", "draft");
} else {
$(this).html('<i class="fa fa-square switch-icon-publish"></i> <?php $L->p('Publish') ?>');
$(this).data("switch", "publish");
}
});
// Button preview
$("#jsbuttonPreview").on("click", function() {
var uuid = $("#jsuuid").val();
var title = $("#jstitle").val();
var content = editorGetContent();
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
var preview = window.open("<?php echo DOMAIN_PAGES . 'autosave-' . $uuid . '?preview=' . md5('autosave-' . $uuid) ?>", "bludit-preview");
preview.focus();
});
});
// Button Save
$("#jsbuttonSave").on("click", function() {
let actionParameters = '';
// If the switch is setted to "published", get the value from the selector
if ($("#jsbuttonSwitch").data("switch") == "publish") {
var value = $("#jstypeSelector option:selected").val();
$("#jstype").val(value);
actionParameters = '#' + value;
} else {
$("#jstype").val("draft");
actionParameters = '#draft';
}
// Get the content
$("#jscontent").val(editorGetContent());
// Submit the form
$("#jsform").attr('action', actionParameters);
$("#jsform").submit();
});
// Autosave
var currentContent = editorGetContent();
setInterval(function() {
var uuid = $("#jsuuid").val();
var title = $("#jstitle").val() + "[<?php $L->p('Autosave') ?>]";
var content = editorGetContent();
// Autosave when content has at least 100 characters
if (content.length < 100) {
return false;
}
// Autosave only when the user change the content
if (currentContent != content) {
currentContent = content;
bluditAjax.saveAsDraft(uuid, title, content).then(function(data) {
if (data.status == 0) {
showAlert("<?php $L->p('Autosave') ?>");
}
});
}
}, 1000 * 60 * AUTOSAVE_INTERVAL);
});
</script>

View file

@ -1,67 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'users' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Add a new user'), 'icon'=>'user')); ?>
</div>
<?php
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
echo Bootstrap::formInputText(array(
'name'=>'new_username',
'label'=>$L->g('Username'),
'value'=>(isset($_POST['new_username'])?$_POST['new_username']:''),
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formInputText(array(
'name'=>'new_password',
'type'=>'password',
'label'=>$L->g('Password'),
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formInputText(array(
'name'=>'confirm_password',
'type'=>'password',
'label'=>$L->g('Confirm Password'),
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
echo Bootstrap::formSelect(array(
'name'=>'role',
'label'=>$L->g('Role'),
'options'=>array('author'=>$L->g('Author'), 'editor'=>$L->g('Editor'), 'admin'=>$L->g('Administrator')),
'selected'=>'Author',
'class'=>'',
'tip'=>$L->g('author-can-write-and-edit-their-own-content')
));
echo Bootstrap::formInputText(array(
'name'=>'email',
'label'=>$L->g('Email'),
'value'=>(isset($_POST['email'])?$_POST['email']:''),
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
?>
<?php echo Bootstrap::formClose(); ?>

View file

@ -1,51 +1,80 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
<div class="align-middle">
<div class="float-right mt-1">
<button type="button" class="btn btn-primary btn-sm jsbuttonSave" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a>
// ============================================================================
// Functions for the view
// ============================================================================
function changePluginsPosition() {
$("li.list-group-item").each(function(index, value) {
var args = {
position: index,
className: $(this).data("class-name")
};
console.log(index);
api.configurePlugin(args).then(function(response) {
if (response.status == 0) {
logs('Plugin configured: ' + response.data.key);
} else {
logs('An error occurred while trying to configured the plugin.');
showAlertError(response.message);
}
});
});
showAlertInfo("<?php $L->p('The changes have been saved') ?>");
}
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
$("#btnSave").on("click", function() {
changePluginsPosition();
});
});
// ============================================================================
// Initlization for the view
// ============================================================================
$(document).ready(function() {
$('.list-group-sortable').sortable({
placeholderClass: 'list-group-item'
});
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-arrow-down-up"></i><?php $L->p('Plugins position') ?></h2>
<div class="ms-auto">
<button id="btnSave" type="button" class="btn btn-primary btn-sm"><?php $L->p('Save') ?></button>
<a id="btnCancel" class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Plugins position'), 'icon'=>'tags')); ?>
</div>
<div class="alert alert-primary"><?php $L->p('Drag and Drop to sort the plugins') ?></div>
<div class="alert alert-primary">
<?php $L->p('Drag and Drop to sort the plugins') ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
<?php echo Bootstrap::formTitle(array('title' => $L->g('Website plugins'))) ?>
echo Bootstrap::formInputHidden(array(
'name'=>'plugin-list',
'value'=>''
));
<ul class="website-plugins list-group list-group-sortable">
<?php foreach ($plugins['siteSidebar'] as $plugin): ?>
<li class="list-group-item" data-class-name="<?php echo $plugin->className() ?>">
<i class="bi bi-arrows-expand"></i><?php echo $plugin->name() ?>
</li>
<?php endforeach; ?>
</ul>
echo '<ul class="list-group list-group-sortable">';
foreach ($plugins['siteSidebar'] as $Plugin) {
echo '<li class="list-group-item" data-plugin="'.$Plugin->className().'"><span class="fa fa-arrows-v"></span> '.$Plugin->name().'</li>';
}
echo '</ul>';
?>
<?php echo Bootstrap::formTitle(array('title' => $L->g('Dashboard plugins'))) ?>
<?php echo Bootstrap::formClose(); ?>
<script>
$(document).ready(function() {
$('.list-group-sortable').sortable({
placeholderClass: 'list-group-item'
});
$(".jsbuttonSave").on("click", function() {
var tmp = [];
$("li.list-group-item").each(function() {
tmp.push( $(this).attr("data-plugin") );
});
$("#jsplugin-list").attr("value", tmp.join(",") );
$("#jsform").submit();
});
});
</script>
<ul class="dashboard-plugins list-group list-group-sortable">
<?php foreach ($plugins['dashboard'] as $plugin): ?>
<li class="list-group-item" data-class-name="<?php echo $plugin->className() ?>">
<i class="bi bi-arrows-expand"></i><?php echo $plugin->name() ?>
</li>
<?php endforeach; ?>
</ul>

View file

@ -0,0 +1,74 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
function configurePlugin(className) {
var args = {
className: className
};
$('input').each(function() {
var key = $(this).attr('name');
var value = $(this).val();
args[key] = value;
});
$('select').each(function() {
var key = $(this).attr('name');
var value = $(this).val();
args[key] = value;
});
api.configurePlugin(args).then(function(response) {
if (response.status == 0) {
logs('Plugin configured: ' + response.data.key);
showAlertInfo("<?php $L->p('The changes have been saved') ?>");
} else {
logs('An error occurred while trying to configured the plugin.');
showAlertError(response.message);
}
});
}
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
$('#btnSave').on('click', function() {
var className = $(this).data('class-name');
configurePlugin(className);
});
});
// ============================================================================
// Initlization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-node-plus"></i><?php echo $plugin->name() ?></h2>
<?php if ($plugin->formButtons()) : ?>
<div class="ms-auto">
<button id="btnSave" type="button" class="btn btn-primary btn-sm" data-class-name="<?php echo $plugin->className() ?>"><?php $L->p('Save') ?></button>
<a id="btnCancel" class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'plugins' ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php endif; ?>
</div>
<?php
if ($plugin->description()) {
echo '<div class="alert alert-primary" role="alert">'.$plugin->description().'</div>';
}
echo $plugin->form();
?>

View file

@ -1,20 +1,49 @@
<?php
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
echo Bootstrap::pageTitle(array('title' => $L->g('Plugins'), 'icon' => 'puzzle-piece'));
echo Bootstrap::link(array(
'title' => $L->g('Change the position of the plugins'),
'href' => HTML_PATH_ADMIN_ROOT . 'plugins-position',
'icon' => 'arrows'
));
echo Bootstrap::formTitle(array('title' => $L->g('Search plugins')));
?>
<input type="text" dir="auto" class="form-control" id="search" placeholder="<?php $L->p('Search') ?>">
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
function activatePlugin(className) {
var args = {
className: className
};
api.activatePlugin(args).then(function(response) {
if (response.status == 0) {
logs('Plugin activated: ' + response.data.key);
window.location.replace('<?php echo HTML_PATH_ADMIN_ROOT . 'plugins-settings/' ?>'+response.data.key);
} else {
logs('An error occurred while trying to activate the plugin.');
showAlertError(response.message);
}
});
}
function deactivatePlugin(className) {
var args = {
className: className
};
api.deactivatePlugin(args).then(function(response) {
if (response.status == 0) {
logs('Plugin deactivated: ' + response.data.key);
window.location.replace('<?php echo HTML_PATH_ADMIN_ROOT . 'plugins' ?>');
} else {
logs('An error occurred while trying to deactivate the plugin.');
showAlertError(response.message);
}
});
}
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
$("#search").on("keyup", function() {
var textToSearch = $(this).val().toLowerCase();
$(".searchItem").each(function() {
@ -28,35 +57,62 @@ echo Bootstrap::formTitle(array('title' => $L->g('Search plugins')));
});
});
});
$('.activatePlugin').on('click', function() {
var className = $(this).data('class-name');
activatePlugin(className);
});
$('.deactivatePlugin').on('click', function() {
var className = $(this).data('class-name');
deactivatePlugin(className);
});
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// nothing here yet
// how do you hang your toilet paper ? over or under ?
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-node-plus"></i><?php $L->p('Plugins') ?></h2>
<div class="ms-auto">
<a id="btnNew" class="btn btn-primary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'plugins-position' ?>" role="button"><i class="bi bi-plus-circle"></i><?php $L->p('Change plugins position') ?></a>
</div>
</div>
<?php echo Bootstrap::formTitle(array('icon' => 'search', 'title' => $L->g('Search plugins'))); ?>
<input type="text" class="form-control" id="search" placeholder="<?php $L->p('Search') ?>">
<?php
echo Bootstrap::formTitle(array('title' => $L->g('Enabled plugins')));
echo Bootstrap::formTitle(array('icon' => 'check-square', 'title' => $L->g('Enabled plugins')));
echo '
<table class="table">
<table class="table table-striped">
<tbody>
';
// Show installed plugins
foreach ($pluginsInstalled as $plugin) {
if ($plugin->type() == 'theme') {
// Do not display theme's plugins
continue;
}
echo '<tr id="' . $plugin->className() . '" class="bg-light searchItem">';
echo '<tr id="' . $plugin->className() . '" class="searchItem">';
echo '<td class="align-middle pt-3 pb-3 w-25">
<div class="searchText">' . $plugin->name() . '</div>
<div class="mt-1">';
if (method_exists($plugin, 'form')) {
echo '<a class="mr-3" href="' . HTML_PATH_ADMIN_ROOT . 'configure-plugin/' . $plugin->className() . '">' . $L->g('Settings') . '</a>';
echo '<a class="me-3" href="' . HTML_PATH_ADMIN_ROOT . 'plugins-settings/' . $plugin->className() . '">' . $L->g('Settings') . '</a>';
}
// You can not disable a plugin for an activated theme
if ($plugin->type()!='theme') {
echo '<span class="link deactivatePlugin" data-class-name="' . $plugin->className() . '">' . $L->g('Deactivate') . '</a>';
}
echo '<a href="' . HTML_PATH_ADMIN_ROOT . 'uninstall-plugin/' . $plugin->className() . '">' . $L->g('Deactivate') . '</a>';
echo '</div>';
echo '</td>';
@ -80,27 +136,22 @@ echo '
</table>
';
echo Bootstrap::formTitle(array('title' => $L->g('Disabled plugins')));
echo Bootstrap::formTitle(array('icon' => 'dash-square', 'title' => $L->g('Disabled plugins')));
echo '
<table class="table">
<table class="table table-striped">
<tbody>
';
// Plugins not installed
$pluginsNotInstalled = array_diff_key($plugins['all'], $pluginsInstalled);
foreach ($pluginsNotInstalled as $plugin) {
if ($plugin->type() == 'theme') {
// Do not display theme's plugins
continue;
}
echo '<tr id="' . $plugin->className() . '" class="searchItem">';
echo '<td class="align-middle pt-3 pb-3 w-25">
<div class="searchText">' . $plugin->name() . '</div>
<div class="mt-1">
<a href="' . HTML_PATH_ADMIN_ROOT . 'install-plugin/' . $plugin->className() . '">' . $L->g('Activate') . '</a>
<span class="link activatePlugin" data-class-name="' . $plugin->className() . '">' . $L->g('Activate') . '</a>
</div>
</td>';

File diff suppressed because it is too large Load diff

View file

@ -1,57 +1,83 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// No events for the view yet
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<?php
echo Bootstrap::pageTitle(array('title' => $L->g('Themes'), 'icon' => 'desktop'));
echo Bootstrap::pageTitle(array('title'=>$L->g('Themes'), 'icon'=>'eye'));
echo '
<table class="table mt-3">
<table class="table table-striped mt-3">
<thead>
<tr>
<th class="border-bottom-0 w-25" scope="col">' . $L->g('Name') . '</th>
<th class="border-bottom-0 d-none d-sm-table-cell" scope="col">' . $L->g('Description') . '</th>
<th class="text-center border-bottom-0 d-none d-lg-table-cell" scope="col">' . $L->g('Version') . '</th>
<th class="text-center border-bottom-0 d-none d-lg-table-cell" scope="col">' . $L->g('Author') . '</th>
<th class="border-bottom-0 w-25" scope="col">'.$L->g('Name').'</th>
<th class="border-bottom-0 d-none d-sm-table-cell" scope="col">'.$L->g('Description').'</th>
<th class="text-center border-bottom-0 d-none d-lg-table-cell" scope="col">'.$L->g('Version').'</th>
<th class="text-center border-bottom-0 d-none d-lg-table-cell" scope="col">'.$L->g('Author').'</th>
</tr>
</thead>
<tbody>
';
foreach ($themes as $theme) {
echo '
<tr ' . ($theme['dirname'] == $site->theme() ? 'class="bg-light"' : '') . '>
<td class="align-middle pt-3 pb-3">
<div>'.$theme['name'].($theme['dirname']==$site->theme()?'<span class="badge badge-primary ml-2">'.$L->g('Active').'</span>':'').'</div>
echo '
<tr>
<td class="align-middle pt-4 pb-4">
<div>'.$theme['name'].($theme['dirname']==$site->theme()?'<span class="badge bg-primary ms-2">Active</span>':'').'</div>
<div class="mt-1">
';
if ($theme['dirname'] != $site->theme()) {
echo '<a href="' . HTML_PATH_ADMIN_ROOT . 'install-theme/' . $theme['dirname'] . '">' . $L->g('Activate') . '</a>';
} else {
if (isset($theme['plugin'])) {
echo '<a href="' . HTML_PATH_ADMIN_ROOT . 'configure-plugin/' . $theme['plugin'] . '">' . $L->g('Settings') . '</a>';
}
}
if ($theme['dirname']!=$site->theme()) {
echo '<a href="'.HTML_PATH_ADMIN_ROOT.'install-theme/'.$theme['dirname'].'">'.$L->g('Activate').'</a>';
} else {
if (isset($theme['plugin'])) {
echo '<a href="' . HTML_PATH_ADMIN_ROOT . 'plugins-settings/' . $theme['plugin'] . '">' . $L->g('Settings') . '</a>';
}
}
echo '
echo '
</div>
</td>
';
echo '<td class="align-middle d-none d-sm-table-cell">';
echo $theme['description'];
echo '</td>';
echo '<td class="align-middle d-none d-sm-table-cell">';
echo $theme['description'];
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">';
echo '<span>' . $theme['version'] . '</span>';
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">';
echo '<span>'.$theme['version'].'</span>';
echo '</td>';
echo '<td class="text-center align-middle d-none d-lg-table-cell">
<a target="_blank" href="' . $theme['website'] . '">' . $theme['author'] . '</a>
echo '<td class="text-center align-middle d-none d-lg-table-cell">
<a target="_blank" href="'.$theme['website'].'">'.$theme['author'].'</a>
</td>';
echo '</tr>';
echo '</tr>';
}
echo '
</tbody>
</table>
';
';

View file

@ -1,60 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<?php echo Bootstrap::formOpen(array('id'=>'jsform', 'class'=>'tab-content')); ?>
<div class="align-middle">
<div class="float-right mt-1">
<button type="submit" class="btn btn-primary btn-sm" name="save"><?php $L->p('Save') ?></button>
<a class="btn btn-secondary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT.'edit-user/'.$user->username() ?>" role="button"><?php $L->p('Cancel') ?></a>
</div>
<?php echo Bootstrap::pageTitle(array('title'=>$L->g('Change password'), 'icon'=>'user')); ?>
</div>
<?php
// Token CSRF
echo Bootstrap::formInputHidden(array(
'name'=>'tokenCSRF',
'value'=>$security->getTokenCSRF()
));
// Username
echo Bootstrap::formInputHidden(array(
'name'=>'username',
'value'=>$user->username()
));
// Username disabled
echo Bootstrap::formInputText(array(
'name'=>'usernameDisabled',
'label'=>$L->g('Username'),
'value'=>$user->username(),
'class'=>'',
'placeholder'=>'',
'disabled'=>true,
'tip'=>''
));
// New password
echo Bootstrap::formInputText(array(
'name'=>'newPassword',
'label'=>$L->g('New password'),
'type'=>'password',
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
// Confirm password
echo Bootstrap::formInputText(array(
'name'=>'confirmPassword',
'label'=>$L->g('Confirm new password'),
'type'=>'password',
'value'=>'',
'class'=>'',
'placeholder'=>'',
'tip'=>''
));
?>
<?php echo Bootstrap::formClose(); ?>

View file

@ -1,15 +1,37 @@
<?php defined('BLUDIT') or die('Bludit CMS.'); ?>
<script>
// ============================================================================
// Variables for the view
// ============================================================================
// ============================================================================
// Functions for the view
// ============================================================================
// ============================================================================
// Events for the view
// ============================================================================
$(document).ready(function() {
// No events for the view yet
});
// ============================================================================
// Initialization for the view
// ============================================================================
$(document).ready(function() {
// No initialization for the view yet
});
</script>
<div class="d-flex align-items-center mb-4">
<h2 class="m-0"><i class="bi bi-people"></i><?php $L->p('Users') ?></h2>
<div class="ms-auto">
<a id="btnNew" class="btn btn-primary btn-sm" href="<?php echo HTML_PATH_ADMIN_ROOT . 'add-user' ?>" role="button"><i class="bi bi-plus-circle"></i><?php $L->p('Add a new user') ?></a>
</div>
</div>
<?php
echo Bootstrap::pageTitle(array('title'=>$L->g('Users'), 'icon'=>'users'));
echo Bootstrap::link(array(
'title'=>$L->g('add-a-new-user'),
'href'=>HTML_PATH_ADMIN_ROOT.'new-user',
'icon'=>'plus'
));
echo '
<table class="table table-striped mt-3">
<thead>
@ -30,20 +52,20 @@ foreach ($list as $username) {
try {
$user = new User($username);
echo '<tr>';
echo '<td><img class="profilePicture mr-1" alt="" src="'.(Sanitize::pathFile(PATH_UPLOADS_PROFILES.$user->username().'.png')?DOMAIN_UPLOADS_PROFILES.$user->username().'.png':HTML_PATH_CORE_IMG.'default.svg').'" /><a href="'.HTML_PATH_ADMIN_ROOT.'edit-user/'.$username.'">'.$username.'</a></td>';
echo '<td class="d-none d-lg-table-cell">'.$user->nickname().'</td>';
echo '<td>'.$user->email().'</td>';
echo '<td>'.($user->enabled()?'<b>'.$L->g('Enabled').'</b>':$L->g('Disabled')).'</td>';
echo '<td class="pt-4 pb-4"><a href="'.HTML_PATH_ADMIN_ROOT.'edit-user/'.$username.'">'.$username.'</a></td>';
echo '<td class="pt-4 pb-4 d-none d-lg-table-cell">'.$user->nickname().'</td>';
echo '<td class="pt-4 pb-4">'.$user->email().'</td>';
echo '<td class="pt-4 pb-4">'.($user->enabled()?'<b>'.$L->g('Enabled').'</b>':'<b class="text-danger">'.$L->g('Disabled').'</b>').'</td>';
if ($user->role()=='admin') {
echo '<td>'.$L->g('Administrator').'</td>';
echo '<td class="pt-4 pb-4">'.$L->g('Administrator').'</td>';
} elseif ($user->role()=='editor') {
echo '<td>'.$L->g('Editor').'</td>';
echo '<td class="pt-4 pb-4">'.$L->g('Editor').'</td>';
} elseif ($user->role()=='author') {
echo '<td>'.$L->g('Author').'</td>';
echo '<td class="pt-4 pb-4">'.$L->g('Author').'</td>';
} else {
echo '<td>'.$L->g('Reader').'</td>';
echo '<td class="pt-4 pb-4">'.$L->g('Reader').'</td>';
}
echo '<td class="d-none d-lg-table-cell">'.Date::format($user->registered(), DB_DATE_FORMAT, ADMIN_PANEL_DATE_FORMAT).'</td>';
echo '<td class="pt-4 pb-4 d-none d-lg-table-cell">'.Date::format($user->registered(), DB_DATE_FORMAT, ADMIN_PANEL_DATE_FORMAT).'</td>';
echo '</tr>';
} catch (Exception $e) {
// Continue

View file

@ -16,13 +16,13 @@ $result = array();
if (Text::stringContains(Text::lowercase($L->g('New content')), $query)) {
$tmp = array('disabled'=>true, 'icon'=>'plus-circle', 'type'=>'menu');
$tmp['text'] = $L->g('New content');
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'new-content';
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'editor';
array_push($result, $tmp);
}
if (Text::stringContains(Text::lowercase($L->g('New category')), $query)) {
$tmp = array('disabled'=>true, 'icon'=>'tag', 'type'=>'menu');
$tmp['text'] = $L->g('New category');
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'new-category';
$tmp['url'] = HTML_PATH_ADMIN_ROOT.'add-category';
array_push($result, $tmp);
}
if (Text::stringContains(Text::lowercase($L->g('New user')), $query)) {

View file

@ -1,43 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
header('Content-Type: application/json');
/*
| Delete an image from a particular page
|
| @_POST['filename'] string Name of the file to delete
| @_POST['uuid'] string Page UUID
|
| @return array
*/
// $_POST
// ----------------------------------------------------------------------------
$filename = isset($_POST['filename']) ? $_POST['filename'] : false;
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
// ----------------------------------------------------------------------------
if ($filename===false) {
ajaxResponse(1, 'The filename is empty.');
}
if ($uuid && IMAGE_RESTRICT) {
$imagePath = PATH_UPLOADS_PAGES.$uuid.DS;
$thumbnailPath = PATH_UPLOADS_PAGES.$uuid.DS.'thumbnails'.DS;
} else {
$imagePath = PATH_UPLOADS;
$thumbnailPath = PATH_UPLOADS_THUMBNAILS;
}
// Delete image
if (Sanitize::pathFile($imagePath.$filename)) {
Filesystem::rmfile($imagePath.$filename);
}
// Delete thumbnail
if (Sanitize::pathFile($thumbnailPath.$filename)) {
Filesystem::rmfile($thumbnailPath.$filename);
}
ajaxResponse(0, 'Image deleted.');
?>

View file

@ -2,12 +2,14 @@
header('Content-Type: application/json');
/*
| Returns a list of pages and the title contains the query string
| The returned list have published, sticky and statics pages
| Returns a list of pages that the title contains the query string.
| The returned list have published, sticky and statics pages.
| It's possible to filter the pages are parents by the flag "checkIsParent".
|
| @_POST['query'] string The string to search in the title of the pages
| @_POST['query'] string The string to search in the title of the pages.
| @_POST['checkIsParent'] boolean TRUE returns only parent pages, FALSE returns all pages.
|
| @return array
| @return json Ex. {"results":[{"disabled":false,"id":"follow-bludit","text":"Follow Bludit","type":"published"}]}
*/
// $_GET

View file

@ -1,62 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
header('Content-Type: application/json');
/*
| Returns a list of images from a particular page
|
| @_POST['pageNumber'] int Page number for the paginator
| @_POST['path'] string Pre-defined name for the directory to read, its pre-defined to avoid security issues
| @_POST['uuid'] string Page UUID
|
| @return array
*/
// $_POST
// ----------------------------------------------------------------------------
// $_POST['pageNumber'] > 0
$pageNumber = empty($_POST['pageNumber']) ? 1 : (int)$_POST['pageNumber'];
$pageNumber = $pageNumber - 1;
$path = empty($_POST['path']) ? false : $_POST['path'];
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
// ----------------------------------------------------------------------------
// Set the path to get the file list
if ($path=='thumbnails') {
if ($uuid && IMAGE_RESTRICT) {
$path = PATH_UPLOADS_PAGES.$uuid.DS.'thumbnails'.DS;
} else {
$path = PATH_UPLOADS_THUMBNAILS;
}
} else {
ajaxResponse(1, 'Invalid path.');
}
// Get all files from the directory $path, also split the array by numberOfItems
// The function listFiles split in chunks
$listOfFilesByPage = Filesystem::listFiles($path, '*', '*', MEDIA_MANAGER_SORT_BY_DATE, MEDIA_MANAGER_NUMBER_OF_FILES);
// Check if the page number exists in the chunks
if (isset($listOfFilesByPage[$pageNumber])) {
// Get only the filename from the chunk
$files = array();
foreach ($listOfFilesByPage[$pageNumber] as $file) {
$filename = basename($file);
array_push($files, $filename);
}
// Returns the number of chunks for the paginator
// Returns the files inside the chunk
ajaxResponse(0, 'List of files and number of chunks.', array(
'numberOfPages'=>count($listOfFilesByPage),
'files'=>$files
));
}
ajaxResponse(0, 'List of files and number of chunks.', array(
'numberOfPages'=>0,
'files'=>array()
));
?>

View file

@ -1,22 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
header('Content-Type: application/json');
/*
| Delete the site logo
| This script delete the file and set and empty string in the database
|
| @return array
*/
// Delete the file
$logoFilename = $site->logo(false);
if ($logoFilename) {
Filesystem::rmfile(PATH_UPLOADS.$logoFilename);
}
// Remove the logo from the database
$site->set(array('logo'=>''));
ajaxResponse(0, 'Logo removed.');
?>

View file

@ -1,70 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
header('Content-Type: application/json');
/*
| Upload site logo
| The final filename is the site's name and the extension is the same as the file uploaded
|
| @_FILES['inputFile'] multipart/form-data File from form
|
| @return array
*/
if (!isset($_FILES['inputFile'])) {
ajaxResponse(1, 'Error trying to upload the site logo.');
}
// Check path traversal on $filename
if (Text::stringContains($_FILES['inputFile']['name'], DS, false)) {
$message = 'Path traversal detected.';
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// File extension
$fileExtension = Filesystem::extension($_FILES['inputFile']['name']);
$fileExtension = Text::lowercase($fileExtension);
if (!in_array($fileExtension, $GLOBALS['ALLOWED_IMG_EXTENSION'])) {
$message = $L->g('File type is not supported. Allowed types:').' '.implode(', ',$GLOBALS['ALLOWED_IMG_EXTENSION']);
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// File MIME Type
$fileMimeType = Filesystem::mimeType($_FILES['inputFile']['tmp_name']);
if ($fileMimeType!==false) {
if (!in_array($fileMimeType, $GLOBALS['ALLOWED_IMG_MIMETYPES'])) {
$message = $L->g('File mime type is not supported. Allowed types:').' '.implode(', ',$GLOBALS['ALLOWED_IMG_MIMETYPES']);
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
}
// Final filename
$filename = 'logo.'.$fileExtension;
if (Text::isNotEmpty( $site->title() )) {
$filename = $site->title().'.'.$fileExtension;
}
// Delete old image
$oldFilename = $site->logo(false);
if ($oldFilename) {
Filesystem::rmfile(PATH_UPLOADS.$oldFilename);
}
// Move from temporary directory to uploads
Filesystem::mv($_FILES['inputFile']['tmp_name'], PATH_UPLOADS.$filename);
// Permissions
chmod(PATH_UPLOADS.$filename, 0644);
// Store the filename in the database
$site->set(array('logo'=>$filename));
ajaxResponse(0, 'Image uploaded.', array(
'filename'=>$filename,
'absoluteURL'=>DOMAIN_UPLOADS.$filename,
'absolutePath'=>PATH_UPLOADS.$filename
));
?>

View file

@ -1,74 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
header('Content-Type: application/json');
// $_POST
// ----------------------------------------------------------------------------
// (string) $_POST['username']
$username = empty($_POST['username']) ? false : $_POST['username'];
// ----------------------------------------------------------------------------
if ($username===false) {
ajaxResponse(1, 'Error in username.');
}
if ( ($login->role()!='admin') && ($login->username()!=$username) ) {
ajaxResponse(1, 'Error in username.');
}
if (!isset($_FILES['profilePictureInputFile'])) {
ajaxResponse(1, 'Error trying to upload the profile picture.');
}
// Check path traversal
if (Text::stringContains($username, DS, false)) {
$message = 'Path traversal detected.';
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// Check file extension
$fileExtension = Filesystem::extension($_FILES['profilePictureInputFile']['name']);
$fileExtension = Text::lowercase($fileExtension);
if (!in_array($fileExtension, $GLOBALS['ALLOWED_IMG_EXTENSION']) ) {
$message = $L->g('File type is not supported. Allowed types:').' '.implode(', ',$GLOBALS['ALLOWED_IMG_EXTENSION']);
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// Check file MIME Type
$fileMimeType = Filesystem::mimeType($_FILES['profilePictureInputFile']['tmp_name']);
if ($fileMimeType!==false) {
if (!in_array($fileMimeType, $GLOBALS['ALLOWED_IMG_MIMETYPES'])) {
$message = $L->g('File mime type is not supported. Allowed types:').' '.implode(', ',$GLOBALS['ALLOWED_IMG_MIMETYPES']);
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
}
// Tmp filename
$tmpFilename = $username.'.'.$fileExtension;
// Final filename
$filename = $username.'.png';
// Move from temporary directory to uploads folder
rename($_FILES['profilePictureInputFile']['tmp_name'], PATH_TMP.$tmpFilename);
// Resize and convert to png
$image = new Image();
$image->setImage(PATH_TMP.$tmpFilename, PROFILE_IMG_WIDTH, PROFILE_IMG_HEIGHT, 'crop');
$image->saveImage(PATH_UPLOADS_PROFILES.$filename, PROFILE_IMG_QUALITY, false, true);
// Delete temporary file
Filesystem::rmfile(PATH_TMP.$tmpFilename);
// Permissions
chmod(PATH_UPLOADS_PROFILES.$filename, 0644);
ajaxResponse(0, 'Image uploaded.', array(
'filename'=>$filename,
'absoluteURL'=>DOMAIN_UPLOADS_PROFILES.$filename,
'absolutePath'=>PATH_UPLOADS_PROFILES.$filename
));
?>

View file

@ -1,95 +0,0 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
header('Content-Type: application/json');
/*
| Upload an image to a particular page
|
| @_POST['uuid'] string Page uuid
|
| @return array
*/
// $_POST
// ----------------------------------------------------------------------------
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
// ----------------------------------------------------------------------------
// Check path traversal on $uuid
if ($uuid) {
if (Text::stringContains($uuid, DS, false)) {
$message = 'Path traversal detected.';
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
}
// Set upload directory
if ($uuid && IMAGE_RESTRICT) {
$imageDirectory = PATH_UPLOADS_PAGES . $uuid . DS;
$thumbnailDirectory = $imageDirectory . 'thumbnails' . DS;
if (!Filesystem::directoryExists($thumbnailDirectory)) {
Filesystem::mkdir($thumbnailDirectory, true);
}
} else {
$imageDirectory = PATH_UPLOADS;
$thumbnailDirectory = PATH_UPLOADS_THUMBNAILS;
}
$images = array();
foreach ($_FILES['images']['name'] as $uuid => $filename) {
// Check for errors
if ($_FILES['images']['error'][$uuid] != 0) {
$message = $L->g('Maximum load file size allowed:') . ' ' . ini_get('upload_max_filesize');
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// Convert URL characters such as spaces or quotes to characters
$filename = urldecode($filename);
// Check path traversal on $filename
if (Text::stringContains($filename, DS, false)) {
$message = 'Path traversal detected.';
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// Check file extension
$fileExtension = Filesystem::extension($filename);
$fileExtension = Text::lowercase($fileExtension);
if (!in_array($fileExtension, $GLOBALS['ALLOWED_IMG_EXTENSION'])) {
$message = $L->g('File type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_EXTENSION']);
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// Check file MIME Type
$fileMimeType = Filesystem::mimeType($_FILES['images']['tmp_name'][$uuid]);
if ($fileMimeType !== false) {
if (!in_array($fileMimeType, $GLOBALS['ALLOWED_IMG_MIMETYPES'])) {
$message = $L->g('File mime type is not supported. Allowed types:') . ' ' . implode(', ', $GLOBALS['ALLOWED_IMG_MIMETYPES']);
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
}
// Move from PHP tmp file to Bludit tmp directory
Filesystem::mv($_FILES['images']['tmp_name'][$uuid], PATH_TMP . $filename);
// Transform the image and generate the thumbnail
$image = transformImage(PATH_TMP . $filename, $imageDirectory, $thumbnailDirectory);
if ($image) {
chmod($image, 0644);
$filename = Filesystem::filename($image);
array_push($images, $filename);
} else {
$message = 'Error after transformImage() function.';
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
}
ajaxResponse(0, 'Images uploaded.', array(
'images' => $images
));

View file

@ -1,14 +1,20 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// Start the session
// If the session is not possible to start the admin area is not available
Session::start($site->urlPath(), $site->isHTTPS());
// If the session is not started the admin area is not available
Session::start();
if (Session::started()===false) {
exit('Bludit CMS. Session initialization failed.');
}
// The login object contains the authentication system and/or the current user logged
$login = new Login();
// Initialize plugins
include(PATH_RULES.'60.plugins.php');
// Parameters for the controller and view
// For example "title" keeps the HTML tag <title>
$layout = array(
'controller'=>null,
'view'=>null,
@ -19,14 +25,14 @@ $layout = array(
'title'=>'Bludit'
);
// Get the Controller
// Get from the URL the controller and view
$explodeSlug = $url->explodeSlug();
$layout['controller'] = $layout['view'] = $layout['slug'] = empty($explodeSlug[0])?'dashboard':$explodeSlug[0];
unset($explodeSlug[0]);
// Get the Plugins
include(PATH_RULES.'60.plugins.php');
// Check if the user want to access to an admin controller or view from a plugin
// Check if the user want to get access to an admin controller or view from a plugin
// To get access to a plugin controller or view the URL should be: http://localhost/admin/plugin/<PLUGIN NAME>
// $explodeSlug = [0=>'<PLUGIN NAME>']
if ($layout['controller'] === 'plugin' && !empty($explodeSlug)) {
// Lowercase plugins class name to search by case-insensitive
$pluginsLowerCases = array_change_key_case($pluginsInstalled);
@ -46,59 +52,57 @@ if ($layout['slug']==='ajax') {
include(PATH_RULES.'99.security.php');
// Load the ajax file
if (Sanitize::pathFile(PATH_AJAX, $layout['parameters'].'.php')) {
if (Sanitize::pathFile(PATH_AJAX.$layout['parameters'].'.php')) {
include(PATH_AJAX.$layout['parameters'].'.php');
}
}
header('HTTP/1.1 401 User not logged.');
exit(0);
}
// --- ADMIN AREA ---
else
{
// Boot rules
include(PATH_RULES.'69.pages.php');
include(PATH_RULES.'99.header.php');
include(PATH_RULES.'99.paginator.php');
include(PATH_RULES.'99.themes.php');
include(PATH_RULES.'99.security.php');
// Page not found.
// User not logged.
// Slug is login.
if ($url->notFound() || !$login->isLogged() || ($url->slug()==='login') ) {
$layout['controller'] = 'login';
$layout['view'] = 'login';
$layout['template'] = 'login.php';
// Boot rules
include(PATH_RULES.'69.pages.php');
include(PATH_RULES.'99.header.php');
include(PATH_RULES.'99.paginator.php');
include(PATH_RULES.'99.themes.php');
include(PATH_RULES.'99.security.php');
// Generate the tokenCSRF for the user not logged, when the user log-in the token will be change.
$security->generateTokenCSRF();
}
// Define layout login-form for:
// - User not logged
// - Page not found
// - Slug is login. http://localhost/admin/login
if ($url->notFound() || !$login->isLogged() || ($url->slug()==='login') ) {
$layout['controller'] = 'login';
$layout['view'] = 'login';
$layout['template'] = 'login.php';
// Define variables
$ADMIN_CONTROLLER = $layout['controller'];
$ADMIN_VIEW = $layout['view'];
// Load plugins before the admin area will be load.
Theme::plugins('beforeAdminLoad');
// Load init.php if the theme has one.
if (Sanitize::pathFile(PATH_ADMIN_THEMES, $site->adminTheme().DS.'init.php')) {
include(PATH_ADMIN_THEMES.$site->adminTheme().DS.'init.php');
}
// Load controller.
if (Sanitize::pathFile(PATH_ADMIN_CONTROLLERS, $layout['controller'].'.php')) {
include(PATH_ADMIN_CONTROLLERS.$layout['controller'].'.php');
} elseif ($layout['plugin'] && method_exists($layout['plugin'], 'adminController')) {
$layout['plugin']->adminController();
}
// Load view and theme.
if (Sanitize::pathFile(PATH_ADMIN_THEMES, $site->adminTheme().DS.$layout['template'])) {
include(PATH_ADMIN_THEMES.$site->adminTheme().DS.$layout['template']);
}
// Load plugins after the admin area is loaded.
Theme::plugins('afterAdminLoad');
// Generate the tokenCSRF for the user not logged, when the user log-in the token will change
$security->generateTokenCSRF();
}
// Define global variables
$ADMIN_CONTROLLER = $layout['controller'];
$ADMIN_VIEW = $layout['view'];
// Execute plugins before load the admin area
execPluginsByHook('beforeAdminLoad');
// Load init.php if the theme has one
if (Sanitize::pathFile(PATH_ADMIN_THEMES.$site->adminTheme().DS.'init.php')) {
include(PATH_ADMIN_THEMES.$site->adminTheme().DS.'init.php');
}
// Load controller
if (Sanitize::pathFile(PATH_ADMIN_CONTROLLERS.$layout['controller'].'.php')) {
include(PATH_ADMIN_CONTROLLERS.$layout['controller'].'.php');
} elseif ($layout['plugin'] && method_exists($layout['plugin'], 'adminController')) {
$layout['plugin']->adminController();
}
// Load view and theme
if (Sanitize::pathFile(PATH_ADMIN_THEMES.$site->adminTheme().DS.$layout['template'])) {
include(PATH_ADMIN_THEMES.$site->adminTheme().DS.$layout['template']);
}
// Execute plugins after the admin area is loaded
execPluginsByHook('afterAdminLoad');

View file

@ -1,77 +1,69 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// Bludit version
define('BLUDIT_VERSION', '3.16.2');
define('BLUDIT_CODENAME', 'Valencia');
define('BLUDIT_RELEASE_DATE', '2024-08-23');
define('BLUDIT_BUILD', '20240806');
define('BLUDIT_VERSION', '4.0.0');
define('BLUDIT_CODENAME', '');
define('BLUDIT_RELEASE_DATE', '2021-05-23');
define('BLUDIT_BUILD', '20210523');
// Change to TRUE for debugging
// Debug mode
// Change to FALSE, for prevent warning or errors on browser
define('DEBUG_MODE', TRUE);
define('DEBUG_TYPE', 'INFO'); // INFO, TRACE
// This determines whether errors should be printed to the screen as part of the output or if they should be hidden from the user.
ini_set("display_errors", 0);
// Even when display_errors is on, errors that occur during PHP's startup sequence are not displayed.
// It's strongly recommended to keep display_startup_errors off, except for debugging.
ini_set('display_startup_errors', 0);
// If disabled, error message will be solely plain text instead HTML code.
ini_set("html_errors", 0);
// Tells whether script error messages should be logged to the server's error log or error_log.
ini_set('log_errors', 1);
error_reporting(0); // Turn off all error reporting
if (DEBUG_MODE) {
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
} else {
error_reporting(E_ERROR);
// Turn on all error reporting
ini_set("display_errors", 0);
ini_set('display_startup_errors',0);
ini_set("html_errors", 1);
ini_set('log_errors', 1);
error_reporting(E_ALL | E_STRICT | E_NOTICE);
}
// PHP paths
// PATH_ROOT and PATH_BOOT are defined in index.php
define('PATH_LANGUAGES', PATH_ROOT . 'bl-languages' . DS);
define('PATH_THEMES', PATH_ROOT . 'bl-themes' . DS);
define('PATH_PLUGINS', PATH_ROOT . 'bl-plugins' . DS);
define('PATH_KERNEL', PATH_ROOT . 'bl-kernel' . DS);
define('PATH_CONTENT', PATH_ROOT . 'bl-content' . DS);
define('PATH_LANGUAGES', PATH_ROOT.'bl-languages'.DS);
define('PATH_THEMES', PATH_ROOT.'bl-themes'.DS);
define('PATH_PLUGINS', PATH_ROOT.'bl-plugins'.DS);
define('PATH_KERNEL', PATH_ROOT.'bl-kernel'.DS);
define('PATH_CONTENT', PATH_ROOT.'bl-content'.DS);
define('PATH_ABSTRACT', PATH_KERNEL . 'abstract' . DS);
define('PATH_RULES', PATH_KERNEL . 'boot' . DS . 'rules' . DS);
define('PATH_HELPERS', PATH_KERNEL . 'helpers' . DS);
define('PATH_AJAX', PATH_KERNEL . 'ajax' . DS);
define('PATH_CORE_JS', PATH_KERNEL . 'js' . DS);
define('PATH_ABSTRACT', PATH_KERNEL.'abstract'.DS);
define('PATH_RULES', PATH_KERNEL.'boot'.DS.'rules'.DS);
define('PATH_HELPERS', PATH_KERNEL.'helpers'.DS);
define('PATH_AJAX', PATH_KERNEL.'ajax'.DS);
define('PATH_CORE_JS', PATH_KERNEL.'js'.DS);
define('PATH_PAGES', PATH_CONTENT . 'pages' . DS);
define('PATH_DATABASES', PATH_CONTENT . 'databases' . DS);
define('PATH_PLUGINS_DATABASES', PATH_CONTENT . 'databases' . DS . 'plugins' . DS);
define('PATH_TMP', PATH_CONTENT . 'tmp' . DS);
define('PATH_UPLOADS', PATH_CONTENT . 'uploads' . DS);
define('PATH_WORKSPACES', PATH_CONTENT . 'workspaces' . DS);
define('PATH_PAGES', PATH_CONTENT.'pages'.DS);
define('PATH_DATABASES', PATH_CONTENT.'databases'.DS);
define('PATH_PLUGINS_DATABASES',PATH_CONTENT.'databases'.DS.'plugins'.DS);
define('PATH_THEMES_DATABASES', PATH_CONTENT.'databases'.DS.'themes'.DS);
define('PATH_TMP', PATH_CONTENT.'tmp'.DS);
define('PATH_UPLOADS', PATH_CONTENT.'uploads'.DS);
define('PATH_WORKSPACES', PATH_CONTENT.'workspaces'.DS);
define('PATH_UPLOADS_PAGES', PATH_UPLOADS . 'pages' . DS);
define('PATH_UPLOADS_PROFILES', PATH_UPLOADS . 'profiles' . DS);
define('PATH_UPLOADS_THUMBNAILS', PATH_UPLOADS . 'thumbnails' . DS);
define('PATH_UPLOADS_PAGES', PATH_UPLOADS.'pages'.DS);
define('PATH_UPLOADS_PROFILES', PATH_UPLOADS.'profiles'.DS);
define('PATH_UPLOADS_THUMBNAILS',PATH_UPLOADS.'thumbnails'.DS);
define('PATH_ADMIN', PATH_KERNEL . 'admin' . DS);
define('PATH_ADMIN_THEMES', PATH_ADMIN . 'themes' . DS);
define('PATH_ADMIN_CONTROLLERS', PATH_ADMIN . 'controllers' . DS);
define('PATH_ADMIN_VIEWS', PATH_ADMIN . 'views' . DS);
define('PATH_ADMIN', PATH_KERNEL.'admin'.DS);
define('PATH_ADMIN_THEMES', PATH_ADMIN.'themes'.DS);
define('PATH_ADMIN_CONTROLLERS',PATH_ADMIN.'controllers'.DS);
define('PATH_ADMIN_VIEWS', PATH_ADMIN.'views'.DS);
define('DEBUG_FILE', PATH_CONTENT . 'debug.txt');
define('DEBUG_FILE', PATH_CONTENT.'debug.txt');
// PAGES DATABASE
define('DB_PAGES', PATH_DATABASES . 'pages.php');
define('DB_SITE', PATH_DATABASES . 'site.php');
define('DB_CATEGORIES', PATH_DATABASES . 'categories.php');
define('DB_TAGS', PATH_DATABASES . 'tags.php');
define('DB_SYSLOG', PATH_DATABASES . 'syslog.php');
define('DB_USERS', PATH_DATABASES . 'users.php');
define('DB_SECURITY', PATH_DATABASES . 'security.php');
define('DB_PAGES', PATH_DATABASES.'pages.php');
define('DB_SITE', PATH_DATABASES.'site.php');
define('DB_CATEGORIES', PATH_DATABASES.'categories.php');
define('DB_TAGS', PATH_DATABASES.'tags.php');
define('DB_SYSLOG', PATH_DATABASES.'syslog.php');
define('DB_USERS', PATH_DATABASES.'users.php');
define('DB_SECURITY', PATH_DATABASES.'security.php');
// User environment variables
include(PATH_KERNEL . 'boot' . DS . 'variables.php');
include(PATH_KERNEL.'boot'.DS.'variables.php');
// Set internal character encoding
mb_internal_encoding(CHARSET);
@ -80,50 +72,51 @@ mb_internal_encoding(CHARSET);
mb_http_output(CHARSET);
// Inclde Abstract Classes
include(PATH_ABSTRACT . 'dbjson.class.php');
include(PATH_ABSTRACT . 'dblist.class.php');
include(PATH_ABSTRACT . 'plugin.class.php');
include(PATH_ABSTRACT.'dbjson.class.php');
include(PATH_ABSTRACT.'dblist.class.php');
include(PATH_ABSTRACT.'plugin.class.php');
// Inclde Classes
include(PATH_KERNEL . 'pages.class.php');
include(PATH_KERNEL . 'users.class.php');
include(PATH_KERNEL . 'tags.class.php');
include(PATH_KERNEL . 'language.class.php');
include(PATH_KERNEL . 'site.class.php');
include(PATH_KERNEL . 'categories.class.php');
include(PATH_KERNEL . 'syslog.class.php');
include(PATH_KERNEL . 'pagex.class.php');
include(PATH_KERNEL . 'category.class.php');
include(PATH_KERNEL . 'tag.class.php');
include(PATH_KERNEL . 'user.class.php');
include(PATH_KERNEL . 'url.class.php');
include(PATH_KERNEL . 'login.class.php');
include(PATH_KERNEL . 'parsedown.class.php');
include(PATH_KERNEL . 'security.class.php');
include(PATH_KERNEL.'pages.class.php');
include(PATH_KERNEL.'users.class.php');
include(PATH_KERNEL.'tags.class.php');
include(PATH_KERNEL.'language.class.php');
include(PATH_KERNEL.'site.class.php');
include(PATH_KERNEL.'categories.class.php');
include(PATH_KERNEL.'syslog.class.php');
include(PATH_KERNEL.'page.class.php');
include(PATH_KERNEL.'category.class.php');
include(PATH_KERNEL.'tag.class.php');
include(PATH_KERNEL.'user.class.php');
include(PATH_KERNEL.'url.class.php');
include(PATH_KERNEL.'login.class.php');
include(PATH_KERNEL.'parsedown.class.php');
include(PATH_KERNEL.'security.class.php');
// Include functions
include(PATH_KERNEL . 'functions.php');
include(PATH_KERNEL.'functions.php');
// Include Helpers Classes
include(PATH_HELPERS . 'text.class.php');
include(PATH_HELPERS . 'log.class.php');
include(PATH_HELPERS . 'date.class.php');
include(PATH_HELPERS . 'theme.class.php');
include(PATH_HELPERS . 'session.class.php');
include(PATH_HELPERS . 'redirect.class.php');
include(PATH_HELPERS . 'sanitize.class.php');
include(PATH_HELPERS . 'valid.class.php');
include(PATH_HELPERS . 'email.class.php');
include(PATH_HELPERS . 'filesystem.class.php');
include(PATH_HELPERS . 'alert.class.php');
include(PATH_HELPERS . 'paginator.class.php');
include(PATH_HELPERS . 'image.class.php');
include(PATH_HELPERS . 'tcp.class.php');
include(PATH_HELPERS . 'dom.class.php');
include(PATH_HELPERS . 'cookie.class.php');
include(PATH_HELPERS.'text.class.php');
include(PATH_HELPERS.'log.class.php');
include(PATH_HELPERS.'date.class.php');
include(PATH_HELPERS.'session.class.php');
include(PATH_HELPERS.'redirect.class.php');
include(PATH_HELPERS.'sanitize.class.php');
include(PATH_HELPERS.'valid.class.php');
include(PATH_HELPERS.'email.class.php');
include(PATH_HELPERS.'filesystem.class.php');
include(PATH_HELPERS.'alert.class.php');
include(PATH_HELPERS.'paginator.class.php');
include(PATH_HELPERS.'simple-image.class.php');
include(PATH_HELPERS.'tcp.class.php');
include(PATH_HELPERS.'dom.class.php');
include(PATH_HELPERS.'cookie.class.php');
include(PATH_HELPERS.'bootstrap.class.php');
include(PATH_HELPERS.'html.class.php');
if (file_exists(PATH_KERNEL . 'bludit.pro.php')) {
include(PATH_KERNEL . 'bludit.pro.php');
if (file_exists(PATH_KERNEL.'bludit.pro.php')) {
include(PATH_KERNEL.'bludit.pro.php');
}
// Objects
@ -148,43 +141,44 @@ if (!empty($_SERVER['DOCUMENT_ROOT']) && !empty($_SERVER['SCRIPT_NAME']) && empt
$base = str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_NAME']);
$base = dirname($base);
} elseif (empty($base)) {
$base = empty($_SERVER['SCRIPT_NAME']) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
$base = empty( $_SERVER['SCRIPT_NAME'] ) ? $_SERVER['PHP_SELF'] : $_SERVER['SCRIPT_NAME'];
$base = dirname($base);
}
if (strpos($_SERVER['REQUEST_URI'], $base) !== 0) {
if (strpos($_SERVER['REQUEST_URI'], $base)!==0) {
$base = '/';
} elseif ($base != DS) {
} elseif ($base!=DS) {
$base = trim($base, '/');
$base = '/' . $base . '/';
$base = '/'.$base.'/';
} else {
// Workaround for Windows Web Servers
$base = '/';
}
define('HTML_PATH_ROOT', $base);
define('HTML_PATH_THEMES', HTML_PATH_ROOT . 'bl-themes/');
define('HTML_PATH_THEME', HTML_PATH_THEMES . $site->theme() . '/');
define('HTML_PATH_THEME_CSS', HTML_PATH_THEME . 'css/');
define('HTML_PATH_THEME_JS', HTML_PATH_THEME . 'js/');
define('HTML_PATH_THEME_IMG', HTML_PATH_THEME . 'img/');
define('HTML_PATH_ADMIN_ROOT', HTML_PATH_ROOT . ADMIN_URI_FILTER . '/');
define('HTML_PATH_ADMIN_THEME', HTML_PATH_ROOT . 'bl-kernel/admin/themes/' . $site->adminTheme() . '/');
define('HTML_PATH_ADMIN_THEME_JS', HTML_PATH_ADMIN_THEME . 'js/');
define('HTML_PATH_ADMIN_THEME_CSS', HTML_PATH_ADMIN_THEME . 'css/');
define('HTML_PATH_CORE_JS', HTML_PATH_ROOT . 'bl-kernel/js/');
define('HTML_PATH_CORE_CSS', HTML_PATH_ROOT . 'bl-kernel/css/');
define('HTML_PATH_CORE_IMG', HTML_PATH_ROOT . 'bl-kernel/img/');
define('HTML_PATH_CONTENT', HTML_PATH_ROOT . 'bl-content/');
define('HTML_PATH_UPLOADS', HTML_PATH_ROOT . 'bl-content/uploads/');
define('HTML_PATH_UPLOADS_PAGES', HTML_PATH_UPLOADS . 'pages/');
define('HTML_PATH_UPLOADS_PROFILES', HTML_PATH_UPLOADS . 'profiles/');
define('HTML_PATH_UPLOADS_THUMBNAILS', HTML_PATH_UPLOADS . 'thumbnails/');
define('HTML_PATH_PLUGINS', HTML_PATH_ROOT . 'bl-plugins/');
define('HTML_PATH_THEMES', HTML_PATH_ROOT.'bl-themes/');
define('HTML_PATH_THEME', HTML_PATH_THEMES.$site->theme().'/');
define('HTML_PATH_THEME_CSS', HTML_PATH_THEME.'css/');
define('HTML_PATH_THEME_JS', HTML_PATH_THEME.'js/');
define('HTML_PATH_THEME_IMG', HTML_PATH_THEME.'img/');
define('HTML_PATH_ADMIN_ROOT', HTML_PATH_ROOT.ADMIN_URI_FILTER.'/');
define('HTML_PATH_ADMIN_THEME', HTML_PATH_ROOT.'bl-kernel/admin/themes/'.$site->adminTheme().'/');
define('HTML_PATH_ADMIN_THEME_JS', HTML_PATH_ADMIN_THEME.'js/');
define('HTML_PATH_ADMIN_THEME_CSS', HTML_PATH_ADMIN_THEME.'css/');
define('HTML_PATH_CORE_JS', HTML_PATH_ROOT.'bl-kernel/js/');
define('HTML_PATH_CORE_VENDORS', HTML_PATH_ROOT.'bl-kernel/vendors/');
define('HTML_PATH_CORE_CSS', HTML_PATH_ROOT.'bl-kernel/css/');
define('HTML_PATH_CORE_IMG', HTML_PATH_ROOT.'bl-kernel/img/');
define('HTML_PATH_CONTENT', HTML_PATH_ROOT.'bl-content/');
define('HTML_PATH_UPLOADS', HTML_PATH_ROOT.'bl-content/uploads/');
define('HTML_PATH_UPLOADS_PAGES', HTML_PATH_UPLOADS.'pages/');
define('HTML_PATH_UPLOADS_PROFILES', HTML_PATH_UPLOADS.'profiles/');
define('HTML_PATH_UPLOADS_THUMBNAILS', HTML_PATH_UPLOADS.'thumbnails/');
define('HTML_PATH_PLUGINS', HTML_PATH_ROOT.'bl-plugins/');
// --- Objects with dependency ---
$language = new Language($site->language());
$url->checkFilters($site->uriFilters());
$language = new Language( $site->language() );
$url->checkFilters( $site->uriFilters() );
// --- CONSTANTS with dependency ---
@ -217,38 +211,40 @@ 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_PHP', THEME_DIR . 'php' . 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);
define('THEME_DIR_LANG', THEME_DIR . 'languages' . 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);
define('THEME_DIR_LANG', THEME_DIR.'languages'.DS);
// --- Absolute paths with domain ---
// This paths are absolutes for the user / web browsing.
define('DOMAIN', $site->domain());
define('DOMAIN_BASE', DOMAIN . HTML_PATH_ROOT);
define('DOMAIN_CORE_JS', DOMAIN . HTML_PATH_CORE_JS);
define('DOMAIN_CORE_CSS', DOMAIN . HTML_PATH_CORE_CSS);
define('DOMAIN_THEME', DOMAIN . HTML_PATH_THEME);
define('DOMAIN_THEME_CSS', DOMAIN . HTML_PATH_THEME_CSS);
define('DOMAIN_THEME_JS', DOMAIN . HTML_PATH_THEME_JS);
define('DOMAIN_THEME_IMG', DOMAIN . HTML_PATH_THEME_IMG);
define('DOMAIN_ADMIN_THEME', DOMAIN . HTML_PATH_ADMIN_THEME);
define('DOMAIN_ADMIN_THEME_CSS', DOMAIN . HTML_PATH_ADMIN_THEME_CSS);
define('DOMAIN_ADMIN_THEME_JS', DOMAIN . HTML_PATH_ADMIN_THEME_JS);
define('DOMAIN_UPLOADS', DOMAIN . HTML_PATH_UPLOADS);
define('DOMAIN_UPLOADS_PAGES', DOMAIN . HTML_PATH_UPLOADS_PAGES);
define('DOMAIN_UPLOADS_PROFILES', DOMAIN . HTML_PATH_UPLOADS_PROFILES);
define('DOMAIN_UPLOADS_THUMBNAILS', DOMAIN . HTML_PATH_UPLOADS_THUMBNAILS);
define('DOMAIN_PLUGINS', DOMAIN . HTML_PATH_PLUGINS);
define('DOMAIN_CONTENT', DOMAIN . HTML_PATH_CONTENT);
define('DOMAIN_BASE', DOMAIN.HTML_PATH_ROOT);
define('DOMAIN_CORE_JS', DOMAIN.HTML_PATH_CORE_JS);
define('DOMAIN_CORE_CSS', DOMAIN.HTML_PATH_CORE_CSS);
define('DOMAIN_CORE_VENDORS', DOMAIN.HTML_PATH_CORE_VENDORS);
define('DOMAIN_THEME', DOMAIN.HTML_PATH_THEME);
define('DOMAIN_THEME_CSS', DOMAIN.HTML_PATH_THEME_CSS);
define('DOMAIN_THEME_JS', DOMAIN.HTML_PATH_THEME_JS);
define('DOMAIN_THEME_IMG', DOMAIN.HTML_PATH_THEME_IMG);
define('DOMAIN_ADMIN_THEME', DOMAIN.HTML_PATH_ADMIN_THEME);
define('DOMAIN_ADMIN_THEME_CSS', DOMAIN.HTML_PATH_ADMIN_THEME_CSS);
define('DOMAIN_ADMIN_THEME_JS', DOMAIN.HTML_PATH_ADMIN_THEME_JS);
define('DOMAIN_UPLOADS', DOMAIN.HTML_PATH_UPLOADS);
define('DOMAIN_UPLOADS_PAGES', DOMAIN.HTML_PATH_UPLOADS_PAGES);
define('DOMAIN_UPLOADS_PROFILES', DOMAIN.HTML_PATH_UPLOADS_PROFILES);
define('DOMAIN_UPLOADS_THUMBNAILS', DOMAIN.HTML_PATH_UPLOADS_THUMBNAILS);
define('DOMAIN_PLUGINS', DOMAIN.HTML_PATH_PLUGINS);
define('DOMAIN_CONTENT', DOMAIN.HTML_PATH_CONTENT);
define('DOMAIN_ADMIN', DOMAIN_BASE . ADMIN_URI_FILTER . '/');
define('DOMAIN_ADMIN', DOMAIN_BASE.ADMIN_URI_FILTER.'/');
define('DOMAIN_TAGS', Text::addSlashes(DOMAIN_BASE . TAG_URI_FILTER, false, true));
define('DOMAIN_CATEGORIES', Text::addSlashes(DOMAIN_BASE . CATEGORY_URI_FILTER, false, true));
define('DOMAIN_PAGES', Text::addSlashes(DOMAIN_BASE . PAGE_URI_FILTER, false, true));
define('DOMAIN_TAGS', Text::addSlashes(DOMAIN_BASE.TAG_URI_FILTER, false, true));
define('DOMAIN_CATEGORIES', Text::addSlashes(DOMAIN_BASE.CATEGORY_URI_FILTER, false, true));
define('DOMAIN_PAGES', Text::addSlashes(DOMAIN_BASE.PAGE_URI_FILTER, false, true));
$ADMIN_CONTROLLER = '';
$ADMIN_VIEW = '';

View file

@ -1,7 +1,7 @@
<?php defined('BLUDIT') or die('Bludit CMS.');
// ============================================================================
// Variables
// Global Variables
// ============================================================================
$plugins = array(
@ -29,6 +29,9 @@ $plugins = array(
'paginator'=>array(),
'beforePageModify'=>array(),
'beforePageDelete'=>array(),
'afterPageCreate'=>array(),
'afterPageModify'=>array(),
'afterPageDelete'=>array(),
@ -37,12 +40,12 @@ $plugins = array(
'loginBodyBegin'=>array(),
'loginBodyEnd'=>array(),
'all'=>array()
'all'=>array() // $plugins['all'] keep installed and not installed plugins
);
$pluginsEvents = $plugins;
unset($pluginsEvents['all']);
// This array has only the installed plugins
// The array key is the "plugin class name" and the value is the object
// pluginsInstalled[pluginClass] = $Plugin
$pluginsInstalled = array();
// ============================================================================
@ -52,19 +55,20 @@ $pluginsInstalled = array();
function buildPlugins()
{
global $plugins;
global $pluginsEvents;
global $pluginsInstalled;
global $L;
global $site;
// This array is only to get the hooks names
$pluginsHooks = $plugins;
unset($pluginsHooks['all']); // remove "all" because is not a valid hook
// Get declared clasess BEFORE load plugins clasess
$currentDeclaredClasess = get_declared_classes();
// List plugins directories
// Load plugins clasess
$list = Filesystem::listDirectories(PATH_PLUGINS);
// Load each plugin clasess
foreach ($list as $pluginPath) {
// Check if the directory has the plugin.php
if (file_exists($pluginPath.DS.'plugin.php')) {
include_once($pluginPath.DS.'plugin.php');
}
@ -89,8 +93,7 @@ function buildPlugins()
$Plugin->setMetadata('name',$database['plugin-data']['name']);
$Plugin->setMetadata('description',$database['plugin-data']['description']);
// Remove name and description from the language file loaded and add new words if there are
// This function overwrite the key=>value
// Remove name and description from the language and includes new words to the global language dictionary
unset($database['plugin-data']);
if (!empty($database)) {
$L->add($database);
@ -99,22 +102,24 @@ function buildPlugins()
// $plugins['all'] Array with all plugins, installed and not installed
$plugins['all'][$pluginClass] = $Plugin;
// If the plugin is installed insert on the hooks
if ($Plugin->installed()) {
// Include custom hooks
// Include the plugin installed in the global array
$pluginsInstalled[$pluginClass] = $Plugin;
// Define new hooks from custom hooks
if (!empty($Plugin->customHooks)) {
foreach ($Plugin->customHooks as $customHook) {
if (!isset($plugins[$customHook])) {
$plugins[$customHook] = array();
$pluginsEvents[$customHook] = array();
foreach ($Plugin->customHooks as $hook) {
if (!isset($plugins[$hook])) {
$plugins[$hook] = array();
$pluginsHooks[$hook] = array();
}
}
}
$pluginsInstalled[$pluginClass] = $Plugin;
foreach ($pluginsEvents as $event=>$value) {
if (method_exists($Plugin, $event)) {
array_push($plugins[$event], $Plugin);
// Insert the plugin into the hooks
foreach ($pluginsHooks as $hook=>$value) {
if (method_exists($Plugin, $hook)) {
array_push($plugins[$hook], $Plugin);
}
}
}
@ -124,6 +129,12 @@ function buildPlugins()
return $a->position()>$b->position();
}
);
// Sort the plugins by the position for the dashboard
uasort($plugins['dashboard'], function ($a, $b) {
return $a->position()>$b->position();
}
);
}
}

View file

@ -16,7 +16,7 @@
*/
$content = array();
// Page filtered by the user, is a Page Object
// Page filtered by the user, will be a Page Object
$page = false;
// Array with static content, each item is a Page Object
@ -29,7 +29,7 @@ $page = false;
N => Page Object
)
*/
$staticContent = $staticPages = buildStaticPages();
$staticContent = buildStaticPages();
// ============================================================================
// Main
@ -38,7 +38,7 @@ $staticContent = $staticPages = buildStaticPages();
// Execute the scheduler
if ($pages->scheduler()) {
// Execute plugins with the hook afterPageCreate
Theme::plugins('afterPageCreate');
execPluginsByHook('afterPageCreate');
reindexTags();
reindexCategories();
@ -61,7 +61,7 @@ if ($site->homepage() && $url->whereAmI()==='home') {
// Build specific page
if ($url->whereAmI()==='page') {
$content[0] = $page = buildThePage();
$page = buildThePage();
}
// Build content by tag
elseif ($url->whereAmI()==='tag') {
@ -73,14 +73,10 @@ elseif ($url->whereAmI()==='category') {
}
// Build content for the homepage
elseif ( ($url->whereAmI()==='home') || ($url->whereAmI()==='blog') ) {
$content = buildPagesForHome();
}
if (isset($content[0])) {
$page = $content[0];
$content = buildPagesForHome();
}
// If set notFound, create the page 404
if ($url->notFound()) {
$content[0] = $page = buildErrorPage();
$page = buildErrorPage();
}

View file

@ -21,7 +21,7 @@ if ($url->whereAmI()=='admin') {
}
// Execute hook from plugins
Theme::plugins('paginator');
execPluginsByHook('paginator');
// Items per page
Paginator::set('itemsPerPage', $itemsPerPage);

View file

@ -3,7 +3,7 @@
// ============================================================================
// Variables
// ============================================================================
$themePlugin = getPlugin($site->theme()); // Returns plugin object or False
$theme = getPlugin($site->theme()); // Returns plugin object or False
// ============================================================================
// Functions
@ -16,18 +16,20 @@ function buildThemes()
$themes = array();
$themesPaths = Filesystem::listDirectories(PATH_THEMES);
foreach ($themesPaths as $themePath) {
foreach($themesPaths as $themePath)
{
// Check if the theme is translated.
$languageFilename = $themePath . DS . 'languages' . DS . $site->language() . '.json';
if (!Sanitize::pathFile($languageFilename)) {
$languageFilename = $themePath . DS . 'languages' . DS . DEFAULT_LANGUAGE_FILE;
$languageFilename = $themePath.DS.'languages'.DS.$site->language().'.json';
if( !Sanitize::pathFile($languageFilename) ) {
$languageFilename = $themePath.DS.'languages'.DS.DEFAULT_LANGUAGE_FILE;
}
if (Sanitize::pathFile($languageFilename)) {
if( Sanitize::pathFile($languageFilename) )
{
$database = file_get_contents($languageFilename);
$database = json_decode($database, true);
if (empty($database)) {
Log::set('99.themes.php' . LOG_SEP . 'Language file error on theme ' . $themePath);
if(empty($database)) {
Log::set('99.themes.php'.LOG_SEP.'Language file error on theme '.$themePath);
break;
}
@ -36,19 +38,20 @@ function buildThemes()
$database['dirname'] = basename($themePath);
// --- Metadata ---
$filenameMetadata = $themePath . DS . 'metadata.json';
$filenameMetadata = $themePath.DS.'metadata.json';
if (Sanitize::pathFile($filenameMetadata)) {
if( Sanitize::pathFile($filenameMetadata) )
{
$metadataString = file_get_contents($filenameMetadata);
$metadata = json_decode($metadataString, true);
$database['compatible'] = false;
if (!empty($metadata['compatible'])) {
if( !empty($metadata['compatible']) ) {
$bluditRoot = explode('.', BLUDIT_VERSION);
$compatible = explode(',', $metadata['compatible']);
foreach ($compatible as $version) {
foreach( $compatible as $version ) {
$root = explode('.', $version);
if ($root[0] == $bluditRoot[0] && $root[1] == $bluditRoot[1]) {
if( $root[0]==$bluditRoot[0] && $root[1]==$bluditRoot[1] ) {
$database['compatible'] = true;
}
}
@ -68,12 +71,13 @@ function buildThemes()
// ============================================================================
// Load the language file
$languageFilename = THEME_DIR . 'languages' . DS . $site->language() . '.json';
if (!Sanitize::pathFile($languageFilename)) {
$languageFilename = THEME_DIR . 'languages' . DS . DEFAULT_LANGUAGE_FILE;
$languageFilename = THEME_DIR.'languages'.DS.$site->language().'.json';
if( !Sanitize::pathFile($languageFilename) ) {
$languageFilename = THEME_DIR.'languages'.DS.DEFAULT_LANGUAGE_FILE;
}
if (Sanitize::pathFile($languageFilename)) {
if( Sanitize::pathFile($languageFilename) )
{
$database = file_get_contents($languageFilename);
$database = json_decode($database, true);
@ -81,7 +85,7 @@ if (Sanitize::pathFile($languageFilename)) {
unset($database['theme-data']);
// Load words from the theme language
if (!empty($database)) {
if(!empty($database)) {
$L->add($database);
}
}
}

View file

@ -4,7 +4,7 @@
include(PATH_RULES.'60.plugins.php');
// Plugins before all
Theme::plugins('beforeAll');
execPluginsByHook('beforeAll');
// Load rules
include(PATH_RULES.'60.router.php');
@ -14,22 +14,22 @@ include(PATH_RULES.'99.paginator.php');
include(PATH_RULES.'99.themes.php');
// Plugins before site loaded
Theme::plugins('beforeSiteLoad');
execPluginsByHook('beforeSiteLoad');
// Theme init.php
if (Sanitize::pathFile(PATH_THEMES, $site->theme().DS.'init.php')) {
if (Sanitize::pathFile(PATH_THEMES.$site->theme().DS.'init.php')) {
include(PATH_THEMES.$site->theme().DS.'init.php');
}
// Theme HTML
if (Sanitize::pathFile(PATH_THEMES, $site->theme().DS.'index.php')) {
if (Sanitize::pathFile(PATH_THEMES.$site->theme().DS.'index.php')) {
include(PATH_THEMES.$site->theme().DS.'index.php');
} else {
$L->p('Please check your theme configuration in the admin panel. Check for an active theme.');
}
// Plugins after site loaded
Theme::plugins('afterSiteLoad');
execPluginsByHook('afterSiteLoad');
// Plugins after all
Theme::plugins('afterAll');
execPluginsByHook('afterAll');

View file

@ -26,7 +26,7 @@ define('PROFILE_IMG_HEIGHT', 400);
define('PROFILE_IMG_QUALITY', 100); // 100%
// Items per page for admin area
define('ITEMS_PER_PAGE_ADMIN', 20);
define('ITEMS_PER_PAGE_ADMIN', 12);
// Password length
define('PASSWORD_LENGTH', 6);
@ -107,7 +107,13 @@ define('MEDIA_MANAGER_SORT_BY_DATE', true);
$GLOBALS['DB_TAGS_TYPES'] = array('published','static','sticky');
// Allowed image extensions
$GLOBALS['ALLOWED_IMG_EXTENSION'] = array('gif', 'png', 'jpg', 'jpeg', 'svg', 'webp');
$GLOBALS['ALLOWED_IMG_EXTENSIONS'] = array('gif', 'png', 'jpg', 'jpeg', 'svg');
// Allowed image mime types
$GLOBALS['ALLOWED_IMG_MIMETYPES'] = array('image/gif', 'image/png', 'image/jpeg', 'image/svg+xml', 'image/webp');
$GLOBALS['ALLOWED_IMG_MIMETYPES'] = array('image/gif', 'image/png', 'image/jpeg', 'image/svg+xml');
// Allowed files extensions
$GLOBALS['ALLOWED_FILE_EXTENSIONS'] = array('gif', 'png', 'jpg', 'jpeg', 'svg');
// Allowed files mime types
$GLOBALS['ALLOWED_FILE_MIMETYPES'] = array('image/gif', 'image/png', 'image/jpeg', 'image/svg+xml', 'application/pdf');

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

6
bl-kernel/css/jquery-ui.min.css vendored Normal file
View file

@ -0,0 +1,6 @@
/*! jQuery UI - v1.12.1 - 2020-11-01
* http://jqueryui.com
* Includes: core.css, autocomplete.css, menu.css
* Copyright jQuery Foundation and other contributors; Licensed MIT */
.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

Before

Width:  |  Height:  |  Size: 424 KiB

View file

@ -0,0 +1,107 @@
.tagsinput,
.tagsinput * {
box-sizing: border-box
}
.tagsinput {
display: flex;
flex-wrap: wrap;
color: #6c757d;
padding: 5px 5px 0;
border-radius: 2px;
border: 1px solid #ced4da;
}
.tagsinput .tag {
position: relative;
background: #6c757d;
display: block;
max-width: 100%;
word-wrap: break-word;
color: #fff;
padding: 5px 30px 5px 5px;
border-radius: 2px;
margin: 0 5px 5px 0
}
.tagsinput .tag .tag-remove {
position: absolute;
background: 0 0;
display: block;
width: 30px;
height: 30px;
top: 0;
right: 0;
cursor: pointer;
text-decoration: none;
text-align: center;
color: #ccc;
line-height: 30px;
padding: 0;
border: 0
}
.tagsinput .tag .tag-remove:after,
.tagsinput .tag .tag-remove:before {
background: #ccc;
position: absolute;
display: block;
width: 10px;
height: 2px;
top: 14px;
left: 10px;
content: ''
}
.tagsinput .tag .tag-remove:before {
-webkit-transform: rotateZ(45deg);
transform: rotateZ(45deg)
}
.tagsinput .tag .tag-remove:after {
-webkit-transform: rotateZ(-45deg);
transform: rotateZ(-45deg)
}
.tagsinput div {
-webkit-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex-positive: 1;
flex-grow: 1
}
.tagsinput div input {
display: block;
width: 100%;
padding: 5px;
border: 0;
margin: 0 5px 5px 0
}
.tagsinput div input.error {
color: #ccc
}
.tagsinput div input::-ms-clear {
display: none
}
.tagsinput div input::-webkit-input-placeholder {
color: #ccc;
opacity: 1
}
.tagsinput div input:-moz-placeholder {
color: #ccc;
opacity: 1
}
.tagsinput div input::-moz-placeholder {
color: #ccc;
opacity: 1
}
.tagsinput div input:-ms-input-placeholder {
color: #ccc;
opacity: 1
}

View file

@ -0,0 +1,79 @@
.token-autocomplete-container {
display: block;
flex-wrap: wrap;
border: 1px solid #E6E6E6;
background-color: #FFFFFF;
}
.token-autocomplete-container, .token-autocomplete-container * {
box-sizing: border-box;
}
.token-autocomplete-container .token-autocomplete-input {
display: block;
line-height: 32px;
margin: 4px 2px;
padding: 0px 8px;
}
.token-autocomplete-container .token-autocomplete-input:empty::before {
content: attr(data-placeholder);
color: rgb(0,0,0,0.6);
}
.token-autocomplete-container .token-autocomplete-token {
width: 100%;
display: block;
padding: 2px 8px;
background: #ccc;
}
.token-autocomplete-container .token-autocomplete-token:hover {
background-color: #ddd;
}
.token-autocomplete-container .token-autocomplete-token .token-autocomplete-token-delete {
cursor: pointer;
font-size: 24px;
line-height: 16px;
margin-left: 4px;
pointer-events: auto;
border-radius: 50%;
height: 24px;
width: 24px;
display: inline-block;
text-align: center;
}
.token-autocomplete-container .token-autocomplete-token .token-autocomplete-token-delete:hover {
background-color: #e55858;
}
.token-autocomplete-container .token-autocomplete-suggestions {
display: none;
width: 100%;
list-style-type: none;
padding: 0px;
margin: 0px;
}
.token-autocomplete-container .token-autocomplete-suggestions li {
width: 100%;
padding: 8px;
cursor: pointer;
}
.token-autocomplete-container .token-autocomplete-suggestions li.token-autocomplete-suggestion-active {
color: #747474;
background-color: #fdfdfd;
}
.token-autocomplete-container .token-autocomplete-suggestions li.token-autocomplete-suggestion-highlighted {
background-color: #95caec;
}
.token-autocomplete-container .token-autocomplete-suggestions li .token-autocomplete-suggestion-description {
display:block;
font-size: 0.7em;
color: #808080;
}

File diff suppressed because it is too large Load diff

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