-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from PortableSteve/merge-ss4-changes
Merge ss4 changes
- Loading branch information
Showing
6 changed files
with
253 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,33 @@ | ||
<?php | ||
|
||
class sgn_hasoneedit_DataObjectExtension extends DataExtension { | ||
const separator = '-_1_-'; | ||
|
||
public function onBeforeWrite() { | ||
/** | ||
* @see DataObject::onBeforeWrite} | ||
*/ | ||
public function onBeforeWrite() | ||
{ | ||
$changed = $this->owner->getChangedFields(); | ||
$toWrite = array(); | ||
foreach($changed as $name => $value) { | ||
if(!strpos($name, self::separator)) { | ||
// Also skip $name that starts with a separator | ||
continue; | ||
} | ||
$value = (string)$value['after']; | ||
list($hasone, $key) = explode(self::separator, $name, 2); | ||
if($this->owner->has_one($hasone) || $this->owner->belongs_to($hasone)) { | ||
$rel = $this->owner->getComponent($hasone); | ||
|
||
// Get original: | ||
$original = (string)$rel->__get($key); | ||
if($original !== $value) { | ||
$rel->setCastedField($key, $value); | ||
$toWrite[$hasone] = $rel; | ||
} | ||
} | ||
$toWrite = []; | ||
|
||
foreach ($changed as $name => $value) { | ||
if (!HasOneEdit::isHasOneEditField($name)) continue; | ||
|
||
list($relationName, $fieldOnRelation) = HasOneEdit::getRelationNameAndField($name); | ||
$relatedObject = HasOneEdit::getRelationRecord($this->owner, $relationName); | ||
if ($relatedObject === null) continue; | ||
|
||
$relatedObject->setCastedField($fieldOnRelation, $value['after']); | ||
if ($relatedObject->isChanged(null, DataObject::CHANGE_VALUE)) { | ||
$toWrite[$relationName] = $relatedObject; | ||
} | ||
|
||
} | ||
foreach($toWrite as $rel => $obj) { | ||
|
||
foreach ($toWrite as $relationName => $obj) { | ||
$obj->write(); | ||
$key = $rel . 'ID'; | ||
if(!$this->owner->$key) { | ||
$this->owner->$key = $obj->ID; | ||
} | ||
$this->owner->setField("{$relationName}ID", $obj->ID); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
|
||
/** | ||
* Class HasOneEdit | ||
*/ | ||
class HasOneEdit | ||
{ | ||
/** | ||
* | ||
*/ | ||
const FIELD_SEPARATOR = '-_1_-'; | ||
|
||
/** | ||
* | ||
*/ | ||
const SUPPORTED_SEPARATORS = [ | ||
self::FIELD_SEPARATOR, | ||
':', | ||
'/', | ||
]; | ||
|
||
/** | ||
* @param FormField|string $field | ||
* @return string[] Array of [relation name, field on relation] | ||
*/ | ||
public static function getRelationNameAndField($field) | ||
{ | ||
if (!is_string($field)) { | ||
$field = $field->getName(); | ||
} | ||
|
||
return explode(static::FIELD_SEPARATOR, $field, 2); | ||
} | ||
|
||
/** | ||
* @param DataObject $parent | ||
* @param string $relationName | ||
* @return DataObject|null | ||
*/ | ||
public static function getRelationRecord(DataObject $parent, $relationName) | ||
{ | ||
return ($parent->hasOneComponent($relationName) || $parent->belongsToComponent($relationName, false)) | ||
? $parent->getComponent($relationName) | ||
: null; | ||
} | ||
|
||
/** | ||
* @param FormField|string $field | ||
* @return bool | ||
*/ | ||
public static function isHasOneEditField($field) | ||
{ | ||
if (!is_string($field)) { | ||
$field = $field->getName(); | ||
} | ||
|
||
return boolval(strpos($field, static::FIELD_SEPARATOR)); | ||
} | ||
|
||
/** | ||
* @param string $fieldName | ||
* @return string | ||
*/ | ||
public static function normaliseSeparator($fieldName) | ||
{ | ||
return str_replace(static::SUPPORTED_SEPARATORS, static::FIELD_SEPARATOR, $fieldName); | ||
} | ||
|
||
/** | ||
* @param DataObject $parent | ||
* @param string $relation | ||
* @return FieldList|FormField[] | ||
*/ | ||
public static function getInlineFields(DataObject $parent, $relation) | ||
{ | ||
/** @var DataObject|ProvidesHasOneInlineFields $relatedObject */ | ||
$relatedObject = static::getRelationRecord($parent, $relation); | ||
return $relatedObject->provideHasOneInlineFields($relation); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
<?php | ||
|
||
/** | ||
* Class HasOneUploadField | ||
*/ | ||
class HasOneUploadField extends UploadField | ||
{ | ||
|
||
/** | ||
* HasOneUploadField constructor. | ||
* @param UploadField $original | ||
*/ | ||
public function __construct(UploadField $original) | ||
{ | ||
if (!HasOneEdit::isHasOneEditField($original)) { | ||
throw new InvalidArgumentException('Original upload field passed to HasOneUploadField must have the has_one separator "' . | ||
HasOneEdit::FIELD_SEPARATOR . '" in its name.'); | ||
} | ||
|
||
parent::__construct($original->getName(), $original->title, $original->getItems()); | ||
|
||
// Copy state from original upload field | ||
foreach (get_object_vars($original) as $prop => $value) { | ||
$this->{$prop} = $value; | ||
} | ||
} | ||
|
||
/** | ||
* @see UploadField::saveInto() | ||
* @inheritDoc | ||
*/ | ||
public function saveInto(DataObjectInterface $record) | ||
{ | ||
list($relationName, $fieldOnRelation) = HasOneEdit::getRelationNameAndField($this); | ||
$record = HasOneEdit::getRelationRecord($this->getRecord(), $relationName); | ||
|
||
// Check type of relation | ||
$relation = $record->hasMethod($fieldOnRelation) ? $record->$fieldOnRelation() : null; | ||
if ($relation && ($relation instanceof RelationList || $relation instanceof UnsavedRelationList)) { | ||
// has_many or many_many | ||
$relation->setByIDList($this->getItemIDs()); | ||
} else if ($class = $record->hasOneComponent($fieldOnRelation)) { | ||
// Get details to save | ||
$idList = $this->getItemIDs(); | ||
|
||
// Assign has_one ID | ||
$id = !empty($idList) ? reset($idList) : 0; | ||
$record->setField("{$fieldOnRelation}ID", $id); | ||
|
||
// Polymorphic asignment | ||
if ($class === DataObject::class) { | ||
$file = $id ? File::get()->byID($id) : null; | ||
$fileClass = $file ? get_class($file) : File::class; | ||
$record->{"{$fieldOnRelation}Class"} = $id ? $fileClass : null; | ||
} | ||
|
||
// Write has one record | ||
$record->write(); | ||
} | ||
|
||
return $this; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
/** | ||
* Trait ProvidesHasOneInlineFields | ||
* @mixin DataObject | ||
*/ | ||
trait ProvidesHasOneInlineFields | ||
{ | ||
/** | ||
* @param string $relationName | ||
* @return FieldList|FormField[] | ||
*/ | ||
public function provideHasOneInlineFields($relationName) | ||
{ | ||
$fields = $this->getCMSFields()->dataFields(); | ||
|
||
foreach ($fields as $name => $field) { | ||
$field->setName($relationName . HasOneEdit::FIELD_SEPARATOR . $field->getName()); | ||
} | ||
|
||
return $fields; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,53 @@ | ||
<?php | ||
|
||
class sgn_hasoneedit_UpdateFormExtension extends \Extension { | ||
public function updateEditForm(\Form $form) { | ||
class sgn_hasoneedit_UpdateFormExtension extends Extension { | ||
|
||
/** | ||
* @param Form $form | ||
*/ | ||
public function updateItemEditForm(Form $form) | ||
{ | ||
$this->updateEditForm($form); | ||
} | ||
|
||
/** | ||
* @param Form $form | ||
*/ | ||
public function updateEditForm(Form $form) | ||
{ | ||
$record = $form->getRecord(); | ||
$fields = $form->Fields()->dataFields(); | ||
|
||
foreach($fields as $name => $field) { | ||
$name = str_replace(array(':', '/'), sgn_hasoneedit_DataObjectExtension::separator, $name); | ||
if(!strpos($name, sgn_hasoneedit_DataObjectExtension::separator)) { | ||
// Also skip $name that starts with a separator | ||
continue; | ||
} | ||
$fieldList = $form->Fields(); | ||
|
||
foreach ($fieldList->dataFields() as $name => $field) { | ||
$name = HasOneEdit::normaliseSeparator($name); | ||
if (!HasOneEdit::isHasOneEditField($name)) continue; | ||
|
||
$field->setName($name); | ||
if(!$record) { | ||
continue; | ||
} | ||
if($field->Value()) { | ||
// Skip fields that already have a value | ||
continue; | ||
} | ||
list($hasone, $key) = explode(sgn_hasoneedit_DataObjectExtension::separator, $name, 2); | ||
if($record->has_one($hasone)) { | ||
$rel = $record->getComponent($hasone); | ||
// Copied from loadDataFrom() | ||
$exists = ( | ||
isset($rel->$key) || | ||
$rel->hasMethod($key) || | ||
($rel->hasMethod('hasField') && $rel->hasField($key)) | ||
); | ||
|
||
if($exists) { | ||
$value = $rel->__get($key); | ||
$field->setValue($value); | ||
} | ||
} | ||
|
||
if ($field instanceof UploadField) { | ||
$field = HasOneUploadField::create($field); | ||
$fieldList->replaceField($name, $field); | ||
} | ||
|
||
// Skip populating value if record doesn't exist yet, or field already has value | ||
if (!$record || $field->Value()) continue; | ||
|
||
list($relationName, $fieldOnRelation) = HasOneEdit::getRelationNameAndField($name); | ||
$relatedObject = HasOneEdit::getRelationRecord($record, $relationName); | ||
if ($relatedObject === null) continue; | ||
|
||
if ($field instanceof HasOneUploadField) { | ||
if ($relatedObject->hasField("{$fieldOnRelation}ID")) { | ||
$field->setValue([ 'Files' => [ $relatedObject->getField("{$fieldOnRelation}ID") ] ]); | ||
} | ||
|
||
} else { | ||
if ($relatedObject->hasField($fieldOnRelation)) { | ||
$field->setValue($relatedObject->getField($fieldOnRelation)); | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
public function updateItemEditForm(\Form $form) { | ||
$this->updateEditForm($form); | ||
} | ||
} |