bludit/bl-kernel/dbpages.class.php
2017-05-10 20:40:28 +02:00

695 lines
16 KiB
PHP

<?php defined('BLUDIT') or die('Bludit CMS.');
class dbPages extends dbJSON
{
private $parentKeyList = array();
private $dbFields = array(
'title'=> array('inFile'=>true, 'value'=>''),
'content'=> array('inFile'=>true, 'value'=>''),
'description'=> array('inFile'=>false, 'value'=>''),
'username'=> array('inFile'=>false, 'value'=>''),
'tags'=> array('inFile'=>false, 'value'=>array()),
'status'=> array('inFile'=>false, 'value'=>'draft'), // published, draft, scheduled
'date'=> array('inFile'=>false, 'value'=>''),
'dateModified'=> array('inFile'=>false, 'value'=>''),
'position'=> array('inFile'=>false, 'value'=>0),
'coverImage'=> array('inFile'=>false, 'value'=>''),
'category'=> array('inFile'=>false, 'value'=>''),
'md5file'=> array('inFile'=>false, 'value'=>''),
'uuid'=> array('inFile'=>false, 'value'=>''),
'allowComments'=> array('inFile'=>false, 'value'=>false)
);
function __construct()
{
parent::__construct(DB_PAGES);
}
// Create a new page
public function add($args)
{
$dataForDb = array(); // This data will be saved in the database
$dataForFile = array(); // This data will be saved in the file
// The user is always the one loggued
$args['username'] = Session::get('username');
if( Text::isEmpty($args['username']) ) {
return false;
}
// Generate key
$key = $this->generateKey($args['slug'], $args['parent']);
// Generate UUID
$args['uuid'] = md5( uniqid() );
// Get current date
$args['date'] = Date::current(DB_DATE_FORMAT);
foreach($this->dbFields as $field=>$options) {
if( isset($args[$field]) ) {
if($field=='tags') {
$value = $this->generateTags($args['tags']);
}
else {
if( !$options['inFile'] ) {
// Sanitize if will be stored on database
$value = Sanitize::html($args[$field]);
}
else {
$value = $args[$field];
}
}
}
else {
// Default value for the field
$value = $options['value'];
}
// Where the data is stored
if($options['inFile']) {
$dataForFile[$field] = Text::firstCharUp($field).': '.$value;
}
else {
// Set type
settype($value, gettype($options['value']));
// Save on database
$dataForDb[$field] = $value;
}
}
// Create the directory
if( Filesystem::mkdir(PATH_PAGES.$key, true) === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to create the directory '.PATH_PAGES.$key);
return false;
}
// Make the index.txt and save the file.
$data = implode("\n", $dataForFile);
if( file_put_contents(PATH_PAGES.$key.DS.FILENAME, $data) === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to put the content in the file '.FILENAME);
return false;
}
// Save the database
$this->db[$key] = $dataForDb;
if( $this->save() === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to save the database file.');
return false;
}
return $key;
}
public function edit($args)
{
$dataForDb = array();
$dataForFile = array();
// The user is always the one loggued
$args['username'] = Session::get('username');
if( Text::isEmpty($args['username']) ) {
return false;
}
$newKey = $this->generateKey($args['slug'], $args['parent'], false, $args['key']);
// If the page is draft then the time created is now
if( $this->db[$args['key']]['status']=='draft' ) {
$args['date'] = Date::current(DB_DATE_FORMAT);
}
else {
$args['date'] = $this->db[$args['key']]['date'];
}
// Current UUID
$args['uuid'] = $this->db[$args['key']]['uuid'];
// Modified date
$args['dateModified'] = Date::current(DB_DATE_FORMAT);
foreach($this->dbFields as $field=>$options) {
if( isset($args[$field]) ) {
if($field=='tags') {
$value = $this->generateTags($args['tags']);
}
else {
if( !$options['inFile'] ) {
// Sanitize if will be stored on database
$value = Sanitize::html($args[$field]);
}
else {
// Default value for the field
$value = $args[$field];
}
}
}
else {
$value = $options['value'];
}
// Where the data is stored
if($options['inFile']) {
$dataForFile[$field] = Text::firstCharUp($field).': '.$value;
}
else {
// Set type
settype($value, gettype($options['value']));
// Save on database
$dataForDb[$field] = $value;
}
}
// Move the directory from old key to new key.
if($newKey!==$args['key']) {
if( Filesystem::mv(PATH_PAGES.$args['key'], PATH_PAGES.$newKey) === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to move the directory to '.PATH_PAGES.$newKey);
return false;
}
}
// Make the index.txt and save the file.
$data = implode("\n", $dataForFile);
if( file_put_contents(PATH_PAGES.$newKey.DS.FILENAME, $data) === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to put the content in the file '.FILENAME);
return false;
}
// Remove the old key
unset( $this->db[$args['key']] );
// Save the database
$this->db[$newKey] = $dataForDb;
if( $this->save() === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to save the database file.');
return false;
}
return $newKey;
}
public function delete($key)
{
// Page doesn't exist in database
if(!$this->pageExists($key)) {
Log::set(__METHOD__.LOG_SEP.'The page does not exist. Key: '.$key);
}
// Delete the index.txt file
if( Filesystem::rmfile(PATH_PAGES.$key.DS.FILENAME) === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to delete the file '.FILENAME);
}
// Delete the directory
if( Filesystem::rmdir(PATH_PAGES.$key) === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to delete the directory '.PATH_PAGES.$key);
}
// Remove from database
unset($this->db[$key]);
// Save the database.
if( $this->save() === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to save the database file.');
}
return true;
}
// Returns a database with published pages
public function getPublishedDB()
{
$tmp = $this->db;
foreach($tmp as $key=>$fields) {
if($fields['status']!='published') {
unset($tmp[$key]);
}
}
return $tmp;
}
// Return an array with the database for a page, FALSE otherwise.
public function getPageDB($key)
{
if( $this->pageExists($key) ) {
return $this->db[$key];
}
return false;
}
// Returns an array with a list of pages
// (int) $pageNumber, the page number
// (int) $amountOfItems, amount of items to return
// (boolean) $onlyPublished, TRUE to return only published pages
public function getList($pageNumber, $amountOfItems, $onlyPublished=true)
{
$db = $this->db;
if( $onlyPublished ) {
$db = $this->getPublishedDB();
}
$total = count($db);
$init = (int) $amountOfItems * $pageNumber;
$end = (int) min( ($init + $amountOfItems - 1), $total );
$outrange = $init<0 ? true : $init>$end;
if(!$outrange) {
return array_slice($db, $init, $amountOfItems, true);
}
return array();
}
// Returns the amount of pages
// (boolean) $total, TRUE returns the total of pages
// (boolean) $total, FALSE returns the total of published pages (without draft and scheduled)
public function numberPages($onlyPublished=true)
{
if( $onlyPublished ) {
$db = $this->getPublishedDB();
return count($db);
}
return count($this->db);
}
// ----- OLD
// Set a field of the database
public function setField($key, $field, $value)
{
if( $this->pageExists($key) ) {
settype($value, gettype($this->dbFields[$key]['value']));
$this->db[$key][$field] = $value;
}
return false;
}
// Return TRUE if the page exists, FALSE otherwise.
public function pageExists($key)
{
return isset($this->db[$key]);
}
public function parentKeyList()
{
return $this->parentKeyList;
}
public function parentKeyExists($key)
{
return isset( $this->parentKeyList[$key] );
}
public function addParentKey($key)
{
$this->parentKeyList[$key] = $key;
}
// Generate a valid Key/Slug.
public function generateKey($text, $parent=NO_PARENT_CHAR, $returnSlug=false, $oldKey='')
{
if(Text::isEmpty($text)) {
$text = 'empty';
}
if( Text::isEmpty($parent) || ($parent==NO_PARENT_CHAR) ) {
$newKey = Text::cleanUrl($text);
}
else {
$newKey = Text::cleanUrl($parent).'/'.Text::cleanUrl($text);
}
if($newKey!==$oldKey) {
// Verify if the key is already been used
if( isset($this->db[$newKey]) ) {
if( !Text::endsWithNumeric($newKey) ) {
$newKey = $newKey.'-0';
}
while( isset($this->db[$newKey]) ) {
$newKey++;
}
}
}
if($returnSlug) {
$explode = explode('/', $newKey);
if(isset($explode[1])) {
return $explode[1];
}
return $explode[0];
}
return $newKey;
}
// Returns the database
public function getDB()
{
return $this->db;
}
// Returns an Array, array('tagSlug'=>'tagName')
// (string) $tags, tag list separeted by comma.
public function generateTags($tags)
{
$tmp = array();
$tags = trim($tags);
if(empty($tags)) {
return $tmp;
}
// Make array
$tags = explode(',', $tags);
foreach($tags as $tag)
{
$tag = trim($tag);
$tagKey = Text::cleanUrl($tag);
$tmp[$tagKey] = $tag;
}
return $tmp;
}
// Change all posts with the old category key for the new category key
public function changeCategory($oldCategoryKey, $newCategoryKey)
{
foreach($this->db as $key=>$value) {
if($value['category']==$oldCategoryKey) {
$this->db[$key]['category'] = $newCategoryKey;
}
}
// Save database
return $this->save();
}
public function count()
{
$count = parent::count();
// DEBUG: Less than - 1 because the error page.
return $count - 1;
}
// Return TRUE if there are new pages published, FALSE otherwise.
public function scheduler()
{
// Get current date
$currentDate = Date::current(DB_DATE_FORMAT);
$saveDatabase = false;
// The database need to be sorted by date
foreach($this->db as $pageKey=>$fields) {
if($fields['status']=='scheduled') {
if($fields['date']<=$currentDate) {
$this->db[$pageKey]['status'] = 'published';
$saveDatabase = true;
}
}
elseif($fields['status']=='published') {
break;
}
}
if($saveDatabase) {
if( $this->save() === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to save the database file.');
return false;
}
Log::set(__METHOD__.LOG_SEP.'New pages published from the scheduler.');
return true;
}
return false;
}
// --- OLD
public function cliMode()
{
// LOG
Log::set('CLI MODE - PAGES - Starting...');
$pageList = array();
$pagesDirectories = Filesystem::listDirectories(PATH_PAGES);
foreach( $pagesDirectories as $directory ) {
if( Sanitize::pathFile($directory.DS.FILENAME) ) {
// The key is the directory name
$key = basename($directory);
// Add the page key to the list
$pageList[$key] = true;
// LOG
Log::set('CLI MODE - Page found, key: '.$key);
// Search sub-pages
$subPaths = Filesystem::listDirectories($directory.DS);
foreach( $subPaths as $subDirectory )
{
// The key of the sub-page
$subKey = basename($subDirectory);
if( Sanitize::pathFile($subDirectory.DS.FILENAME) ) {
// Add the key of the sub-page, the key is composed by the directory/subdirectory
$pageList[$key.'/'.$subKey] = true;
// LOG
Log::set('CLI MODE - Page found, key: '.$key);
}
}
}
}
foreach( $pageList as $key=>$value ) {
if( !isset($this->db[$key]) ) {
// LOG
Log::set('CLI MODE - The page is not in the database, key: '.$key);
// Insert new post
$this->cliModeInsert($key);
}
else {
$checksum = md5_file(PATH_PAGES.$key.DS.FILENAME);
// If checksum is different, update the post
if( !isset($this->db[$key]['md5file']) ||
$this->db[$key]['md5file']!==$checksum ) {
// LOG
Log::set('CLI MODE - Different md5 checksum, key: '.$key);
// Update the post
$this->cliModeInsert($key, $update=true);
}
}
}
// LOG
Log::set('CLI MODE - Cleaning database...');
foreach( array_diff_key($this->db, $pageList) as $key=>$data ) {
// LOG
Log::set('CLI MODE - Removing page from database, key: '.$key);
// Remove the page from database
unset( $this->db[$key] );
}
// Save the database
$this->save();
// LOG
Log::set('CLI MODE - PAGES - Finishing...');
return true;
}
private function cliModeInsert($key, $update=false)
{
if($update) {
// LOG
Log::set('CLI MODE - cliModeInsert() - Updating the page, key: '.$key);
// Database from the current database
$dataForDb = $this->db[$key];
$dataForDb['dateModified'] = Date::current(DB_DATE_FORMAT);
}
else {
// LOG
Log::set('CLI MODE - cliModeInsert() - Inserting the new post, key: '.$key);
// Database for the new page, fields with the default values
$dataForDb = array();
foreach( $this->dbFields as $field=>$options ) {
if( !$options['inFile'] ) {
$dataForDb[$field] = $options['value'];
}
}
// Fields and value predefined in init.php
$dataForDb['username'] = CLI_USERNAME;
$dataForDb['status'] = CLI_STATUS;
$dataForDb['date'] = Date::current(DB_DATE_FORMAT);
}
// MD5 checksum
$dataForDb['md5file'] = md5_file(PATH_PAGES.$key.DS.FILENAME);
// Generate the Object from the file
$Page = new Page($key);
foreach( $this->dbFields as $field=>$options ) {
if( !$options['inFile'] ) {
// Get the field from the file
// If the field doesn't exist, the function returns FALSE
$data = $Page->getField($field);
if( $data!==false ) {
$tmpValue = '';
if( $field=='tags' ) {
$tmpValue = $this->generateTags($data);
}
elseif( $field=='date' ) {
// Validate format date from file
if( Valid::date($data, DB_DATE_FORMAT) ) {
$tmpValue = $data;
}
}
else {
$tmpValue = Sanitize::html($data);
}
settype($tmpValue, gettype($options['value']));
$dataForDb[$field] = $tmpValue;
}
}
}
// Insert row in the database
$this->db[$key] = $dataForDb;
return true;
}
public function regenerateCli()
{
$db = $this->db;
$newPaths = array();
$fields = array();
// Default fields and value
foreach($this->dbFields as $field=>$options) {
if(!$options['inFile']) {
$fields[$field] = $options['value'];
}
}
//$tmpPaths = glob(PATH_PAGES.'*', GLOB_ONLYDIR);
$tmpPaths = Filesystem::listDirectories(PATH_PAGES);
foreach($tmpPaths as $directory)
{
$key = basename($directory);
if(file_exists($directory.DS.FILENAME)) {
// The key is the directory name
$newPaths[$key] = true;
}
// Recovery pages from subdirectories
//$subPaths = glob($directory.DS.'*', GLOB_ONLYDIR);
$subPaths = Filesystem::listDirectories($directory.DS);
foreach($subPaths as $subDirectory)
{
$subKey = basename($subDirectory);
if(file_exists($subDirectory.DS.FILENAME)) {
// The key is composed by the directory/subdirectory
$newPaths[$key.'/'.$subKey] = true;
}
}
}
foreach($newPaths as $key=>$value)
{
if(!isset($this->db[$key]))
{
// Default values for the new pages.
$fields['status'] = CLI_STATUS;
$fields['date'] = Date::current(DB_DATE_FORMAT);
$fields['username'] = 'admin';
// Create the entry for the new page.
$this->db[$key] = $fields;
}
$Page = new Page($key);
// Update all fields from FILE to DATABASE.
foreach($fields as $f=>$v)
{
// If the field exists on the FILE, update it.
if($Page->getField($f))
{
$valueFromFile = $Page->getField($f);
if($f=='tags') {
// Generate tags array.
$this->db[$key]['tags'] = $this->generateTags($valueFromFile);
}
elseif($f=='date') {
// Validate Date from file
if(Valid::date($valueFromFile, DB_DATE_FORMAT)) {
$this->db[$key]['date'] = $valueFromFile;
}
}
else {
// Sanitize the values from file.
$this->db[$key][$f] = Sanitize::html($valueFromFile);
}
}
}
}
// Remove old pages from db
foreach( array_diff_key($db, $newPaths) as $key=>$data ) {
unset($this->db[$key]);
}
// Save the database.
if( $this->save() === false ) {
Log::set(__METHOD__.LOG_SEP.'Error occurred when trying to save the database file.');
return false;
}
return $this->db!=$db;
}
}