/** * Returns a new duplicate copy of the entity */ public function duplicate($flushdb = true, &$translations = array(), &$entityMap = array(), $excludeFields = array()) { $metadata = $this->metadata(); $class = $metadata->getName(); $fieldNames = $metadata->getFieldNames(); $associationNames = $metadata->getAssociationNames(); $duplicate = new $class(); $isTree = $this->isTreeNode(); if ($class::_static()) { throw new \Exception($class::singular() . ' is a static type and cannot be duplicated'); } // Copy field names across foreach ($fieldNames as $fieldName) { if (in_array($fieldName, $excludeFields)) { continue; } $value = $this->get($fieldName); $duplicate->set($fieldName, $value); } // Copy associations across foreach ($associationNames as $associationName) { if (in_array($associationName, $excludeFields)) { continue; } $associationMapping = $metadata->getAssociationMapping($associationName); $value = $this->get($associationName); $shouldCopy = $associationMapping['orphanRemoval'] || $associationMapping['isCascadeRemove']; $isTreeChildren = $isTree && $associationName == 'children'; $targetPropName = $associationMapping['isOwningSide'] ? @$associationMapping['inversedBy'] : @$associationMapping['mappedBy']; if (!empty($value) && ($shouldCopy || $isTreeChildren)) { if ($metadata->isCollectionValuedAssociation($associationName)) { $duplicateCollection = array(); foreach ($value as $item) { $itemClass = $item->metadata()->name; if (!$itemClass::_static()) { $duplicateItem = $item->duplicate(false, $translations, $entityMap, array($targetPropName)); if (!empty($duplicateItem)) { $duplicateCollection[] = $duplicateItem; } } } $value = $duplicateCollection; } else { $itemClass = $value->metadata()->name; if (!$itemClass::_static()) { $value = $value->duplicate(false, $translations, $entityMap, array($targetPropName)); } else { $value = null; } } } $duplicate->set($associationName, $value); } if (!$flushdb) { \D::manager()->persist($duplicate); } // If languages are enabled, add its translations to the array reference using the new oid if ($this->id && \CMF::langEnabled()) { $oid = spl_object_hash($duplicate); $entityMap[$oid] = $duplicate; if (!isset($translations[$oid])) { $translations[$oid] = \DB::query("SELECT * FROM ext_translations WHERE object_class = '{$metadata->rootEntityName}' AND foreign_key = '{$this->id}'")->execute()->as_array(); } } if ($flushdb) { // Persist the item if ($isTree) { $class::repository()->persistAsNextSiblingOf($duplicate, $this); } else { \D::manager()->persist($duplicate); } $displayField = $this->findFieldUsedInDisplay(); if (!empty($displayField)) { $duplicate->setUniqueValueForField($displayField); } \D::manager()->flush(); // Add translations after all the entities have been committed to the db if (!empty($translations)) { foreach ($translations as $objectHash => $objectTranslations) { $entity = isset($entityMap[$objectHash]) ? $entityMap[$objectHash] : null; if (empty($entity) || empty($entity->id) || empty($objectTranslations)) { continue; } $cols = null; $qb = \DB::insert('ext_translations'); foreach ($objectTranslations as $translation) { unset($translation['id']); $translation['foreign_key'] = strval($entity->id); if (is_null($cols)) { $cols = array_keys($translation); $qb->columns($cols); } // Insert the new translations $qb->values($translation); } $qb->execute(); } } try { if (is_subclass_of($class, 'CMF\\Model\\Node')) { $repo = \D::manager()->getRepository($class); $repo->recover(); \D::manager()->flush(); } } catch (\Exception $e) { } } return $duplicate; }