From 8439abbe97a2b40e7efe52d16cbe9bc31f4029f6 Mon Sep 17 00:00:00 2001 From: Diego Najar <dignajar@gmail.com> Date: Sun, 12 Sep 2021 22:06:29 +0200 Subject: [PATCH] add comments, and styling --- bl-kernel/boot/init.php | 14 +- bl-kernel/helpers/sanitize.class.php | 11 +- bl-kernel/js/variables.php | 1 + bl-kernel/page.class.php | 1307 ++++++++++++++------------ bl-kernel/pages.class.php | 90 +- bl-languages/en.json | 2 + 6 files changed, 759 insertions(+), 666 deletions(-) diff --git a/bl-kernel/boot/init.php b/bl-kernel/boot/init.php index c02bf708..8c1eba00 100644 --- a/bl-kernel/boot/init.php +++ b/bl-kernel/boot/init.php @@ -219,7 +219,7 @@ 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', $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); @@ -228,17 +228,15 @@ 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_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_PAGES', DOMAIN.HTML_PATH_UPLOADS_PAGES); +define('DOMAIN_UPLOADS_PROFILES',DOMAIN.HTML_PATH_UPLOADS_PROFILES); define('DOMAIN_PLUGINS', DOMAIN.HTML_PATH_PLUGINS); define('DOMAIN_CONTENT', DOMAIN.HTML_PATH_CONTENT); - 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)); diff --git a/bl-kernel/helpers/sanitize.class.php b/bl-kernel/helpers/sanitize.class.php index f6311c4b..3e2c6cf3 100644 --- a/bl-kernel/helpers/sanitize.class.php +++ b/bl-kernel/helpers/sanitize.class.php @@ -6,8 +6,15 @@ class Sanitize { return strip_tags($text); } - // Convert special characters to HTML entities - public static function html($text) + /** + * Convert special characters to HTML entities. + * For example, & => & + * For example, " => " + * + * @param string $text + * @return string + */ + public static function html(string $text): string { $flags = ENT_COMPAT; diff --git a/bl-kernel/js/variables.php b/bl-kernel/js/variables.php index e9109637..d3072227 100644 --- a/bl-kernel/js/variables.php +++ b/bl-kernel/js/variables.php @@ -18,6 +18,7 @@ echo 'var DOMAIN_PAGES = "'.DOMAIN_PAGES.'";'.PHP_EOL; echo 'var DOMAIN_ADMIN = "'.DOMAIN_ADMIN.'";'.PHP_EOL; echo 'var DOMAIN_CONTENT = "'.DOMAIN_CONTENT.'";'.PHP_EOL; echo 'var DOMAIN_UPLOADS = "'.DOMAIN_UPLOADS.'";'.PHP_EOL; +echo 'var DOMAIN_UPLOADS_PAGES = "'.DOMAIN_UPLOADS_PAGES.'";'.PHP_EOL; echo 'var DB_DATE_FORMAT = "'.DB_DATE_FORMAT.'";'.PHP_EOL; echo 'var AUTOSAVE_INTERVAL = "'.AUTOSAVE_INTERVAL.'";'.PHP_EOL; echo 'var PAGE_BREAK = "'.PAGE_BREAK.'";'.PHP_EOL; diff --git a/bl-kernel/page.class.php b/bl-kernel/page.class.php index d4e47297..6c6d3f23 100644 --- a/bl-kernel/page.class.php +++ b/bl-kernel/page.class.php @@ -2,631 +2,686 @@ class Page { - protected $vars; - - function __construct($key) - { - global $pages; - - $this->vars['key'] = $key; - // If key is FALSE, the page is create with default values, like an empty page - // Useful for Page Not Found - if ($key===false) { - $row = $pages->getDefaultFields(); - } else { - if (Text::isEmpty($key) || !$pages->exists($key)) { - $errorMessage = 'Page not found in database by key ['.$key.']'; - Log::set(__METHOD__.LOG_SEP.$errorMessage); - throw new Exception($errorMessage); - } - $row = $pages->getPageDB($key); - } - - foreach ($row as $field=>$value) { - if ($field=='date') { - $this->setField('dateRaw', $value); - } else { - $this->setField($field, $value); - } - } - } - - public function getValue($field) - { - if (isset($this->vars[$field])) { - return $this->vars[$field]; - } - return false; - } - - public function setField($field, $value) - { - $this->vars[$field] = $value; - return true; - } - - // Returns the raw content - // This content is not markdown parser - // (boolean) $sanitize, TRUE returns the content sanitized - public function contentRaw($sanitize=false) - { - $key = $this->key(); - $filePath = PATH_PAGES.$key.DS.FILENAME; - $contentRaw = file_get_contents($filePath); - - if ($sanitize) { - return Sanitize::html($contentRaw); - } - return $contentRaw; - } - - // Returns the full content - // This content is markdown parser - // (boolean) $sanitize, TRUE returns the content sanitized - public function content($sanitize=false) - { - // If already set the content, return it - $content = $this->getValue('content'); - if (!empty($content)) { - return $content; - } - - // Get the raw content - $content = $this->contentRaw(); - - // Parse Markdown - if (MARKDOWN_PARSER) { - $parsedown = new Parsedown(); - $content = $parsedown->text($content); - } - - // Parse img src relative to absolute (with domain) - if (IMAGE_RELATIVE_TO_ABSOLUTE) { - $domain = IMAGE_RESTRICT?DOMAIN_UPLOADS_PAGES.$this->uuid().'/':DOMAIN_UPLOADS; - $content = Text::imgRel2Abs($content, $domain); - } - - if ($sanitize) { - return Sanitize::html($content); - } - return $content; - } - - // Returns the first part of the content if the content is splited, otherwise is returned the full content - // This content is markdown parser - // (boolean) $sanitize, TRUE returns the content sanitized - public function contentBreak($sanitize=false) - { - $content = $this->content($sanitize); - $explode = explode(PAGE_BREAK, $content); - return $explode[0]; - } - - // Returns the date according to locale settings and the format defined in the system - public function date($format=false) - { - $dateRaw = $this->dateRaw(); - if ($format===false) { - global $site; - $format = $site->dateFormat(); - } - return Date::format($dateRaw, DB_DATE_FORMAT, $format); - } - - // Returns the date according to locale settings and format as database stored - public function dateRaw() - { - // This field is set in the constructor - return $this->getValue('dateRaw'); - } - - // Returns the date according to locale settings and format settings - public function dateModified($format=false) - { - $dateRaw = $this->getValue('dateModified'); - if ($format===false) { - global $site; - $format = $site->dateFormat(); - } - return Date::format($dateRaw, DB_DATE_FORMAT, $format); - } - - // Returns the username who created the page - public function username() - { - return $this->getValue('username'); - } - - // TODO: Check if necessary this function - public function getDB() - { - return $this->vars; - } - - // Returns the permalink - // (boolean) $absolute, TRUE returns the page link with the DOMAIN, FALSE without the DOMAIN - public function permalink($absolute=true) - { - // Get the key of the page - $key = $this->key(); - - if($absolute) { - return DOMAIN_PAGES.$key; - } - - return HTML_PATH_ROOT.PAGE_URI_FILTER.$key; - } - - public function url($absolute=true) - { - return $this->permalink($absolute); - } - - // Returns the previous page key - public function previousKey() - { - global $pages; - return $pages->previousPageKey($this->key()); - } - - // Returns the next page key - public function nextKey() - { - global $pages; - return $pages->nextPageKey($this->key()); - } - - // Returns the category name - public function category() - { - return $this->categoryMap('name'); - } - - // Returns the category template - public function categoryTemplate() - { - return $this->categoryMap('template'); - } - - // Returns the category description - public function categoryDescription() - { - return $this->categoryMap('description'); - } - - // Returns the category key - public function categoryKey() - { - return $this->getValue('category'); - } - - // Returns the category permalink - public function categoryPermalink() - { - return DOMAIN_CATEGORIES.$this->categoryKey(); - } - - // Returns the field from the array - // categoryMap = array( 'name'=>'', 'list'=>array() ) - public function categoryMap($field) - { - global $categories; - $categoryKey = $this->categoryKey(); - $map = $categories->getMap($categoryKey); - - if ($field=='key') { - return $this->categoryKey(); - } elseif(isset($map[$field])) { - return $map[$field]; - } - - return false; - } - - // Returns the user object or passing the method returns the object User method - public function user($method=false) - { - $username = $this->username(); - try { - $user = new User($username); - if ($method) { - return $user->{$method}(); - } - return $user; - } catch (Exception $e) { - return false; - } - } - - /* Returns the template for the page === Bludit v4 - - @return string/boolean Returns the template for the page or FALSE if the page haven't a template assigned - */ - public function template() - { - $template = $this->getValue('template'); - if (empty($template)) { - return false; - } - return $template; - } - - // Returns the description field - public function description() - { - return $this->getValue('description'); - } - - // Returns the tags separated by comma - // (boolean) $returnsArray, TRUE to get the tags as an array, FALSE to get the tags separated by comma - // The tags in array format returns array( tagKey => tagName ) - public function tags($returnsArray=false) - { - $tags = $this->getValue('tags'); - if ($returnsArray) { - if (empty($tags)) { - return array(); - } - return $tags; - } - - if (empty($tags)) { - return ''; - } - // Return string with tags separated by comma. - return implode(',', $tags); - } - - - - public function json($returnsArray=false) - { - $tmp['key'] = $this->key(); - $tmp['title'] = $this->title(); - $tmp['content'] = $this->content(); // Markdown parsed - $tmp['contentRaw'] = $this->contentRaw(true); // No Markdown parsed - $tmp['description'] = $this->description(); - $tmp['type'] = $this->type(); - $tmp['slug'] = $this->slug(); - $tmp['date'] = $this->date(); - $tmp['dateRaw'] = $this->dateRaw(); - $tmp['tags'] = $this->tags(false); - $tmp['username'] = $this->username(); - $tmp['category'] = $this->category(); - $tmp['uuid'] = $this->uuid(); - $tmp['dateUTC'] = Date::convertToUTC($this->dateRaw(), DB_DATE_FORMAT, DB_DATE_FORMAT); - $tmp['permalink'] = $this->permalink(true); - $tmp['coverImage'] = $this->coverImage(true); - $tmp['coverImageFilename'] = $this->coverImage(false); - - if ($returnsArray) { - return $tmp; - } - - return json_encode($tmp); - } - - // Returns the endpoint of the coverimage, FALSE if the page doesn't have a cover image - // (boolean) $absolute, TRUE returns the complete URL, FALSE returns the filename - // If the user defined an external cover image the function returns it - public function coverImage($absolute=true) - { - $filename = $this->getValue('coverImage'); - if (empty($filename)) { - return false; - } - - // Check is external cover image - if (filter_var($filename, FILTER_VALIDATE_URL)) { - return $filename; - } - - if ($absolute) { - if (IMAGE_RESTRICT) { - return DOMAIN_UPLOADS_PAGES.$this->uuid().'/'.$filename; - } - return DOMAIN_UPLOADS.$filename; - } - - return $filename; - } - - // Returns TRUE if the content has the text splited - public function readMore() - { - $content = $this->contentRaw(); - return Text::stringContains($content, PAGE_BREAK); - } - - public function uuid() - { - return $this->getValue('uuid'); - } - - // Returns the field key - public function key() - { - return $this->getValue('key'); - } - - // (boolean) Returns TRUE if the page is published, FALSE otherwise - public function published() - { - return ($this->getValue('type')==='published'); - } - - // (boolean) Returns TRUE if the page is scheduled, FALSE otherwise - public function scheduled() - { - return ($this->getValue('type')==='scheduled'); - } - - // (boolean) Returns TRUE if the page is draft, FALSE otherwise - public function draft() - { - return ($this->getValue('type')=='draft'); - } - - // (boolean) Returns TRUE if the page is autosave, FALSE otherwise - public function autosave() - { - return ($this->getValue('type')=='autosave'); - } - - // (boolean) Returns TRUE if the page is sticky, FALSE otherwise - public function sticky() - { - return ($this->getValue('type')=='sticky'); - } - - // (boolean) Returns TRUE if the page is static, FALSE otherwise - public function isStatic() - { - return ($this->getValue('type')=='static'); - } - - // (boolean) Returns TRUE if the page is unlisted, FALSE otherwise - public function unlisted() - { - return ($this->getValue('type')=='unlisted'); - } - - // (string) Returns type of the page - public function type() - { - return $this->getValue('type'); - } - - // Returns the title field - public function title() - { - return $this->getValue('title'); - } - - // Returns TRUE if the page has enabled the comments, FALSE otherwise - public function allowComments() - { - return $this->getValue('allowComments'); - } - - // Returns the page position - public function position() - { - return $this->getValue('position'); - } - - // Returns the page noindex - public function noindex() - { - return $this->getValue('noindex'); - } - - // Returns the page nofollow - public function nofollow() - { - return $this->getValue('nofollow'); - } - - // Returns the page noarchive - public function noarchive() - { - return $this->getValue('noarchive'); - } - - // Returns the page slug - public function slug() - { - $explode = explode('/', $this->key()); - return end($explode); - } - - // Returns the parent key, if the page doesn't have a parent returns FALSE - public function parent() - { - return $this->parentKey(); - } - - // Returns the parent key, if the page doesn't have a parent returns FALSE - public function parentKey() - { - $explode = explode('/', $this->key()); - if (isset($explode[1])) { - return $explode[0]; - } - return false; - } - - // Returns TRUE if the page is a parent, has or not children - public function isParent() - { - return $this->parentKey()===false; - } - - // Returns the parent method output, if the page doesn't have a parent returns FALSE - public function parentMethod($method) - { - $parentKey = $this->parentKey(); - if ($parentKey) { - try { - $page = new Page($parentKey); - return $page->{$method}(); - } catch (Exception $e) { - // Continoue - } - } - - return false; - } - - // Returns TRUE if the page is a child, FALSE otherwise - public function isChild() - { - return $this->parentKey()!==false; - } - - // Returns TRUE if the page has children - public function hasChildren() - { - $childrenKeys = $this->childrenKeys(); - return !empty($childrenKeys); - } - - // Returns an array with all children's keys - public function childrenKeys() - { - global $pages; - $key = $this->key(); - return $pages->getChildren($key); - } - - // Returns an array with all children as Page-Object - public function children() - { - global $pages; - $list = array(); - $childrenKeys = $pages->getChildren($this->key()); - foreach ($childrenKeys as $childKey) { - try { - $child = new Page($childKey); - array_push($list, $child); - } catch (Exception $e) { - // Continue - } - } - - return $list; - } - - /* Returns the amount of minutes takes to read the page === Bludit v4 - - @return string Returns the minutes as string - */ - public function readingTime() { - $words = $this->content(true); - $words = strip_tags($words); - $words = str_word_count($words); - $average = $words / 200; - $minutes = round($average); - - if ($minutes>1) { - return $minutes; - } - return '~1'; - } - - // Returns the value from the field, false if the fields doesn't exists - // If you set the $option as TRUE, the function returns an array with all the values of the field - public function custom($field, $options=false) - { - if (isset($this->vars['custom'][$field])) { - if ($options) { - return $this->vars['custom'][$field]; - } - return $this->vars['custom'][$field]['value']; - } - return false; - } - - /* Returns an array with all pages key related to the page === Bludit v4 - The relation is based on the tags. - - @sortByDate boolean TRUE if you want to get sort by date the pages, FALSE random order - @getFirst int Amount of related pages, -1 indicates all related pages - @return array Returns an array with the page keys related to page - */ - public function related($sortByDate=false, $getFirst=-1) { - global $tags; - $pageTags = $this->tags(true); - $list = array(); - // For each tag get the list of related pages - foreach ($pageTags as $tagKey=>$tagName) { - $pagesRelated = $tags->getList($tagKey, 1, -1); - $list = array_merge($list, $pagesRelated); - } - - // Remove duplicates - $list = array_unique($list); - - // Remove himself from the list - if (($key = array_search($this->key(), $list)) !== false) { - unset($list[$key]); - } - - // Sort by date if requested - if ($sortByDate) { - $listSortByDate = array(); - foreach ($list as $pageKey) { - $tmpPage = new Page($pageKey); - $listSortByDate[$tmpPage->date('U')] = $pageKey; - } - krsort($listSortByDate); - $list = $listSortByDate; - } - - if ($getFirst==-1) { - return $list; - } else { - return array_slice($list, 0, $getFirst); - } - } - - /* Returns relative time (e.g. "1 minute ago") === Bludit v4 - Based on http://stackoverflow.com/a/18602474 - - @complete boolean TRUE full version, FALSE short version - @return string Relative time, for example: 1 minute ago - */ - public function relativeTime($complete=false) { - $current = new DateTime; - $past = new DateTime($this->getValue('dateRaw')); - $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'; - } + protected $vars; + + function __construct($key) + { + global $pages; + + $this->vars['key'] = $key; + // If key is FALSE, the page is create with default values, like an empty page + // Useful for Page Not Found + if ($key===false) { + $row = $pages->getDefaultFields(); + } else { + if (Text::isEmpty($key) || !$pages->exists($key)) { + $errorMessage = 'Page not found in database by key ['.$key.']'; + Log::set(__METHOD__.LOG_SEP.$errorMessage); + throw new Exception($errorMessage); + } + // The database doesn't have the page's content. + $row = $pages->getPageDB($key); + } + + foreach ($row as $field=>$value) { + if ($field=='date') { + $this->vars['dateRaw'] = $value; + } else { + $this->vars[$field] = $value; + } + } + } + + /** + * Returns the value associated to a field, if the field doesn't exists returns FALSE. + * + * @param string $field + * @return bool|string|int|array + */ + public function getValue(string $field): bool|string|int|array + { + if (isset($this->vars[$field])) { + return $this->vars[$field]; + } + return false; + } + + /** + * Set the value associated to a field. + * + * @param string $field + * @param string $value + * @return boolean + */ + public function setField(string $field, string $value): bool + { + $this->vars[$field] = $value; + return true; + } + + /** + * Returns the full raw page's content. This content is not markdown parser. + * + * @param boolean $sanitize TRUE returns the content sanitized + * @return string + */ + public function contentRaw(bool $sanitize=false): string + { + $key = $this->key(); + $filePath = PATH_PAGES.$key.DS.FILENAME; + $contentRaw = file_get_contents($filePath); + + if ($sanitize) { + return Sanitize::html($contentRaw); + } + return $contentRaw; + } + + /** + * Returns the full page's content. + * + * @param boolean $sanitize TRUE returns the content sanitized + * @return string + */ + public function content(bool $sanitize=false): string + { + // If already set the content, return it + $content = $this->getValue('content'); + if (!empty($content)) { + return $content; + } + + // Get the raw content + $content = $this->contentRaw(false); + + // Parse Markdown + if (MARKDOWN_PARSER) { + $parsedown = new Parsedown(); + $content = $parsedown->text($content); + } + + // Parse img src relative to absolute (with domain) + if (IMAGE_RELATIVE_TO_ABSOLUTE) { + $domain = IMAGE_RESTRICT?DOMAIN_UPLOADS_PAGES.$this->key().'/':DOMAIN_UPLOADS; + $content = Text::imgRel2Abs($content, $domain); + } + + if ($sanitize) { + return Sanitize::html($content); + } + return $content; + } + + /** + * Returns the first part of the content if the content is splited, otherwise is returned the full content. + * + * @param boolean $sanitize TRUE returns the content sanitized + * @return string + */ + public function contentBreak(bool $sanitize=false): string + { + $content = $this->content($sanitize); + $explode = explode(PAGE_BREAK, $content); + return $explode[0]; + } + + // Returns the date according to locale settings and the format defined in the system + public function date($format=false) + { + $dateRaw = $this->dateRaw(); + if ($format===false) { + global $site; + $format = $site->dateFormat(); + } + return Date::format($dateRaw, DB_DATE_FORMAT, $format); + } + + // Returns the date according to locale settings and format as database stored + public function dateRaw() + { + // This field is set in the constructor + return $this->getValue('dateRaw'); + } + + // Returns the date according to locale settings and format settings + public function dateModified($format=false) + { + $dateRaw = $this->getValue('dateModified'); + if ($format===false) { + global $site; + $format = $site->dateFormat(); + } + return Date::format($dateRaw, DB_DATE_FORMAT, $format); + } + + // Returns the username who created the page + public function username() + { + return $this->getValue('username'); + } + + // TODO: Check if necessary this function + public function getDB() + { + return $this->vars; + } + + // Returns the permalink + // (boolean) $absolute, TRUE returns the page link with the DOMAIN, FALSE without the DOMAIN + public function permalink($absolute=true) + { + // Get the key of the page + $key = $this->key(); + + if($absolute) { + return DOMAIN_PAGES.$key; + } + + return HTML_PATH_ROOT.PAGE_URI_FILTER.$key; + } + + public function url($absolute=true) + { + return $this->permalink($absolute); + } + + // Returns the previous page key + public function previousKey() + { + global $pages; + return $pages->previousPageKey($this->key()); + } + + // Returns the next page key + public function nextKey() + { + global $pages; + return $pages->nextPageKey($this->key()); + } + + // Returns the category name + public function category() + { + return $this->categoryMap('name'); + } + + // Returns the category template + public function categoryTemplate() + { + return $this->categoryMap('template'); + } + + // Returns the category description + public function categoryDescription() + { + return $this->categoryMap('description'); + } + + // Returns the category key + public function categoryKey() + { + return $this->getValue('category'); + } + + // Returns the category permalink + public function categoryPermalink() + { + return DOMAIN_CATEGORIES.$this->categoryKey(); + } + + // Returns the field from the array + // categoryMap = array( 'name'=>'', 'list'=>array() ) + public function categoryMap($field) + { + global $categories; + $categoryKey = $this->categoryKey(); + $map = $categories->getMap($categoryKey); + + if ($field=='key') { + return $this->categoryKey(); + } elseif(isset($map[$field])) { + return $map[$field]; + } + + return false; + } + + // Returns the user object or passing the method returns the object User method + public function user($method=false) + { + $username = $this->username(); + try { + $user = new User($username); + if ($method) { + return $user->{$method}(); + } + return $user; + } catch (Exception $e) { + return false; + } + } + + /** + * Returns the template for the page or FALSE if the page haven't a template assigned. + * + * @return boolean|string + */ + public function template(): bool|string + { + $template = $this->getValue('template'); + if (empty($template)) { + return false; + } + return $template; + } + + // Returns the description field + public function description() + { + return $this->getValue('description'); + } + + // Returns the tags separated by comma + // (boolean) $returnsArray, TRUE to get the tags as an array, FALSE to get the tags separated by comma + // The tags in array format returns array( tagKey => tagName ) + public function tags($returnsArray=false) + { + $tags = $this->getValue('tags'); + if ($returnsArray) { + if (empty($tags)) { + return array(); + } + return $tags; + } + + if (empty($tags)) { + return ''; + } + // Return string with tags separated by comma. + return implode(',', $tags); + } + + + + public function json($returnsArray=false) + { + $tmp['key'] = $this->key(); + $tmp['title'] = $this->title(); + $tmp['content'] = $this->content(); // Markdown parsed + $tmp['contentRaw'] = $this->contentRaw(true); // No Markdown parsed + $tmp['description'] = $this->description(); + $tmp['type'] = $this->type(); + $tmp['slug'] = $this->slug(); + $tmp['date'] = $this->date(); + $tmp['dateRaw'] = $this->dateRaw(); + $tmp['tags'] = $this->tags(false); + $tmp['username'] = $this->username(); + $tmp['category'] = $this->category(); + $tmp['uuid'] = $this->uuid(); + $tmp['dateUTC'] = Date::convertToUTC($this->dateRaw(), DB_DATE_FORMAT, DB_DATE_FORMAT); + $tmp['permalink'] = $this->permalink(true); + $tmp['coverImage'] = $this->coverImage(true); + $tmp['coverImageFilename'] = $this->coverImage(false); + + if ($returnsArray) { + return $tmp; + } + + return json_encode($tmp); + } + + /** + * Returns the cover image endpoint, FALSE if the page doesn't have a cover image + * + * @param boolean $absolute TRUE returns the complete URL, FALSE returns the filename + * @return string + */ + public function coverImage(bool $absolute=true): string + { + $filename = $this->getValue('coverImage'); + if (empty($filename)) { + return false; + } + + // Check if it is an external cover image + if (filter_var($filename, FILTER_VALIDATE_URL)) { + return $filename; + } + + if ($absolute) { + if (IMAGE_RESTRICT) { + return DOMAIN_UPLOADS_PAGES.$this->key().'/'.$filename; + } + return DOMAIN_UPLOADS.$filename; + } + + return $filename; + } + + // Returns TRUE if the content has the text splited + public function readMore() + { + $content = $this->contentRaw(); + return Text::stringContains($content, PAGE_BREAK); + } + + public function uuid() + { + return $this->getValue('uuid'); + } + + // Returns the field key + public function key() + { + return $this->getValue('key'); + } + + /** + * Returns TRUE if the page is type "published", FALSE otherwise + * + * @return boolean + */ + public function published(): bool + { + return ($this->getValue('type')==='published'); + } + + /** + * Returns TRUE if the page is type "scheduled", FALSE otherwise + * + * @return boolean + */ + public function scheduled(): bool + { + return ($this->getValue('type')==='scheduled'); + } + + /** + * Returns TRUE if the page is type "draft", FALSE otherwise + * + * @return boolean + */ + public function draft(): bool + { + return ($this->getValue('type')=='draft'); + } + + /** + * Returns TRUE if the page is type "sticky", FALSE otherwise + * + * @return boolean + */ + public function sticky(): bool + { + return ($this->getValue('type')=='sticky'); + } + + /** + * Returns TRUE if the page is type "static", FALSE otherwise + * + * @return boolean + */ + public function isStatic(): bool + { + return ($this->getValue('type')=='static'); + } + + /** + * Returns TRUE if the page is type "unlisted", FALSE otherwise + * + * @return boolean + */ + public function unlisted(): bool + { + return ($this->getValue('type')=='unlisted'); + } + + // (boolean) Returns TRUE if the page is autosave, FALSE otherwise + public function autosave() + { + return ($this->getValue('type')=='autosave'); + } + + // (string) Returns type of the page + public function type() + { + return $this->getValue('type'); + } + + // Returns the title field + public function title() + { + return $this->getValue('title'); + } + + // Returns TRUE if the page has enabled the comments, FALSE otherwise + public function allowComments() + { + return $this->getValue('allowComments'); + } + + // Returns the page position + public function position() + { + return $this->getValue('position'); + } + + // Returns the page noindex + public function noindex() + { + return $this->getValue('noindex'); + } + + // Returns the page nofollow + public function nofollow() + { + return $this->getValue('nofollow'); + } + + // Returns the page noarchive + public function noarchive() + { + return $this->getValue('noarchive'); + } + + // Returns the page slug + public function slug() + { + $explode = explode('/', $this->key()); + return end($explode); + } + + // Returns the parent key, if the page doesn't have a parent returns FALSE + public function parent() + { + return $this->parentKey(); + } + + // Returns the parent key, if the page doesn't have a parent returns FALSE + public function parentKey() + { + $explode = explode('/', $this->key()); + if (isset($explode[1])) { + return $explode[0]; + } + return false; + } + + // Returns TRUE if the page is a parent, has or not children + public function isParent() + { + return $this->parentKey()===false; + } + + // Returns the parent method output, if the page doesn't have a parent returns FALSE + public function parentMethod($method) + { + $parentKey = $this->parentKey(); + if ($parentKey) { + try { + $page = new Page($parentKey); + return $page->{$method}(); + } catch (Exception $e) { + // Continoue + } + } + + return false; + } + + // Returns TRUE if the page is a child, FALSE otherwise + public function isChild() + { + return $this->parentKey()!==false; + } + + // Returns TRUE if the page has children + public function hasChildren() + { + $childrenKeys = $this->childrenKeys(); + return !empty($childrenKeys); + } + + // Returns an array with all children's keys + public function childrenKeys() + { + global $pages; + $key = $this->key(); + return $pages->getChildren($key); + } + + // Returns an array with all children as Page-Object + public function children() + { + global $pages; + $list = array(); + $childrenKeys = $pages->getChildren($this->key()); + foreach ($childrenKeys as $childKey) { + try { + $child = new Page($childKey); + array_push($list, $child); + } catch (Exception $e) { + // Continue + } + } + + return $list; + } + + /** + * Returns the amount of minutes takes to read the page + * + * @return string + */ + public function readingTime(): string + { + $words = $this->content(true); + $words = strip_tags($words); + $words = str_word_count($words); + $average = $words / 200; + $minutes = round($average); + + if ($minutes>1) { + return $minutes; + } + return '~1'; + } + + // Returns the value from the field, false if the fields doesn't exists + // If you set the $option as TRUE, the function returns an array with all the values of the field + public function custom($field, $options=false) + { + if (isset($this->vars['custom'][$field])) { + if ($options) { + return $this->vars['custom'][$field]; + } + return $this->vars['custom'][$field]['value']; + } + return false; + } + + /** + * Returns an array with all pages' keys related to the page. The relation is based on the tags. + * + * @param boolean $sortByDate TRUE if you want to get sort by date the pages, FALSE random order + * @param integer $getFirst Amount of related pages, -1 indicates all related pages + * @return array + */ + public function related(bool $sortByDate=false, int $getFirst=-1): array + { + global $tags; + $pageTags = $this->tags(true); + $list = array(); + // For each tag get the list of related pages + foreach ($pageTags as $tagKey=>$tagName) { + $pagesRelated = $tags->getList($tagKey, 1, -1); + $list = array_merge($list, $pagesRelated); + } + + // Remove duplicates + $list = array_unique($list); + + // Remove himself from the list + if (($key = array_search($this->key(), $list)) !== false) { + unset($list[$key]); + } + + // Sort by date if requested + if ($sortByDate) { + $listSortByDate = array(); + foreach ($list as $pageKey) { + $tmpPage = new Page($pageKey); + $listSortByDate[$tmpPage->date('U')] = $pageKey; + } + krsort($listSortByDate); + $list = $listSortByDate; + } + + if ($getFirst==-1) { + return $list; + } else { + return array_slice($list, 0, $getFirst); + } + } + + /** + * Returns the date as relative time. + * + * @param boolean $complete TRUE full version, FALSE short version + * @return string Relative time, for example: 1 minute ago + */ + public function relativeTime(bool $complete=false): string + { + $current = new DateTime; + $past = new DateTime($this->getValue('dateRaw')); + $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'; + } } diff --git a/bl-kernel/pages.class.php b/bl-kernel/pages.class.php index b534781a..9d1159d1 100644 --- a/bl-kernel/pages.class.php +++ b/bl-kernel/pages.class.php @@ -34,17 +34,18 @@ class Pages extends dbJSON { return $this->dbFields; } - /* Get the database row associated to a page - - @key string The key of the page to be fetch - @return array/boolean Return an array with the database for a page, FALSE otherwise - */ - public function getPageDB($key) + /** + * Returns the table row associated to a particular page. The page's content is not included. + * For example in SQL, SELECT * FROM pages WHERE key = $key + * + * @param string $key The key of the page to be fetch + * @return array Return an array with the database for a page, FALSE otherwise + */ + public function getPageDB(string $key): array { if ($this->exists($key)) { return $this->db[$key]; } - return false; } @@ -57,12 +58,13 @@ class Pages extends dbJSON { return isset ($this->db[$key]); } - /* Create a new page === Bludit v4 - - @args array The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used. - @return string/boolean Returns the page key if the page is successfully created, FALSE otherwise - */ - public function add($args) + /** + * Creates a new page. + * + * @param array $args The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used. + * @return boolean|string Returns the page key if the page is successfully created, FALSE otherwise + */ + public function add(array $args): bool|string { $row = array(); @@ -175,12 +177,13 @@ class Pages extends dbJSON { return $key; } - /* Edit a page === Bludit v4 - - @args array The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used. - @return string/boolean Returns the page key if the page is successfully edited, FALSE otherwise - */ - public function edit($args) + /** + * Edit a page. + * + * @param array $args The array $args supports all the keys from the variable $dbFields. If you don't pass all the keys, the default values are used. + * @return boolean|string Returns the page key if the page is successfully edited, FALSE otherwise + */ + public function edit(array $args): bool|string { // This is the new row for the table and is going to replace the old row $row = array(); @@ -300,12 +303,13 @@ class Pages extends dbJSON { return $newKey; } - /* Delete a page === Bludit v4 - - @key string The key of the page to be deleted - @return boolean Returns TRUE if the page was deleted successfully, FALSE otherwise - */ - public function delete($key) + /** + * Delete a page. + * + * @param string $key The key of the page to be deleted + * @return boolean Returns TRUE if the page was deleted successfully, FALSE otherwise + */ + public function delete(string $key): bool { // This is need it, because if the key is empty the Filesystem::deleteRecursive is going to delete PATH_PAGES if (empty($key)) { @@ -485,6 +489,26 @@ class Pages extends dbJSON { return $tmp; } + /** + * Returns an array with all unlisted pages + * + * @param boolean $onlyKeys If TRUE returns only the pages' keys + * @return array + */ + public function getUnlistedDB(bool $onlyKeys=true): array + { + $tmp = $this->db; + foreach ($tmp as $key=>$fields) { + if($fields['type']!='unlisted') { + unset($tmp[$key]); + } + } + if ($onlyKeys) { + return array_keys($tmp); + } + return $tmp; + } + // Returns the next number of the bigger position public function nextPositionNumber() { @@ -530,12 +554,18 @@ class Pages extends dbJSON { } /** - * Get a list of pages' keys. === Bludit v4 - * @param int $pageNumber Page number for the paginator - * @param int $numberOfItems Amount of items to return, if -1 returns all the items - * @return array|bool Returns an array with the pages' keys or FALSE if it out of range + * Get a list of pages' keys. + * + * @param integer $pageNumber Page number for the paginator + * @param integer $numberOfItems Amount of items to return, if -1 returns all the items + * @param boolean $published + * @param boolean $static + * @param boolean $sticky + * @param boolean $draft + * @param boolean $scheduled + * @return boolean|array Returns an array with the pages' keys or FALSE if it out of range */ - public function getList(int $pageNumber, int $numberOfItems, bool $published=true, bool $static=false, bool $sticky=false, bool $draft=false, bool $scheduled=false) + public function getList(int $pageNumber, int $numberOfItems, bool $published=true, bool $static=false, bool $sticky=false, bool $draft=false, bool $scheduled=false): bool|array { $list = array(); foreach ($this->db as $key=>$fields) { diff --git a/bl-languages/en.json b/bl-languages/en.json index 6b7344bc..b334d843 100644 --- a/bl-languages/en.json +++ b/bl-languages/en.json @@ -58,10 +58,12 @@ "thanks-for-supporting-bludit": "Thanks for supporting Bludit", "upgrade-to-bludit-pro": "Upgrade to Bludit PRO", "language": "Language", + "unlisted": "Unlisted", "plugin": "Plugin", "plugins": "Plugins", "developers": "Developers", "themes": "Themes", + "theme": "Theme", "about": "About", "url": "URL", "welcome": "Welcome",