Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions src/Model/Behavior/DuplicatableBehavior.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* - set: fields and their default value
* - prepend: fields and text to prepend
* - append: fields and text to append
* - keysToPreserve: only used in the case of composite keys. Provide any keys which the behavior should preserve and not unset
*/
class DuplicatableBehavior extends Behavior
{
Expand All @@ -35,14 +36,16 @@ class DuplicatableBehavior extends Behavior
'set' => [],
'prepend' => [],
'append' => [],
'saveOptions' => []
'saveOptions' => [],
'keysToPreserve' => []
];

/**
* Duplicate record.
*
* @param int|string $id Id of entity to duplicate.
* @return \Cake\Datasource\EntityInterface New entity or false on failure
* @throws \Exception
*/
public function duplicate($id)
{
Expand All @@ -54,6 +57,7 @@ public function duplicate($id)
*
* @param int|string $id Id of entity to duplicate.
* @return \Cake\Datasource\EntityInterface
* @throws \Exception
*/
public function duplicateEntity($id)
{
Expand Down Expand Up @@ -172,19 +176,22 @@ protected function _getContain()
* @param \Cake\Datasource\EntityInterface $entity Entity
* @param \Cake\ORM\Table|\Cake\ORM\Association $object Table or association instance.
* @return void
* @throws \Exception
*/
protected function _modifyEntity(EntityInterface $entity, $object)
{
// belongs to many is tricky
if ($object instanceof BelongsToMany) {
unset($entity->_joinData);
} else {

// unset primary key
unset($entity->{$object->getPrimaryKey()});
$this->removePrimaryKey($entity, $object);

// unset foreign key
if ($object instanceof Association) {
unset($entity->{$object->getPrimaryKey()});
// unset primary key
$this->removePrimaryKey($entity, $object);
}
}

Expand All @@ -206,6 +213,7 @@ protected function _modifyEntity(EntityInterface $entity, $object)
* @param \Cake\ORM\Table|\Cake\ORM\Association $object Table or association instance.
* @param array $parts Related properties chain.
* @return void
* @throws \Exception
*/
protected function _drillDownAssoc(EntityInterface $entity, $object, array $parts)
{
Expand Down Expand Up @@ -329,4 +337,36 @@ protected function _doAction($action, EntityInterface $entity, $prop, $value = n
break;
}
}

/**
* Removes the primary key from the entity being duplicated. If the entity has a composite key, you must
* specify which field(s) we wish to preserve
*
* @param EntityInterface $entity
* @param $object
* @throws \Exception
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return void missing maybe here?

*/
protected function removePrimaryKey(EntityInterface $entity, $object)
{
$primaryKey = $object->getPrimaryKey();

if (!is_array($primaryKey)) {
unset($entity->{$primaryKey});
return;
}

$keysToPreserve = $this->getConfig('keysToPreserve');

$commonKeys = array_intersect($keysToPreserve, $primaryKey);

if (empty($keysToPreserve) || empty($commonKeys)) {
throw new \Exception('You must specify which key to preserve when duplicating composite keys');
}

foreach ($primaryKey as $pkField) {
if (!in_array($pkField, $keysToPreserve)) {
unset($entity->{$pkField});
}
}
}
}