'Copy this plugin and return the new plugin.
The logic of this method is the following:
# get a new generic plugin instance
# assign the position in the plugin tree
# save it to let mptt/treebeard calculate the tree attributes
# then get a copy of the current plugin instance
# assign to it the id of the generic plugin instance above;
this will effectively change the generic plugin created above
into a concrete one
# copy the tree related attributes from the generic plugin to
the concrete one
# save the concrete plugin
# trigger the copy relations
# return the generic plugin instance
This copy logic is required because we don\'t know what the fields of
the real plugin are. By getting another instance of it at step 4 and
then overwriting its ID at step 5, the ORM will copy the custom
fields for us.'

def copy_plugin(self, target_placeholder, target_language, parent_cache, no_signals=False):

    try:
        (plugin_instance, cls) = self.get_plugin_instance()
    except KeyError:
        return
    new_plugin = CMSPlugin()
    new_plugin.placeholder = target_placeholder
    parent_cache[self.pk] = new_plugin
    if self.parent:
        parent = parent_cache[self.parent_id]
        parent = CMSPlugin.objects.get(pk=parent.pk)
        new_plugin.parent_id = parent.pk
        new_plugin.parent = parent
    new_plugin.language = target_language
    new_plugin.plugin_type = self.plugin_type
    if no_signals:
        from cms.signals import pre_save_plugins
        signals.pre_save.disconnect(pre_save_plugins, sender=CMSPlugin, dispatch_uid='cms_pre_save_plugin')
        signals.pre_save.disconnect(pre_save_plugins, sender=CMSPlugin)
        new_plugin._no_reorder = True
    new_plugin.save()
    if plugin_instance:
        plugin_instance = plugin_instance.__class__.objects.get(pk=plugin_instance.pk)
        plugin_instance.pk = new_plugin.pk
        plugin_instance.id = new_plugin.pk
        plugin_instance.placeholder = target_placeholder
        plugin_instance.cmsplugin_ptr = new_plugin
        plugin_instance.language = target_language
        plugin_instance.parent = new_plugin.parent
        plugin_instance.depth = new_plugin.depth
        plugin_instance.path = new_plugin.path
        plugin_instance.numchild = new_plugin.numchild
        plugin_instance._no_reorder = True
        plugin_instance.save()
        old_instance = plugin_instance.__class__.objects.get(pk=self.pk)
        plugin_instance.copy_relations(old_instance)
    if no_signals:
        signals.pre_save.connect(pre_save_plugins, sender=CMSPlugin, dispatch_uid='cms_pre_save_plugin')
    return new_plugin
