src/View/ActionHandler/CopyHandler.php
public function process(EnvironmentInterface $environment): void
    {
        $dispatcher      = $environment->getEventDispatcher();
        $definition      = $environment->getDataDefinition();
        $basicDefinition = $definition->getBasicDefinition();
        $currentUrl      = $this->requestStack->getCurrentRequest()->getUri();

        if (!$basicDefinition->isCreatable()) {
            throw new NotCreatableException('DataContainer ' . $definition->getName() . ' is not creatable');
        }
        // We only support flat tables, sorry.
        if (BasicDefinitionInterface::MODE_FLAT !== $basicDefinition->getMode()) {
            return;
        }
        $modelId = ModelId::fromSerialized($environment->getInputProvider()->getParameter('source'));

        $dataProvider = $environment->getDataProvider();
        $model        = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId()));
        $copyModel    = $environment->getController()->createClonedModel($model);

        // Dispatch pre duplicate event.
        $copyEvent = new PreDuplicateModelEvent($environment, $copyModel, $model);
        $dispatcher->dispatch($copyEvent::NAME, $copyEvent);

        // Save the copy.
        $provider = $environment->getDataProvider($copyModel->getProviderName());
        $provider->save($copyModel);

        // Dispatch post duplicate event.
        $copyEvent = new PostDuplicateModelEvent($environment, $copyModel, $model);
        $dispatcher->dispatch($copyEvent::NAME, $copyEvent);

        // Redirect to the edit mask of the cloned model
        throw new RedirectResponseException(
            UrlBuilder::fromUrl($currentUrl)
                ->setQueryParameter('act', 'edit')
                ->setQueryParameter('id', ModelId::fromModel($copyModel)->getSerialized())
                ->unsetQueryParameter('source')
                ->getUrl()
        );
    }
public function process(EnvironmentInterface $environment): void
    {
        $dispatcher      = $environment->getEventDispatcher();
        $definition      = $environment->getDataDefinition();
        $basicDefinition = $definition->getBasicDefinition();
        $currentUrl      = $this->requestStack->getCurrentRequest()->getUri();

        if (!$basicDefinition->isCreatable()) {
            throw new NotCreatableException('DataContainer ' . $definition->getName() . ' is not creatable');
        }
        // We only support flat tables, sorry.
        if (BasicDefinitionInterface::MODE_FLAT !== $basicDefinition->getMode()) {
            return;
        }
        $modelId = ModelId::fromSerialized($environment->getInputProvider()->getParameter('source'));

        $dataProvider = $environment->getDataProvider();
        $model        = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId()));
        $copyModel    = $environment->getController()->createClonedModel($model);

        // Dispatch pre duplicate event.
        $copyEvent = new PreDuplicateModelEvent($environment, $copyModel, $model);
        $dispatcher->dispatch($copyEvent::NAME, $copyEvent);

        // Save the copy.
        $provider = $environment->getDataProvider($copyModel->getProviderName());
        $provider->save($copyModel);

        // Dispatch post duplicate event.
        $copyEvent = new PostDuplicateModelEvent($environment, $copyModel, $model);
        $dispatcher->dispatch($copyEvent::NAME, $copyEvent);

        // Redirect to the edit mask of the cloned model
        throw new RedirectResponseException(
            UrlBuilder::fromUrl($currentUrl)
                ->setQueryParameter('act', 'edit')
                ->setQueryParameter('id', ModelId::fromModel($copyModel)->getSerialized())
                ->unsetQueryParameter('source')
                ->getUrl()
        );
    }
Handle the action.

@param EnvironmentInterface $environment The environment.

@return void

@throws RedirectResponseException To redirect to the edit mask with cloned model.
@throws NotCreatableException     When the DataContainer is not creatable.