diff --git a/admin/panels/entry/admin.entry.write.php b/admin/panels/entry/admin.entry.write.php index 27b2e14..2000a14 100755 --- a/admin/panels/entry/admin.entry.write.php +++ b/admin/panels/entry/admin.entry.write.php @@ -24,6 +24,7 @@ ); var $events = array('save', 'preview', 'savecontinue'); + var $draft = false; function _makePreview($arr, $id=null) { @@ -32,24 +33,43 @@ $arr['content'] = apply_filters('content_save_pre', $arr['content']); } - + + if ($this->draft || $this->draft = draft_exists($this->id)) { + if (isset($arr['categories']) + && is_array($arr['categories']) && !in_array('draft', $arr['categories']) ) { + $arr['categories'][] = 'draft'; + } else { + $arr['categories'][] = 'draft'; + } + + } + + // unfiltered content (for editing) $this->smarty->assign('post', $arr); if (THEME_LEGACY_MODE) { theme_entry_filters($arr, $id); } - - $arr = array_change_key_case($arr, CASE_LOWER); - + + // content for preview $this->smarty->assign('entry', $arr); $this->smarty->assign('preview', true); - } function makePageTitle($title, $sep) { - global $lang; + global $lang, $panel; + if ($this->draft) { + $this->smarty->append( + 'warnings', + $lang['admin']['entry']['write']['msgs']['draft'] + ); + } return "$title $sep {$lang['admin']['entry']['write']['head']}"; } + + function draft_class($string) { + return "$string draft"; + } function _getCatsFlags() { @@ -90,6 +110,7 @@ $this->_getCatsFlags(); add_filter('wp_title', array(&$this, 'makePageTitle'), 10, 2); + if ($this->draft) add_filter('admin_body_class', array(&$this, 'draft_class')); } @@ -101,12 +122,14 @@ $author = user_get(); $arr['author'] = $author['userid']; $arr['date'] = !empty($_POST['timestamp'])?$_POST['timestamp']:date_time(); + $cats = !empty($_POST['cats'])?$_POST['cats']:array(); $flags = !empty($_POST['flags'])?$_POST['flags']:array(); $catids = array_merge(array_keys($flags), array_keys($cats)); - + + $this->draft = isset($flags['draft']); if ($catids) $arr['categories'] = $catids; @@ -119,25 +142,25 @@ $id = $this->id; $data = $this->_getposteddata(); - if (isset($data['categories']) && in_array('draft', $data['categories'])) { - - $success=draft_save($data, $id); + if ($this->draft) { + $success=draft_save($data, $id, true); + $this->smarty->assign('success', $success? 1 : -1 ); } else { - - /* anyway issued */ - - draft_to_entry($id); $success=entry_save($data, $id); - + $this->smarty->assign('success', is_numeric($success)? $success : 1 ); } - if ($success) sess_remove('entry'); - - $this->smarty->assign('success',$success? 1:-1); + // if ($success) sess_remove('entry'); + if ($do_preview) $this->_makePreview($data); - + + if ($success<0) { + $this->main(); + return PANEL_NOREDIRECT; + } + return 1; } @@ -151,6 +174,7 @@ $this->_getCatsFlags(); add_filter('wp_title', array(&$this, 'makePageTitle'), 10, 2); + if ($this->draft) add_filter('admin_body_class', array(&$this, 'draft_class')); return 0; @@ -164,7 +188,7 @@ $this->_getCatsFlags(); add_filter('wp_title', array(&$this, 'makePageTitle'), 10, 2); - + if ($this->draft) add_filter('admin_body_class', array(&$this, 'draft_class')); } diff --git a/admin/panels/maintain/admin.maintain.php b/admin/panels/maintain/admin.maintain.php index b5e239c..2e3e019 100755 --- a/admin/panels/maintain/admin.maintain.php +++ b/admin/panels/maintain/admin.maintain.php @@ -55,7 +55,7 @@ $id=basename($file,EXT); $arr=entry_parse($id, true); - echo "[POST] $id => {$arr['SUBJECT']}\n"; + echo "[POST] $id => {$arr['subject']}\n"; $this->index->add($id, $arr); return 0; diff --git a/fp-includes/core/core.bplustree.class.php b/fp-includes/core/core.bplustree.class.php index 09b24cd..78c9f01 100755 --- a/fp-includes/core/core.bplustree.class.php +++ b/fp-includes/core/core.bplustree.class.php @@ -985,7 +985,7 @@ class BPlusTree_Node { #d(implode(",",$this->keys)); #$place = array_search($key, $this->keys); $place = BPT_bisect($this->keys, $key, 0, $this->validkeys); - if (@$this->keys[$place-1] == $key) { + if ($this->keys[$place-1] == $key) { return $this->indices[$place-1]; } else { if ($loose) { @@ -2539,28 +2539,48 @@ class SBPlusTree extends BPlusTree { $this->maxstring = $maxstring; } + function startup() { + fwrite($this->stringfile, 'BPTSTRINGS'); + return parent::startup(); + } + function getstring($seek) { fseek($this->stringfile, $seek); $s = fread($this->stringfile, $this->maxstring); return rtrim($s); } - function setstring($s) { - fseek($this->stringfile, 0, SEEK_END); - $seek = ftell($this->stringfile); + function setstring($s, $key) { + $seek = $this->has_key($key); + if (!is_numeric($seek)) { + fseek($this->stringfile, 0, SEEK_END); + $seek = ftell($this->stringfile); + } else { + fseek($this->stringfile, $seek); + } // nul-pad string + if (strlen($s>$this->maxstring)) + $x = substr($s, 0, $this->maxstring); $x = str_pad($s, $this->maxstring, chr(0)); fwrite($this->stringfile, $x); return $seek; } function getitem(&$key, $loose=false) { - $seek = parent::getitem($key, $loose); - return $seek!==false? $this->getstring($seek) : false; + $seek = $this->has_key($key, $loose); + return is_numeric($seek)? $this->getstring($seek) : false; + } + + /** + * @param $key target key + * @returns int seek point if key exists, 0 otherwise + */ + function has_key($key, $loose=false) { + return @parent::getitem($key, $loose); } function setitem($key, $val) { - $seek = $this->setstring($val); + $seek = $this->setstring($val, $key); parent::setitem($key, $seek); return $seek; } diff --git a/fp-includes/core/core.draft.php b/fp-includes/core/core.draft.php index bc9fb21..3a159e6 100644 --- a/fp-includes/core/core.draft.php +++ b/fp-includes/core/core.draft.php @@ -64,7 +64,7 @@ $entry = io_load_file($fname); - $entry = array_change_key_case(utils_kexplode($entry)); + $entry = utils_kexplode($entry); if (!isset($entry['categories'])) $entry['categories'] = array(); else @@ -76,7 +76,7 @@ } - function draft_save($entry, $id=null, $update_date=false) { + function draft_save($entry, $id=null, $update_index = false, $update_date=false) { if (!$id) { $id = bdb_idfromtime('entry', $entry['date']); @@ -90,28 +90,22 @@ // move collateral files @rename($ed, $dd); - // delete normal entry - fs_delete($ed.EXT); + if ($update_index) { + // delete normal entry + fs_delete($ed.EXT); - // remove from normal flow - $o =& entry_init(); - $o->delete($id); + // remove from normal flow + $o =& entry_init(); + $o->delete($id, null); + } } - $entry['content'] = apply_filters('content_save_pre', $entry['content']); - $entry['subject'] = apply_filters('title_save_pre', $entry['subject']); - - $entry = array_change_key_case($entry, CASE_UPPER); - if (isset($entry['CATEGORIES'])) { - - if (is_array($entry['CATEGORIES'])) - $entry['CATEGORIES'] = implode(',',$entry['CATEGORIES']); - else - trigger_error("Failed saving draft. Expected 'categories' to be - an array, found " . gettype($entry['CATEGORIES']), E_USER_ERROR); - } - + $entry = entry_prepare($entry); + if ($entry['categories']) + $entry['categories']=implode(',', $entry['categories']); + else unset($entry['categories']); + $string = utils_kimplode($entry); @@ -136,9 +130,6 @@ function draft_exists($id) { - if (!user_loggedin()) - return false; - $dir = draft_dir($id); if (!$dir) return false; diff --git a/fp-includes/core/core.entry.php b/fp-includes/core/core.entry.php index b6f916d..bf3205d 100755 --- a/fp-includes/core/core.entry.php +++ b/fp-includes/core/core.entry.php @@ -100,15 +100,19 @@ return $this->indices[$cat]; } - function add($id, $entry, $del = array()) { + function add($id, $entry, $del = array(), $update_title = true) { $key = entry_idtokey($id); - $val = $entry['SUBJECT']; + $val = $entry['subject']; $main =& $this->get_index(); - $seek = $main->setitem($key, $val); - - if (isset($entry['CATEGORIES']) && is_array($entry['CATEGORIES'])) { - foreach ($entry['CATEGORIES'] as $cat) { + $seek = null; + if (!$update_title) + $seek = $main->has_key($key, $val); + + if (is_numeric($seek)) + $seek = $main->setitem($key, $val); + if (isset($entry['categories']) && is_array($entry['categories'])) { + foreach ($entry['categories'] as $cat) { if (!is_numeric($cat)) continue; $this_index =& $this->get_index($cat); $this_index->setitem($key, $seek); @@ -117,6 +121,7 @@ if ($del) { foreach($del as $cat) { + // echo 'DEL '. $cat,"\n"; $this_index =& $this->get_index($cat); $this_index->delitem($key); } @@ -126,18 +131,19 @@ } - function delete($id) { + function delete($id, $entry) { $key = entry_idtokey($id); $main =& $this->get_index(); $main->delitem($key); - $entry = entry_parse($id); + if (isset($entry['categories']) && is_array($entry['categories'])) { foreach ($entry['categories'] as $cat) { if (!is_numeric($cat)) continue; $this_index =& $this->get_index($cat); - $this_index->delitem($key); + if ($this_index->has_key($key)) + $this_index->delitem($key); } } @@ -202,10 +208,10 @@ function add($id, $val) { - $this->_list[$id]=array('subject' => $val['SUBJECT'], + $this->_list[$id]=array('subject' => $val['subject'], 'categories' => - (isset($val['CATEGORIES'])? - $val['CATEGORIES'] : array())); + (isset($val['categories'])? + $val['categories'] : array())); return $this->save(); } @@ -424,11 +430,14 @@ return file_exists($f)? $f : false; } - function entry_dir($id) { + function entry_dir($id, $month_only = false) { if (!preg_match('|^entry[0-9]{6}-[0-9]{6}$|', $id)) return false; $date = date_from_id($id); - $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/$id"; + if ($month_only) + $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/"; + else + $f = CONTENT_DIR . "{$date['y']}/{$date['m']}/$id"; return $f; @@ -450,18 +459,18 @@ // propagates the error if entry does not exist - if (isset($arr['CATEGORIES']) && // fix to bad old behaviour: - (trim($arr['CATEGORIES']) != '')) { + if (isset($arr['categories']) && // fix to bad old behaviour: + (trim($arr['categories']) != '')) { - $cats = (array)explode(',',$arr['CATEGORIES']); - $arr['CATEGORIES'] = (array) $cats; + $cats = (array)explode(',',$arr['categories']); + $arr['categories'] = (array) $cats; - } else $arr['CATEGORIES'] = array(); + } else $arr['categories'] = array(); - // if (!is_array($arr['CATEGORIES'])) die(); + // if (!is_array($arr['categories'])) die(); if (!isset($arr['AUTHOR'])) { global $fp_config; @@ -469,7 +478,7 @@ } if ($raw) return $arr; - return array_change_key_case($arr, CASE_LOWER); + return $arr; } @@ -620,62 +629,122 @@ } - - function entry_save($entry_cont, $id=null, $update_index = true) { + // @TODO : check against schema ? + function entry_prepare($entry) { // prepare for serialization global $post; - $obj =& entry_init(); - - if (!isset($entry_cont['date'])) { - $entry_cont['date']=date_time(); + // fill in missing value + if (!isset($entry['date'])) { + $entry['date']=date_time(); } - - $post = $entry_cont; - $entry = array_change_key_case($entry_cont, CASE_UPPER); + // import into global scope + $post = $entry; + + // apply *_pre filters + $entry['content'] = apply_filters('content_save_pre', $entry['content']); + $entry['subject'] = apply_filters('title_save_pre', $entry['subject']); + + + // prepare for serialization + if (isset($entry['categories'])) { + if (!is_array($entry['categories'])) { + trigger_error("Expected 'categories' to be an array, found " + . gettype($entry['categories']), E_USER_WARNING); + $entry['categories'] = array(); + } + + } else { $entry['categories'] = array(); } + + + + return $entry; + } + + function entry_save($entry, $id=null, $update_index = true) { + + // PHASE 1 : prepare entry if (!$id) { - $id = bdb_idfromtime(BDB_ENTRY, $entry['DATE']); + if (!@$entry['date']) $entry['date'] = date_time(); + $id = bdb_idfromtime(BDB_ENTRY, $entry['date']); } - do_action('publish_post', $id, $entry_cont); - - $f = bdb_idtofile($id); - - $entry['CONTENT'] = apply_filters('content_save_pre', $entry['CONTENT']); - $entry['SUBJECT'] = apply_filters('title_save_pre', $entry['SUBJECT']); - $del = array(); - if ($arr = entry_parse($id)) { - if (isset($entry['CATEGORIES']) && is_array($entry['CATEGORIES'])) - $del = array_diff($arr['categories'], $entry['CATEGORIES']); + do_action('publish_post', $id, $entry); + + // PHASE 2 : Store + + // secure data as DRAFT + $ret = draft_save($entry, $id); + + if ($ret === false) { + return -1; // FAILURE: ABORT } - - $ok = ($update_index) ? $obj->add($id, $entry, $del) : true; - + + + // PHASE 3 : Update index + $delete_cats = array(); + $all_cats = @$entry['categories']; + $update_title = false; + if ($old_entry = entry_parse($id)) { + if ($all_cats) { + $delete_cats = array_diff($old_entry['categories'], $all_cats); + } + $all_cats = $all_cats? array_merge($all_cats, $old_entry['categories']) : $old_entry['categories']; + $update_title = $entry['subject'] != $old_entry['subject']; + } + + /* + echo 'old'; + print_r($old_entry['categories']); + echo 'new'; + print_r($entry['categories']); + echo 'del'; + print_r($delete_cats); + echo 'all'; + print_r($all_cats); + */ + + $INDEX =& entry_init(); + $ok = ($update_index) ? $INDEX->add($id, $entry, $delete_cats, $update_title) : true; + + // PHASE 4 : index updated; let's move back the entry if ($ok) { + + $entryd = entry_dir($id, true); + $entryf = $entryd.$id.EXT; + $draftf = draft_exists($id); + if ($draftf === false) { // this should never happen! + if ($update_index) { + $INDEX->delete($id, $all_cats); + } + return -2; + } - - if (isset($entry['CATEGORIES'])) { - - if (is_array($entry['CATEGORIES'])) - $entry['CATEGORIES'] = implode(',',$entry['CATEGORIES']); - else - trigger_error("Failed saving entry. Expected 'categories' to be - an array, found " . gettype($entry['CATEGORIES']), E_USER_ERROR); + fs_delete($entryf); + fs_mkdir($entryd); + $ret = rename($draftf, $entryf); + + if (!$ret) { + if (draft_exists($id)) { + // rollback changes in the index + // (keep the draft file) + if ($update_index) { + $INDEX->delete($id, $all_cats); + } + return -3; + } else { echo 'zomg bacon'; + return -2; + } + } else { + // SUCCESS : delete draft, move comments along + draft_to_entry($id); + return $id; } - - $str = utils_kimplode($entry); - - if (!io_write_file($f, $str)) { - if ($update_index) - $obj->delete($id, $entry); - return false; - } else return $id; - } - return false; + return -4; } diff --git a/fp-includes/core/core.fpdb.class.php b/fp-includes/core/core.fpdb.class.php index ff52ed2..fd8c91c 100644 --- a/fp-includes/core/core.fpdb.class.php +++ b/fp-includes/core/core.fpdb.class.php @@ -773,7 +773,7 @@ if (isset($params['content']) && is_array($params['content']) && $params['content']) { //foreach ($params['entry'] as $k => $val) - $smarty->assign(array_change_key_case($params['content'], CASE_LOWER)); + $smarty->assign($params['content']); return $content; } diff --git a/fp-includes/core/core.static.php b/fp-includes/core/core.static.php index 1ed8c86..b80398c 100755 --- a/fp-includes/core/core.static.php +++ b/fp-includes/core/core.static.php @@ -26,7 +26,7 @@ function static_parse($id) { if ($fname=static_exists($id)) { $entry = io_load_file($fname); - return array_change_key_case(utils_kexplode($entry)); + return (utils_kexplode($entry)); } return array(); } @@ -35,7 +35,6 @@ function static_save($entry, $id, $oldid=null) { $fname = STATIC_DIR . $id . EXT; - $entry = array_change_key_case($entry, CASE_UPPER); $entry['CONTENT'] = apply_filters('content_save_pre', $entry['CONTENT']); $entry['SUBJECT'] = apply_filters('title_save_pre', $entry['SUBJECT']); @@ -106,7 +105,7 @@ if (isset($params['content']) && is_array($params['content']) && $params['content']) { //foreach ($params['entry'] as $k => $val) - $smarty->assign(array_change_key_case($params['content'], CASE_LOWER)); + $smarty->assign($params['content']); return $content; } diff --git a/fp-includes/core/core.utils.php b/fp-includes/core/core.utils.php index 8289525..1d7b956 100644 --- a/fp-includes/core/core.utils.php +++ b/fp-includes/core/core.utils.php @@ -85,8 +85,9 @@ if (!function_exists('fnmatch')) { function utils_kexplode($string, $delim='|', $keyupper=true) { $arr = array(); $string = trim($string); - - $arr[strtok($string, $delim)] = strtok($delim); + + $k = strtolower(strtok($string, $delim)); + $arr[$k] = strtok($delim); while (( $k = strtok($delim) ) !== false) { if ($keyupper && !preg_match('/[A-Z-_]/',$k)){ /* @@ -100,7 +101,7 @@ if (!function_exists('fnmatch')) { continue; } - $arr[$k] = strtok($delim); + $arr[strtolower($k)] = strtok($delim); } return $arr; @@ -156,10 +157,11 @@ if (!function_exists('fnmatch')) { // $arr['key1'] = 'value1'; $arr['key2'] = 'value2'; etc. function utils_kimplode($arr, $delim='|') { + $string = ""; foreach ($arr as $k => $val) { if ($val) - $string .= $k . $delim . $val . $delim; + $string .= strtoupper($k) . $delim . ($val) . $delim; } return $string; } diff --git a/fp-interface/lang/en-us/lang.admin.entry.php b/fp-interface/lang/en-us/lang.admin.entry.php index 7b1188b..d242795 100755 --- a/fp-interface/lang/en-us/lang.admin.entry.php +++ b/fp-interface/lang/en-us/lang.admin.entry.php @@ -73,8 +73,10 @@ $lang['admin']['entry']['write']['msgs'] = array( 1 => 'Entry has been saved successfully', - -1 => 'An error occurred while trying to save - the entry', + -1 => 'An error occurred: your entry could not be saved successfully', + -2 => 'An error occurred: your entry has not been saved; index might have become corrupt', + -3 => 'An error occurred: your entry has been saved as draft', + -4 => 'An error occurred: your entry has been saved as draft; index might have become corrupt', 'draft'=> 'You are editing a draft entry' ); diff --git a/fp-interface/themes/leggero/cpheader.tpl b/fp-interface/themes/leggero/cpheader.tpl index f30a7da..83ea68e 100644 --- a/fp-interface/themes/leggero/cpheader.tpl +++ b/fp-interface/themes/leggero/cpheader.tpl @@ -7,7 +7,7 @@ {action hook=admin_head} -
+