Skip to content

Commit

Permalink
No commit message
Browse files Browse the repository at this point in the history
  • Loading branch information
rixth committed Nov 11, 2009
0 parents commit 6e63bf5
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 0 deletions.
4 changes: 4 additions & 0 deletions _config.php
@@ -0,0 +1,4 @@
<?php

Object::add_extension('SiteTree', 'ConcurrentEditingSiteTree');
Object::add_extension('LeftAndMain', 'ConcurrentEditingLeftAndMain');
58 changes: 58 additions & 0 deletions code/ConcurrentEditingLeftAndMain.php
@@ -0,0 +1,58 @@
<?php

class ConcurrentEditingLeftAndMain extends LeftAndMainDecorator {
static $allowed_actions = array(
'concurrentEditingPing',
);

static $edit_timeout = 35;


function init() {
parent::init();
Requirements::javascript('concurrentediting/javascript/ConcurrentEditing.js');
}

function concurrentEditingPing() {
if (!isset($_REQUEST['ID'])) die('no id passed');

$page = $this->owner->getRecord($_REQUEST['ID']);
if (!$page) {
// Page has not been found
$return = array('status' => 'not_found');
} elseif ($page->getIsDeletedFromStage()) {
// Page has been deleted from stage
$return = array('status' => 'deleted');
} else {
// Mark me as editing if I'm not already
$page->UsersCurrentlyEditing()->add(Member::currentUser());
DB::query("UPDATE SiteTree_UsersCurrentlyEditing SET LastPing = '".date('Y-m-d H:i:s')."'
WHERE MemberID = ".Member::currentUserID()." AND SiteTreeID = {$page->ID}");

// Page exists, who else is editing it?
$names = array();
foreach($page->UsersCurrentlyEditing() as $user) {
if ($user->ID == Member::currentUserId()) continue;
$names[] = trim($user->FirstName . ' ' . $user->Surname);
}
$return = array('status' => 'editing', 'names' => $names);

// Has it been published since the CMS first loaded it?
$usersSaveCount = isset($_REQUEST['SaveCount']) ? $_REQUEST['SaveCount'] : $page->SaveCount;
if ($usersSaveCount < $page->SaveCount) {
$return = array('status' => 'not_current_version');
}
}

// Delete pings older than *timeout* from the cache...
DB::query("DELETE FROM SiteTree_UsersCurrentlyEditing WHERE LastPing < '".date('Y-m-d H:i:s', time()-self::$edit_timeout)."'");

return Convert::array2json($return);
}

function onAfterSave(&$record) {
$record->SaveCount++;
$record->writeWithoutVersion();
FormResponse::add('CurrentPage.setSaveCount('.$record->SaveCount.');');
}
}
27 changes: 27 additions & 0 deletions code/ConcurrentEditingSiteTree.php
@@ -0,0 +1,27 @@
<?php

class ConcurrentEditingSiteTree extends DataObjectDecorator {
function extraStatics() {
return array(
'db' => array(
'SaveCount' => 'Int'
),
'defaults' => array(
'SaveCount' => '0'
),
'many_many' => array(
'UsersCurrentlyEditing' => 'Member'
),
'many_many_extraFields' => array(
'UsersCurrentlyEditing' => array(
'LastPing' => 'SSDatetime'
)
)
);
}

function updateCMSFields(&$fields) {
$alert = new LiteralField("SiteTree_Alert", '<div deletedfromstage="'.((int) $this->owner->getIsDeletedFromStage()).'" savecount="'.$this->owner->SaveCount.'" id="SiteTree_Alert"></div>');
$fields->insertBefore($alert, 'Root');
}
}
59 changes: 59 additions & 0 deletions javascript/ConcurrentEditing.js
@@ -0,0 +1,59 @@
var pagePingInterval = 15;

var CurrentPage = {
id: function() { return $('Form_EditForm_ID') ? $('Form_EditForm_ID').value : null; },
saveCount: function() { return $('SiteTree_Alert') ? $('SiteTree_Alert').getAttribute('savecount') : null; },
setSaveCount: function(count) { if ($('SiteTree_Alert')) { $('SiteTree_Alert').setAttribute('savecount', count); } },
isDeleted: function() { return $('SiteTree_Alert') ? $('SiteTree_Alert').getAttribute('deletedfromstage') : null; }
}

setInterval(function() {
if ($('Form_EditForm_ID')) {
new Ajax.Request("admin/concurrentEditingPing?ID="+CurrentPage.id()+'&SaveCount='+CurrentPage.saveCount(), {
onSuccess: function(t) {
var data = eval('('+t.responseText+')');
var hasAlert = false;

switch(data.status) {
case 'editing':
$('SiteTree_Alert').style.border = '2px solid #B5D4FE';
$('SiteTree_Alert').style.backgroundColor = '#F8FAFC';
if (data.names.length) {
hasAlert = true;
$('SiteTree_Alert').innerHTML = "This page is also being edited by: "+data.names.join(', ');
}
break;
case 'deleted':
// handle deletion by another user (but not us, or if we're already looking at a deleted version)
if (CurrentPage.isDeleted() == 0) {
$('SiteTree_Alert').style.border = '2px solid #ffd324';
$('SiteTree_Alert').style.backgroundColor = '#fff6bf';
$('SiteTree_Alert').innerHTML = "This page has been deleted since you opened it.";
hasAlert = true;
}
break;
case 'not_current_version':
// handle another user publishing
$('SiteTree_Alert').style.border = '2px solid #FFD324';
$('SiteTree_Alert').style.backgroundColor = '#fff6bf';
$('SiteTree_Alert').innerHTML = "This page has been saved since you opened it. You may want to reload it, or risk overwriting changes.";
hasAlert = true;
break;
case 'not_found':
break;
}

if (hasAlert) {
$('SiteTree_Alert').style.padding = '5px';
$('SiteTree_Alert').style.marginBottom = '5px';
$('SiteTree_Alert').style.display = 'block';
} else {
$('SiteTree_Alert').innerHTML = '';
$('SiteTree_Alert').style.padding = '0px';
$('SiteTree_Alert').style.marginBottom = '0px';
if ($('SiteTree_Alert').style.display != 'none') $('SiteTree_Alert').style.display = 'none';
}
}
});
}
}, pagePingInterval*1000);

0 comments on commit 6e63bf5

Please sign in to comment.