diff --git a/bl-kernel/abstract/content.class.php b/bl-kernel/abstract/content.class.php index c0eaf294..eae463ab 100644 --- a/bl-kernel/abstract/content.class.php +++ b/bl-kernel/abstract/content.class.php @@ -1,307 +1,357 @@ -build($path)===false) { - $this->vars = false; - } - } - - // Return TRUE if the content is loaded correctly - public function isValid() - { - return($this->vars!==false); - } - - // Returns the value from the $field, FALSE if the field doesn't exist - public function getField($field) - { - if(isset($this->vars[$field])) { - return $this->vars[$field]; - } - - return false; - } - - // Set a value to a field - public function setField($field, $value, $overwrite=true) - { - if($overwrite || empty($this->vars[$field])) { - $this->vars[$field] = $value; - } - - return true; - } - - // Parse the content from the file index.txt - private function build($path) - { - if( !Sanitize::pathFile($path.FILENAME) ) { - return false; - } - - $tmp = 0; - $lines = file($path.FILENAME); - foreach($lines as $lineNumber=>$line) - { - $parts = array_map('trim', explode(':', $line, 2)); - - // Lowercase variable - $parts[0] = Text::lowercase($parts[0]); - - // If variables is content then break the foreach and process the content after. - if($parts[0]==='content') - { - $tmp = $lineNumber; - break; - } - - if( !empty($parts[0]) && !empty($parts[1]) ) { - // Sanitize all fields, except Content. - $this->vars[$parts[0]] = Sanitize::html($parts[1]); - } - } - - // Process the content. - if($tmp!==0) - { - // Next line after "Content:" variable - $tmp++; - - // Remove lines after Content - $output = array_slice($lines, $tmp); - - if(!empty($parts[1])) { - array_unshift($output, "\n"); - array_unshift($output, $parts[1]); - } - - $implode = implode($output); - $this->vars['content'] = $implode; - - // Sanitize content. - //$this->vars['content'] = Sanitize::html($implode); - } - - } - - // Returns the title field - public function title() - { - return $this->getField('title'); - } - - // Returns the content - // This content is markdown parser - // (boolean) $fullContent, TRUE returns all content, if FALSE returns the first part of the content - // (boolean) $noSanitize, TRUE returns the content without sanitized - public function content($fullContent=true, $noSanitize=true) - { - // This content is not sanitized. - $content = $this->getField('content'); - - if(!$fullContent) { - $content = $this->getField('breakContent'); - } - - if($noSanitize) { - return $content; - } - - return Sanitize::html($content); - } - - // Returns the content - // This content is not markdown parser - // (boolean) $noSanitize, TRUE returns the content without sanitized - public function contentRaw($noSanitize=true) - { - // This content is not sanitized. - $content = $this->getField('contentRaw'); - - if($noSanitize) { - return $content; - } - - return Sanitize::html($content); - } - - // Returns TRUE if the content has the text splited - public function readMore() - { - return $this->getField('readMore'); - } - - // Returns the field key - public function key() - { - return $this->getField('key'); - } - - // Returns TRUE if the post/page is published, FALSE otherwise. - public function published() - { - return ($this->getField('status')==='published'); - } - - // Returns TRUE if the post/page is scheduled, FALSE otherwise. - public function scheduled() - { - return ($this->getField('status')==='scheduled'); - } - - // Returns TRUE if the post/page is draft, FALSE otherwise. - public function draft() - { - return ($this->getField('status')=='draft'); - } - - // Returns the file name of the cover image, FALSE there isn't a cover image setted - // (boolean) $absolute, TRUE returns the absolute path and file name, FALSE just the file name - public function coverImage($absolute=true) - { - $fileName = $this->getField('coverImage'); - - if(empty($fileName)) { - return false; - } - - if($absolute) { - return HTML_PATH_UPLOADS.$fileName; - } - - return $fileName; - } - -/* - DEPRECATED ? - - public function profilePicture() - { - return HTML_PATH_UPLOADS_PROFILES.$this->username().'.jpg'; - } -*/ - // Returns the user object - // (boolean) $field, TRUE returns the value of the field, FALSE returns the object - public function user($field=false) - { - // Get the user object. - $User = $this->getField('user'); - - if($field) { - return $User->getField($field); - } - - return $User; - } - - // Returns the username who created the post/page - public function username() - { - return $this->getField('username'); - } - - // Returns the description field - public function description() - { - return $this->getField('description'); - } - - // Returns the date according to locale settings and format settings - public function date() - { - return $this->getField('date'); - } - - // Returns the date according to locale settings and format as database stored - // (string) $format, you can specify the date format - public function dateRaw($format=false) - { - $date = $this->getField('dateRaw'); - - if($format) { - return Date::format($date, DB_DATE_FORMAT, $format); - } - - return $date; - } - - // Returns the tags - // (boolean) $returnsArray, TRUE to get the tags as an array, FALSE to get the tags separeted by comma - public function tags($returnsArray=false) - { - global $Url; - - $tags = $this->getField('tags'); - - if($returnsArray) { - - if($tags==false) { - return array(); - } - - return $tags; - } - else { - if($tags==false) { - return false; - } - - // Return string with tags separeted by comma. - return implode(', ', $tags); - } - } - - // Returns the permalink - // (boolean) $absolute, TRUE returns the post/page link with the DOMAIN, FALSE without the DOMAIN - public function permalink($absolute=false) - { - global $Url; - global $Site; - - $filterType = $this->getField('filterType'); - - $url = trim(DOMAIN_BASE,'/'); - $key = $this->key(); - $filter = trim($Url->filters($filterType), '/'); - $htmlPath = trim(HTML_PATH_ROOT,'/'); - - if(empty($filter)) { - $tmp = $key; - } - else { - $tmp = $filter.'/'.$key; - } - - if($absolute) { - return $url.'/'.$tmp; - } - - if(empty($htmlPath)) { - return '/'.$tmp; - } - - return '/'.$htmlPath.'/'.$tmp; - } - - public function json($returnsArray=false) - { - $tmp['key'] = $this->key(); - $tmp['title'] = $this->title(); - $tmp['content'] = $this->content(); // Markdown parsed - $tmp['contentRaw'] = $this->contentRaw(); // No Markdown parsed - $tmp['description'] = $this->description(); - $tmp['date'] = $this->dateRaw(); - $tmp['permalink'] = $this->permalink(true); - - if($returnsArray) { - return $tmp; - } - - return json_encode($tmp); - } -} +build($path)===false) { + $this->vars = false; + } + } + + // Return TRUE if the content is loaded correctly + public function isValid() + { + return($this->vars!==false); + } + + // Returns the value from the $field, FALSE if the field doesn't exist + public function getField($field) + { + if(isset($this->vars[$field])) { + return $this->vars[$field]; + } + + return false; + } + + // Set a value to a field + public function setField($field, $value, $overwrite=true) + { + if($overwrite || empty($this->vars[$field])) { + $this->vars[$field] = $value; + } + + return true; + } + + // Parse the content from the file index.txt + private function build($path) + { + if( !Sanitize::pathFile($path.FILENAME) ) { + return false; + } + + $tmp = 0; + $lines = file($path.FILENAME); + foreach($lines as $lineNumber=>$line) + { + $parts = array_map('trim', explode(':', $line, 2)); + + // Lowercase variable + $parts[0] = Text::lowercase($parts[0]); + + // If variables is content then break the foreach and process the content after. + if($parts[0]==='content') + { + $tmp = $lineNumber; + break; + } + + if( !empty($parts[0]) && !empty($parts[1]) ) { + // Sanitize all fields, except Content. + $this->vars[$parts[0]] = Sanitize::html($parts[1]); + } + } + + // Process the content. + if($tmp!==0) + { + // Next line after "Content:" variable + $tmp++; + + // Remove lines after Content + $output = array_slice($lines, $tmp); + + if(!empty($parts[1])) { + array_unshift($output, "\n"); + array_unshift($output, $parts[1]); + } + + $implode = implode($output); + $this->vars['content'] = $implode; + + // Sanitize content. + //$this->vars['content'] = Sanitize::html($implode); + } + + } + + // Returns the title field + public function title() + { + return $this->getField('title'); + } + + // Returns the content + // This content is markdown parser + // (boolean) $fullContent, TRUE returns all content, if FALSE returns the first part of the content + // (boolean) $noSanitize, TRUE returns the content without sanitized + public function content($fullContent=true, $noSanitize=true) + { + // This content is not sanitized. + $content = $this->getField('content'); + + if(!$fullContent) { + $content = $this->getField('breakContent'); + } + + if($noSanitize) { + return $content; + } + + return Sanitize::html($content); + } + + // Returns the content + // This content is not markdown parser + // (boolean) $noSanitize, TRUE returns the content without sanitized + public function contentRaw($noSanitize=true) + { + // This content is not sanitized. + $content = $this->getField('contentRaw'); + + if($noSanitize) { + return $content; + } + + return Sanitize::html($content); + } + + // Returns TRUE if the content has the text splited + public function readMore() + { + return $this->getField('readMore'); + } + + // + public function category() + { + return $this->getField('category'); + } + + public function uuid() + { + return $this->getField('uuid'); + } + + // Returns the field key + public function key() + { + return $this->getField('key'); + } + + // Returns TRUE if the post/page is published, FALSE otherwise. + public function published() + { + return ($this->getField('status')==='published'); + } + + // Returns TRUE if the post/page is scheduled, FALSE otherwise. + public function scheduled() + { + return ($this->getField('status')==='scheduled'); + } + + // Returns TRUE if the post/page is draft, FALSE otherwise. + public function draft() + { + return ($this->getField('status')=='draft'); + } + + // Returns the file name of the cover image, FALSE there isn't a cover image setted + // (boolean) $absolute, TRUE returns the absolute path and file name, FALSE just the file name + public function coverImage($absolute=true) + { + $fileName = $this->getField('coverImage'); + + if(empty($fileName)) { + return false; + } + + if($absolute) { + return HTML_PATH_UPLOADS.$fileName; + } + + return $fileName; + } + +/* + DEPRECATED ? + + public function profilePicture() + { + return HTML_PATH_UPLOADS_PROFILES.$this->username().'.jpg'; + } +*/ + // Returns the user object + // (boolean) $field, TRUE returns the value of the field, FALSE returns the object + public function user($field=false) + { + // Get the user object. + $User = $this->getField('user'); + + if($field) { + return $User->getField($field); + } + + return $User; + } + + // Returns the username who created the post/page + public function username() + { + return $this->getField('username'); + } + + // Returns the description field + public function description() + { + return $this->getField('description'); + } + + // Returns the date according to locale settings and format settings + public function date() + { + return $this->getField('date'); + } + + // Returns the date according to locale settings and format as database stored + // (string) $format, you can specify the date format + public function dateRaw($format=false) + { + $date = $this->getField('dateRaw'); + + if($format) { + return Date::format($date, DB_DATE_FORMAT, $format); + } + + return $date; + } + + // Returns relative time (e.g. "1 minute ago") + // Based on http://stackoverflow.com/a/18602474 + // Modified for Bludit + // $complete = false : short version + // $complete = true : full version + public function relativeTime($complete = false) { + $current = new DateTime; + $past = new DateTime($this->getField('date')); + $elapsed = $current->diff($past); + + $elapsed->w = floor($elapsed->d / 7); + $elapsed->d -= $elapsed->w * 7; + + $string = array( + 'y' => 'year', + 'm' => 'month', + 'w' => 'week', + 'd' => 'day', + 'h' => 'hour', + 'i' => 'minute', + 's' => 'second', + ); + + foreach($string as $key => &$value) { + if($elapsed->$key) { + $value = $elapsed->$key . ' ' . $value . ($elapsed->$key > 1 ? 's' : ' '); + } else { + unset($string[$key]); + } + } + + if(!$complete) { + $string = array_slice($string, 0 , 1); + } + + return $string ? implode(', ', $string) . ' ago' : 'Just now'; + + } + + // Returns the tags + // (boolean) $returnsArray, TRUE to get the tags as an array, FALSE to get the tags separeted by comma + public function tags($returnsArray=false) + { + global $Url; + + $tags = $this->getField('tags'); + + if($returnsArray) { + + if($tags==false) { + return array(); + } + + return $tags; + } + else { + if($tags==false) { + return false; + } + + // Return string with tags separeted by comma. + return implode(', ', $tags); + } + } + + // Returns the permalink + // (boolean) $absolute, TRUE returns the post/page link with the DOMAIN, FALSE without the DOMAIN + public function permalink($absolute=false) + { + global $Url; + global $Site; + + $filterType = $this->getField('filterType'); + + $url = trim(DOMAIN_BASE,'/'); + $key = $this->key(); + $filter = trim($Url->filters($filterType), '/'); + $htmlPath = trim(HTML_PATH_ROOT,'/'); + + if(empty($filter)) { + $tmp = $key; + } + else { + $tmp = $filter.'/'.$key; + } + + if($absolute) { + return $url.'/'.$tmp; + } + + if(empty($htmlPath)) { + return '/'.$tmp; + } + + return '/'.$htmlPath.'/'.$tmp; + } + + public function json($returnsArray=false) + { + $tmp['key'] = $this->key(); + $tmp['title'] = $this->title(); + $tmp['content'] = $this->content(); // Markdown parsed + $tmp['contentRaw'] = $this->contentRaw(); // No Markdown parsed + $tmp['description'] = $this->description(); + $tmp['date'] = $this->dateRaw(); + $tmp['permalink'] = $this->permalink(true); + + if($returnsArray) { + return $tmp; + } + + return json_encode($tmp); + } +} diff --git a/bl-kernel/admin/controllers/add-user.php b/bl-kernel/admin/controllers/add-user.php index ce004cf3..c24d28a4 100644 --- a/bl-kernel/admin/controllers/add-user.php +++ b/bl-kernel/admin/controllers/add-user.php @@ -51,6 +51,7 @@ function addUser($args) $tmp['username'] = $args['new_username']; $tmp['password'] = $args['new_password']; $tmp['role'] = $args['role']; + $tmp['email'] = $args['email']; // Add the user to the database if( $dbUsers->add($tmp) ) diff --git a/bl-kernel/admin/controllers/categories.php b/bl-kernel/admin/controllers/categories.php new file mode 100644 index 00000000..37794c32 --- /dev/null +++ b/bl-kernel/admin/controllers/categories.php @@ -0,0 +1,21 @@ +role()!=='admin') { + Alert::set($Language->g('you-do-not-have-sufficient-permissions')); + Redirect::page('admin', 'dashboard'); +} + +// ============================================================================ +// Functions +// ============================================================================ + +function edit($oldCategoryKey, $newCategory) +{ + global $Language; + global $dbPosts; + global $dbPages; + global $dbCategories; + + if( Text::isEmpty($oldCategoryKey) || Text::isEmpty($newCategory) ) { + Alert::set($Language->g('Empty field')); + Redirect::page('admin', 'categories'); + } + + if( $dbCategories->edit($oldCategoryKey, $newCategory) == false ) { + Alert::set($Language->g('Already exist a category')); + } + else { + $dbPages->changeCategory($oldCategoryKey, $newCategory); + $dbPosts->changeCategory($oldCategoryKey, $newCategory); + Alert::set($Language->g('The changes have been saved')); + } + + Redirect::page('admin', 'categories'); +} + +function delete($categoryKey) +{ + global $Language; + global $dbCategories; + + $dbCategories->remove($categoryKey); + + Alert::set($Language->g('The changes have been saved')); + + Redirect::page('admin', 'categories'); +} + +// ============================================================================ +// Main before POST +// ============================================================================ + +// ============================================================================ +// POST Method +// ============================================================================ + +if( $_SERVER['REQUEST_METHOD'] == 'POST' ) +{ + if( isset($_POST['delete']) ) { + delete($_POST['categoryKey']); + } + elseif( isset($_POST['edit']) ) { + edit($_POST['categoryKey'], $_POST['category']); + } +} + +// ============================================================================ +// Main after POST +// ============================================================================ + +$categoryKey = $layout['parameters']; + +if(!$dbCategories->exists($categoryKey)) { + Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to get the category: '.$categoryKey); + Redirect::page('admin', 'categories'); +} + +$category = $dbCategories->getName($layout['parameters']); + +$layout['title'] .= ' - '.$Language->g('Edit category').' - '.$category; diff --git a/bl-kernel/admin/controllers/edit-page.php b/bl-kernel/admin/controllers/edit-page.php index 594b418c..56fd16a8 100644 --- a/bl-kernel/admin/controllers/edit-page.php +++ b/bl-kernel/admin/controllers/edit-page.php @@ -24,6 +24,9 @@ function editPage($args) { $dbPages->regenerateCli(); + // Re index categories + //reIndexCategoriesPages(); + // Call the plugins after page created. Theme::plugins('afterPageModify'); diff --git a/bl-kernel/admin/controllers/edit-post.php b/bl-kernel/admin/controllers/edit-post.php index d4f4b9b3..9fe9ba44 100644 --- a/bl-kernel/admin/controllers/edit-post.php +++ b/bl-kernel/admin/controllers/edit-post.php @@ -21,6 +21,9 @@ function editPost($args) // Reindex tags, this function is in 70.posts.php reIndexTagsPosts(); + // Re index categories + //reIndexCategoriesPosts(); + // Call the plugins after post created. Theme::plugins('afterPostModify'); diff --git a/bl-kernel/admin/controllers/new-category.php b/bl-kernel/admin/controllers/new-category.php new file mode 100644 index 00000000..65242649 --- /dev/null +++ b/bl-kernel/admin/controllers/new-category.php @@ -0,0 +1,53 @@ +role()!=='admin') { + Alert::set($Language->g('you-do-not-have-sufficient-permissions')); + Redirect::page('admin', 'dashboard'); +} + +// ============================================================================ +// Functions +// ============================================================================ + +function add($category) +{ + global $dbCategories; + global $Language; + + if( Text::isEmpty($category) ) { + Alert::set($Language->g('Category name is empty'), ALERT_STATUS_FAIL); + return false; + } + + if( $dbCategories->add($category) ) { + Alert::set($Language->g('Category added'), ALERT_STATUS_OK); + return true; + } + else { + Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to create the category.'); + return false; + } +} + +// ============================================================================ +// Main before POST +// ============================================================================ + +// ============================================================================ +// POST Method +// ============================================================================ + +if( $_SERVER['REQUEST_METHOD'] == 'POST' ) +{ + if( add($_POST['category']) ) { + Redirect::page('admin', 'categories'); + } +} + +// ============================================================================ +// Main after POST +// ============================================================================ diff --git a/bl-kernel/admin/controllers/new-page.php b/bl-kernel/admin/controllers/new-page.php index 5846f975..4fac1f31 100644 --- a/bl-kernel/admin/controllers/new-page.php +++ b/bl-kernel/admin/controllers/new-page.php @@ -18,6 +18,9 @@ function addPage($args) if($key) { + // Re index categories + //reIndexCategoriesPages(); + // Call the plugins after page created. Theme::plugins('afterPageCreate'); diff --git a/bl-kernel/admin/controllers/new-post.php b/bl-kernel/admin/controllers/new-post.php index 19463e3b..01eb5361 100644 --- a/bl-kernel/admin/controllers/new-post.php +++ b/bl-kernel/admin/controllers/new-post.php @@ -15,21 +15,24 @@ function addPost($args) // Add the page, if the $key is FALSE the creation of the post failure. $key = $dbPosts->add($args); - if($key) - { + if($key) { // Reindex tags, this function is in 70.posts.php reIndexTagsPosts(); - // Call the plugins after post created. + // Re index categories + //reIndexCategoriesPosts(); + + // Call the plugins after post creation Theme::plugins('afterPostCreate'); // Alert for the user Alert::set($Language->g('Post added successfully')); Redirect::page('admin', 'manage-posts'); } - else - { + else { Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to create the post.'); + Log::set(__METHOD__.LOG_SEP.'Cleaning database...'); + $dbPosts->delete($key); } return false; diff --git a/bl-kernel/admin/themes/default/css/default.css b/bl-kernel/admin/themes/default/css/default.css index 7e5aa9a3..cecdf3d0 100644 --- a/bl-kernel/admin/themes/default/css/default.css +++ b/bl-kernel/admin/themes/default/css/default.css @@ -270,6 +270,10 @@ button.aslink:hover { padding-left: 20px; } +.uk-table td, .uk-table th { + padding: 14px 8px !important; +} + /* RESPONSIVE ---------------------------------------------------------------- */ @@ -591,6 +595,17 @@ tr.theme-installed { background: #F2F7FF !important; } +div.plugin-name i.settings-icon { + float: right; + margin-top: 3px; + margin-left: 3px; +} + +i.incompatible-warning { + color: #FFC425; + padding-right: 5px; +} + div.plugin-links > a { display: inline-block; margin-top: 5px; @@ -632,7 +647,15 @@ div.plugin-links > span.separator { } #paginator li.right { - margin-left: 10px; + margin-left: 10px; +} + +#paginator li.next { + margin-right: 1em; +} + +#paginator li.previous { + margin-left: 1em; } /* ----------- PLUGINS FORM ----------- */ diff --git a/bl-kernel/admin/themes/default/index.php b/bl-kernel/admin/themes/default/index.php index 1491bdb7..0c17fab7 100644 --- a/bl-kernel/admin/themes/default/index.php +++ b/bl-kernel/admin/themes/default/index.php @@ -63,6 +63,7 @@ $(document).ready(function() {