Index: textpattern/include/txp_article.php =================================================================== --- textpattern/include/txp_article.php (revision 2651) +++ textpattern/include/txp_article.php (working copy) @@ -12,6 +12,7 @@ */ include_once(txpath.'/lib/classMarkup.php'); +include_once(txpath.'/lib/txplib_revisions.php'); if (!defined('txpinterface')) die('txpinterface is undefined.'); @@ -150,6 +151,8 @@ uid = '".md5(uniqid(rand(),true))."', feed_time = now()" ); + + add_article_revision($ID); if ($Status>=4) { @@ -273,6 +276,8 @@ "ID = $ID" ); + add_article_revision($ID); + if($Status >= 4) { if ($oldArticle['Status'] < 4) { do_pings(); @@ -301,6 +306,8 @@ } else { $ID = gps('ID'); } + + $rev = gps('revision'); // switch to 'text' view upon page load and after article post if(!$view || gps('save') || gps('publish')) { @@ -317,14 +324,26 @@ && $from_view != 'html') { $ID = assert_int($ID); - $article = safe_row( - "*, unix_timestamp(Posted) as sPosted, - unix_timestamp(Expires) as sExpires, - unix_timestamp(LastMod) as sLastMod", - "textpattern", - "ID=$ID" - ); + + if (!empty($rev)) { + $article_rev = get_revision($ID,$rev); + if ($article_rev) { + $article = $article_rev['data']; + $article['sPosted'] = strtotime($article['Posted']); + $article['sExpires'] = ($article['Expires'] == '0000-00-00 00:00:00') ? 0 : strtotime($article['Expires']); + $article['sLastMod'] = strtotime($article['LastMod']); + } + } else { + $article = safe_row( + "*, unix_timestamp(Posted) as sPosted, + unix_timestamp(Expires) as sExpires, + unix_timestamp(LastMod) as sLastMod", + "textpattern", + "ID=$ID" + ); + } + extract($article); $article['reset_time'] = $article['publish_now'] = ($Status < 4); @@ -389,11 +408,14 @@ { echo hInput('store', base64_encode(serialize($article))); } + + $revision = gps('revision'); echo hInput('ID', $ID). eInput('article'). sInput($step). ''. + (!empty($revision) ? hInput('revision', $revision) : ''). startTable('edit'). @@ -454,8 +476,29 @@ echo ''; } + echo ''; - echo ''; + $revisions = get_revisions($ID); + + if (!empty($revisions)) { + echo '

'.gTxt('revision_history').''.'

'. + ''; + } } else @@ -481,12 +524,17 @@ { echo '

'; - if ( ($Status == 4 or $Status == 5) and $step != 'create') { + $revision = gps('revision'); + + if ( ($Status == 4 or $Status == 5) and $step != 'create' and empty($revision)) { include_once txpath.'/publish/taghandlers.php'; echo sp.sp.'['.gTxt('view').']'; } + if (!empty($revision)) + echo sp.sp.'['.gTxt('Revision',array($revision)).']'; + echo '
'. n.'

'; } @@ -1010,4 +1058,29 @@ } } -?> + +//-------------------------------------------------------------- + function add_article_revision($ID) + { + global $prefs; + + if ($ID) { + // get the new article + $rs = safe_row('*', 'textpattern', "ID = $ID"); + + if ($rs) { + // get the article's last version + $rev = get_revision($ID); + + if (isset($prefs['custom_article_compare_func']) and is_callable($prefs['custom_article_compare_func'])) + $changed = call_user_func($prefs['custom_article_compare_func'], array($rs, $rev)); + else + $changed = true; + + if ($changed) + add_revision($ID, $rs); + } + } + } + +?> \ No newline at end of file Index: textpattern/lib/txplib_revisions.php =================================================================== --- textpattern/lib/txplib_revisions.php (revision 0) +++ textpattern/lib/txplib_revisions.php (revision 0) @@ -0,0 +1,149 @@ +limit(1) : " AND version = $ver") ); + + if ($rev) + $rev['data'] = decode_revision_data($rev['data']); + } + + return $rev; + } + +//------------------------------------------------------------- + function get_revision_count($id, $type='article') + { + if (empty($id)) + return false; + + $id = assert_int($id); + $type = doSlash($type); + + if ($id !== false && !empty($type)) + return safe_count('txp_revisions', "type = '$type' AND id = $id"); + + return false; + } + +//------------------------------------------------------------- + function get_next_revision_number($id, $type='article') + { + global $DB; + + if (empty($id)) + return false; + + $id = assert_int($id); + $type = doSlash($type); + + $rev = 0; + + if ($id !== false && !empty($type)) { + $rev = safe_field('version', 'txp_revisions', "type = '$type' AND id = $id ORDER BY version DESC " . $DB->limit(1)); + + if (!$rev) + $rev = 0; + + } + + return $rev + 1; + } + +//------------------------------------------------------------- + function add_revision($id, $data, $type='article', $user='') + { + global $txp_user; + + if (empty($id)) + return false; + + if (empty($user)) $user = $txp_user; + + $id = assert_int($id); + + $data = encode_revision_data($data); + + if ($id !== false && !empty($type) && !empty($user)) { + + $version = get_next_revision_number($id, $type); + + $id = doSlash($id); + $version = doSlash($version); + $type = doSlash($type); + $user = doSlash($user); + + return safe_insert('txp_revisions', "id = $id, version = $version, type = '$type', user = '$user', modified = now(), data = '$data'"); + } + + return false; + } +?> \ No newline at end of file Index: textpattern/model/txp_tables.php =================================================================== --- textpattern/model/txp_tables.php (revision 2651) +++ textpattern/model/txp_tables.php (working copy) @@ -449,4 +449,27 @@ } +class txp_revisions_table extends zem_table +{ + + var $_table_name = 'txp_revisions'; + + var $_cols = array( + 'id' => ZEM_FOREIGN_KEY .' NOT NULL', + 'version' => "smallint NOT NULL default '1'", + 'type' => "varchar(64) NOT NULL default ''", + 'user' => "varchar(64) NOT NULL default ''", + 'modified' => ZEM_DATETIME . " NOT NULL default '0000-00-00 00:00:00'", + 'data' => ZEM_MEDIUMTEXT, + ); + + var $_primary_key = ''; + + function create_table(){ + parent::create_table(); + safe_upgrade_index($this->_table_name,'revision_version','UNIQUE','type,id,version'); + } +} + + ?> \ No newline at end of file Index: textpattern/setup/txpsql.php =================================================================== --- textpattern/setup/txpsql.php (revision 2651) +++ textpattern/setup/txpsql.php (working copy) @@ -28,6 +28,7 @@ $datetime = 'timestamp without time zone'; $autoinc = 'SERIAL NOT NULL'; $mediumtext = 'text'; + $longtext = 'text'; $tinytext = 'text'; $tabletype = ''; $incval = 'DEFAULT'; @@ -53,6 +54,7 @@ $datetime = 'datetime'; $autoinc = 'INT NOT NULL AUTO_INCREMENT'; $incval = 'NULL'; + $longtext = 'longtext'; $mediumtext = 'mediumtext'; $tinytext = 'tinytext'; } @@ -64,6 +66,7 @@ $zerodatetime = $zerodate.' 00:00:00'; $datetime = 'datetime'; $autoinc = 'INTEGER'; + $longtext = 'text'; $mediumtext = 'text'; $tinytext = 'text'; $tabletype = ''; @@ -416,6 +419,16 @@ $create_sql[] = "INSERT INTO ".PFX."txp_prefs VALUES (1, 'dbupdatetime', '1122194504', 2, 'publish', 'text_input', 0)"; $create_sql[] = "INSERT INTO ".PFX."txp_prefs VALUES (1, 'version', '1.0rc4', 2, 'publish', 'text_input', 0)"; +$create_sql[] = "CREATE TABLE ".PFX."txp_revisions ( + id bigint NOT NULL, + version smallint NOT NULL default '1', + type varchar(64) NOT NULL default '', + user varchar(64) NOT NULL default '', + modified $datetime NOT NULL default '$zerodatetime', + data $mediumtext NOT NULL default '', + KEY (id, version, type) +) $tabletype"; + $create_sql[] = "CREATE TABLE ".PFX."txp_section ( name varchar(128) NOT NULL default '', page varchar(128) NOT NULL default '', Index: textpattern/textpattern.css =================================================================== --- textpattern/textpattern.css (revision 2651) +++ textpattern/textpattern.css (working copy) @@ -522,6 +522,17 @@ height: 85px; } +#revisions { +border-top: 1px dashed #ccc; +} + +.revision { +padding-top: .5em; +padding-bottom: .5em; +border-bottom: 1px dashed #ccc; +} + + /* comments ----------------------------------------------- */