Skip to content

Commit

Permalink
Merge 62afe99 into 50fadb1
Browse files Browse the repository at this point in the history
  • Loading branch information
John Milmine committed Oct 2, 2016
2 parents 50fadb1 + 62afe99 commit 772ae06
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 3 deletions.
28 changes: 28 additions & 0 deletions code/controllers/BaseElementController.php
Expand Up @@ -17,4 +17,32 @@ public function WidgetHolder()
{
return $this->renderWith("ElementHolder");
}


public function Link($action = null)
{

if($this->data()->virtualOwner) {
$controller = new BaseElement_Controller($this->data()->virtualOwner);
return $controller->Link($action);
}

return Parent::Link($action);
}


/**
* if this is a virtual request, change the hash if set.
*/
public function redirect($url, $code=302) {

if($this->data()->virtualOwner) {
$parts = explode('#', $url);
if(isset($parts[1])) {
$url = $parts[0] . '#' . $this->data()->virtualOwner->ID;
}
}

return parent::redirect($url, $code);
}
}
28 changes: 28 additions & 0 deletions code/extensions/BaseElementExtension.php
Expand Up @@ -38,4 +38,32 @@ public function canCreate($member = null)
{
return (Permission::check('CMS_ACCESS_CMSMain', 'any', $member)) ? true : null;
}

/**
* Handles unpublishing as VersionedDataObjects doesn't
* Modelled on SiteTree::doUnpublish
*
*/
public function doUnpublish() {
if(!$this->owner->ID) return false;

$this->owner->extend('onBeforeUnpublish');

$origStage = Versioned::get_reading_mode();
Versioned::set_reading_mode('Stage.Live');

// This way our ID won't be unset
$clone = clone $this->owner;
$clone->delete();

Versioned::set_reading_mode($origStage);

$virtualLinkedElements = $this->owner->getPublishedVirtualLinkedElements();
if ($virtualLinkedElements) foreach($virtualLinkedElements as $vle) $vle->doUnpublish();

$this->owner->extend('onAfterUnpublish');

return true;
}

}
42 changes: 42 additions & 0 deletions code/extensions/ElementPageExtension.php
Expand Up @@ -227,6 +227,48 @@ public function onBeforeWrite()
parent::onBeforeWrite();
}

/**
* Ensure that if there are elements that belong to this page
* and are virtualised (Virtual Element links to them), that we move the
* original element to replace one of the virtual elements
* But only if it's a delete not an unpublish
*/
public function onAfterDelete() {
if(Versioned::get_reading_mode() == 'Stage.Stage') {
$area = $this->owner->ElementArea();
foreach ($area->Widgets() as $element) {
$firstVirtual = false;
if ($element->getPublishedVirtualLinkedElements()->Count() > 0) {
// choose the first one
$firstVirtual = $element->getPublishedVirtualLinkedElements()->First();
$wasPublished = true;
} else if ($element->getVirtualLinkedElements()->Count() > 0) {
// choose the first one
$firstVirtual = $element->getVirtualLinkedElements()->First();
$wasPublished = false;
}
if ($firstVirtual) {
$origParentID = $element->ParentID;
$origSort = $element->Sort;

// change element to first's values
$element->ParentID = $firstVirtual->ParentID;
$element->Sort = $firstVirtual->Sort;

$firstVirtual->ParentID = $origParentID;
$firstVirtual->Sort = $origSort;
// write
$element->write();
$firstVirtual->write();
if ($wasPublished) {
$element->doPublish();
$firstVirtual->doPublish();
}
}
}
}
}

/**
* @return boolean
*/
Expand Down
96 changes: 95 additions & 1 deletion code/models/BaseElement.php
Expand Up @@ -63,6 +63,12 @@ class BaseElement extends Widget
*/
private static $enable_title_in_template = false;

/**
* @var Object
* The virtual owner VirtualLinkedElement
*/
public $virtualOwner;


public function getCMSFields()
{
Expand Down Expand Up @@ -176,6 +182,64 @@ public function onBeforeWrite()
}
}

/**
* Ensure that if there are elements that are virtualised from this element
* that we move the original element to replace one of the virtual elements
* But only if it's a delete not an unpublish
*/
public function onBeforeDelete() {
parent::onBeforeDelete();

if(Versioned::get_reading_mode() == 'Stage.Stage') {
$firstVirtual = false;
$allVirtual = $this->getVirtualLinkedElements();
if ($this->getPublishedVirtualLinkedElements()->Count() > 0) {
// choose the first one
$firstVirtual = $this->getPublishedVirtualLinkedElements()->First();
$wasPublished = true;
} else if ($allVirtual->Count() > 0) {
// choose the first one
$firstVirtual = $this->getVirtualLinkedElements()->First();
$wasPublished = false;
}
if ($firstVirtual) {
$origParentID = $this->ParentID;
$origSort = $this->Sort;

$clone = $this->duplicate(false);

// set clones values to first virtual's values
$clone->ParentID = $firstVirtual->ParentID;
$clone->Sort = $firstVirtual->Sort;

$clone->write();
if ($wasPublished) {
$clone->doPublish();
$firstVirtual->doUnpublish();
}

// clone has a new ID, so need to repoint
// all the other virtual elements
foreach($allVirtual as $virtual) {
if ($virtual->ID == $firstVirtual->ID) {
continue;
}
$pub = false;
if ($virtual->isPublished()) {
$pub = true;
}
$virtual->LinkedElementID = $clone->ID;
$virtual->write();
if ($pub) {
$virtual->doPublish();
}
}

$firstVirtual->delete();
}
}
}

/**
* @return string
*/
Expand Down Expand Up @@ -230,6 +294,10 @@ public function ControllerTop()

public function getPage()
{
if ($this->virtualOwner) {
return $this->virtualOwner->getPage();
}

$area = $this->Parent();

if ($area instanceof ElementalArea) {
Expand Down Expand Up @@ -267,7 +335,7 @@ public function onBeforeVersionedPublish()

}

public static function all_allowed_elements() {
public static function all_allowed_elements() {
$classes = array();

// get all dataobject with the elemental extension
Expand Down Expand Up @@ -312,4 +380,30 @@ public function getDefaultSearchContext()
$filters
);
}

public function setVirtualOwner(ElementVirtualLinked $virtualOwner) {
$this->virtualOwner = $virtualOwner;
}

/**
* Finds and returns elements
* that are virtual elements which link to this element
*/
public function getVirtualLinkedElements() {
return ElementVirtualLinked::get()->filter('LinkedElementID', $this->ID);
}

/**
* Finds and returns published elements
* that are virtual elements which link to this element
*/
public function getPublishedVirtualLinkedElements() {
$current = Versioned::get_reading_mode();
Versioned::set_reading_mode('Stage.Live');
$v = $this->getVirtualLinkedElements();
Versioned::set_reading_mode($current);
return $v;
}
}


70 changes: 68 additions & 2 deletions code/models/ElementVirtualLinked.php
Expand Up @@ -36,6 +36,11 @@ public function i18n_singular_name()
return _t(__CLASS__, $this->LinkedElement()->config()->title);
}

public function __construct($record = null, $isSingleton = false, $model = null) {
parent::__construct($record, $isSingleton, $model);
$this->LinkedElement()->setVirtualOwner($this);
}

public function getCMSFields() {
$message = sprintf('<p>%s</p><p><a href="%2$s">%2$s</a></p>',
_t('ElementVirtualLinked.DESCRIBE', 'This is a virtual copy of a block. To edit, visit'),
Expand All @@ -55,7 +60,68 @@ public function getCMSFields() {
return $fields;
}

public function getExtraClass() {
return $this->LinkedElement()->ClassName . ' ' . $this->getField('ExtraClass');
}

class ElementVirtualLinked_Controller extends BaseElement_Controller {

protected $controllerClass;

public function __construct($widget) {
parent::__construct($widget);

$controllerClass = get_class($this->LinkedElement()) . '_Controller';
if(class_exists($controllerClass)) {
$this->controllerClass = $controllerClass;
} else {
$this->controllerClass = 'BaseElement_Controller';
}
}

/**
* Returns the current widget in scope rendered into its' holder
*
* @return HTML
*/
public function WidgetHolder()
{
return $this->renderWith("ElementHolder_VirtualLinked");
}

public function __call($method, $arguments) {
try {
$retVal = parent::__call($method, $arguments);

} catch (Exception $e) {
$controller = new $this->controllerClass($this->LinkedElement());
$retVal = call_user_func_array(array($controller, $method), $arguments);
}
return $retVal;
}

public function hasMethod($action) {
if(parent::hasMethod($action)) {
return true;
}

$controller = new $this->controllerClass($this->LinkedElement());
return $controller->hasMethod($action);
}

public function hasAction($action) {
if(parent::hasAction($action)) {
return true;
}

$controller = new $this->controllerClass($this->LinkedElement());
return $controller->hasAction($action);
}

public function checkAccessAction($action) {
if(parent::checkAccessAction($action)) {
return true;
}

$controller = new $this->controllerClass($this->LinkedElement());
return $controller->checkAccessAction($action);
}
}
3 changes: 3 additions & 0 deletions templates/ElementHolder_VirtualLinked.ss
@@ -0,0 +1,3 @@
<div class="element $ClassName $LinkedElement.ClassName<% if $LinkedElement.ExtraClass %> $LinkedElement.ExtraClass<% end_if %>" id="e{$LinkedElement.ID}">
$Widget
</div>

0 comments on commit 772ae06

Please sign in to comment.