diff --git a/Controller/ArticleController.php b/Controller/ArticleController.php
index 499e18db4..df2ced226 100644
--- a/Controller/ArticleController.php
+++ b/Controller/ArticleController.php
@@ -23,6 +23,7 @@
use ONGR\ElasticsearchDSL\Query\TermQuery;
use ONGR\ElasticsearchDSL\Sort\FieldSort;
use Sulu\Bundle\ArticleBundle\Admin\ArticleAdmin;
+use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
use Sulu\Bundle\ArticleBundle\Document\Form\ArticleDocumentType;
use Sulu\Bundle\ArticleBundle\Metadata\ArticleViewDocumentIdTrait;
use Sulu\Component\Content\Form\Exception\InvalidFormException;
@@ -342,6 +343,14 @@ public function postTriggerAction($uuid, Request $request)
$destLocales = $this->getRequestParameter($request, 'dest', true);
$data = $this->getMapper()->copyLanguage($uuid, $userId, null, $locale, explode(',', $destLocales));
break;
+ case 'copy':
+ /** @var ArticleDocument $document */
+ $document = $this->getDocumentManager()->find($uuid, $locale);
+ $copiedPath = $this->getDocumentManager()->copy($document, dirname($document->getPath()));
+ $this->getDocumentManager()->flush();
+
+ $data = $this->getDocumentManager()->find($copiedPath, $locale);
+ break;
default:
throw new RestException('Unrecognized action: ' . $action);
}
diff --git a/Document/ArticleDocument.php b/Document/ArticleDocument.php
index e69493dda..0fe9da26d 100644
--- a/Document/ArticleDocument.php
+++ b/Document/ArticleDocument.php
@@ -244,9 +244,7 @@ public function getRoute()
}
/**
- * Set route.
- *
- * @param RouteInterface $route
+ * {@inheritdoc}
*/
public function setRoute(RouteInterface $route)
{
@@ -254,6 +252,15 @@ public function setRoute(RouteInterface $route)
$this->routePath = $route->getPath();
}
+ /**
+ * {@inheritdoc}
+ */
+ public function removeRoute()
+ {
+ $this->route = null;
+ $this->routePath = null;
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/Document/Behavior/RoutableBehavior.php b/Document/Behavior/RoutableBehavior.php
index f86904c35..3fe990f94 100644
--- a/Document/Behavior/RoutableBehavior.php
+++ b/Document/Behavior/RoutableBehavior.php
@@ -27,6 +27,11 @@ interface RoutableBehavior extends RoutableInterface, UuidBehavior, LocaleBehavi
*/
public function getRoutePath();
+ /**
+ * Remove route.
+ */
+ public function removeRoute();
+
/**
* Set route-path.
*
diff --git a/Document/Subscriber/ArticleSubscriber.php b/Document/Subscriber/ArticleSubscriber.php
index 2ae4e135d..f96b753a6 100644
--- a/Document/Subscriber/ArticleSubscriber.php
+++ b/Document/Subscriber/ArticleSubscriber.php
@@ -15,6 +15,7 @@
use Sulu\Bundle\ArticleBundle\Document\Index\IndexerInterface;
use Sulu\Component\DocumentManager\DocumentManagerInterface;
use Sulu\Component\DocumentManager\Event\AbstractMappingEvent;
+use Sulu\Component\DocumentManager\Event\CopyEvent;
use Sulu\Component\DocumentManager\Event\FlushEvent;
use Sulu\Component\DocumentManager\Event\RemoveEvent;
use Sulu\Component\DocumentManager\Event\UnpublishEvent;
@@ -78,6 +79,7 @@ public static function getSubscribedEvents()
Events::UNPUBLISH => 'handleUnpublish',
Events::REMOVE_DRAFT => ['handleScheduleIndex', -1024],
Events::FLUSH => [['handleFlush', -2048], ['handleFlushLive', -2048]],
+ Events::COPY => ['handleCopy'],
];
}
@@ -228,4 +230,23 @@ public function handleRemoveLive($event)
$this->liveIndexer->remove($document);
$this->liveIndexer->flush();
}
+
+ /**
+ * Schedule document to index.
+ *
+ * @param CopyEvent $event
+ */
+ public function handleCopy(CopyEvent $event)
+ {
+ $document = $event->getDocument();
+ if (!$document instanceof ArticleDocument) {
+ return;
+ }
+
+ $uuid = $event->getCopiedNode()->getIdentifier();
+ $this->documents[$uuid] = [
+ 'uuid' => $uuid,
+ 'locale' => $document->getLocale(),
+ ];
+ }
}
diff --git a/Document/Subscriber/RoutableSubscriber.php b/Document/Subscriber/RoutableSubscriber.php
index be460b429..837bfa126 100644
--- a/Document/Subscriber/RoutableSubscriber.php
+++ b/Document/Subscriber/RoutableSubscriber.php
@@ -12,11 +12,16 @@
namespace Sulu\Bundle\ArticleBundle\Document\Subscriber;
use Doctrine\ORM\EntityManagerInterface;
+use Sulu\Bundle\ArticleBundle\Document\ArticleDocument;
use Sulu\Bundle\ArticleBundle\Document\Behavior\RoutableBehavior;
+use Sulu\Bundle\DocumentManagerBundle\Bridge\DocumentInspector;
+use Sulu\Bundle\DocumentManagerBundle\Bridge\PropertyEncoder;
use Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface;
use Sulu\Bundle\RouteBundle\Manager\RouteManagerInterface;
+use Sulu\Component\DocumentManager\DocumentManagerInterface;
use Sulu\Component\DocumentManager\Event\AbstractMappingEvent;
use Sulu\Component\DocumentManager\Event\ConfigureOptionsEvent;
+use Sulu\Component\DocumentManager\Event\CopyEvent;
use Sulu\Component\DocumentManager\Event\MetadataLoadEvent;
use Sulu\Component\DocumentManager\Event\RemoveEvent;
use Sulu\Component\DocumentManager\Events;
@@ -27,6 +32,8 @@
*/
class RoutableSubscriber implements EventSubscriberInterface
{
+ const ROUTE_FIELD = 'routePath';
+
/**
* @var RouteManagerInterface
*/
@@ -42,16 +49,43 @@ class RoutableSubscriber implements EventSubscriberInterface
*/
private $entityManager;
+ /**
+ * @var DocumentManagerInterface
+ */
+ private $documentManager;
+
+ /**
+ * @var DocumentInspector
+ */
+ private $documentInspector;
+
+ /**
+ * @var PropertyEncoder
+ */
+ private $propertyEncoder;
+
/**
* @param RouteManagerInterface $routeManager
* @param RouteRepositoryInterface $routeRepository
* @param EntityManagerInterface $entityManager
+ * @param DocumentManagerInterface $documentManager
+ * @param DocumentInspector $documentInspector
+ * @param PropertyEncoder $propertyEncoder
*/
- public function __construct(RouteManagerInterface $routeManager, RouteRepositoryInterface $routeRepository, EntityManagerInterface $entityManager)
- {
+ public function __construct(
+ RouteManagerInterface $routeManager,
+ RouteRepositoryInterface $routeRepository,
+ EntityManagerInterface $entityManager,
+ DocumentManagerInterface $documentManager,
+ DocumentInspector $documentInspector,
+ PropertyEncoder $propertyEncoder
+ ) {
$this->routeManager = $routeManager;
$this->routeRepository = $routeRepository;
$this->entityManager = $entityManager;
+ $this->documentManager = $documentManager;
+ $this->documentInspector = $documentInspector;
+ $this->propertyEncoder = $propertyEncoder;
}
/**
@@ -63,6 +97,7 @@ public static function getSubscribedEvents()
Events::HYDRATE => [['handleHydrate', -500]],
Events::PERSIST => [['handleRouteUpdate', 1], ['handleRoute', 0]],
Events::REMOVE => [['handleRemove', -500]],
+ Events::COPY => ['handleCopy', -2000],
Events::METADATA_LOAD => 'handleMetadataLoad',
Events::CONFIGURE_OPTIONS => 'configureOptions',
];
@@ -149,6 +184,37 @@ public function handleRemove(RemoveEvent $event)
$this->entityManager->flush();
}
+ /**
+ * Update routes for copied article.
+ *
+ * @param CopyEvent $event
+ */
+ public function handleCopy(CopyEvent $event)
+ {
+ $document = $event->getDocument();
+ if (!$document instanceof RoutableBehavior) {
+ return;
+ }
+
+ $locales = $this->documentInspector->getLocales($document);
+ foreach ($locales as $locale) {
+ /** @var ArticleDocument $localizedDocument */
+ $localizedDocument = $this->documentManager->find($event->getCopiedPath(), $locale);
+
+ $localizedDocument->removeRoute();
+ $route = $this->routeManager->create($localizedDocument);
+ $document->setRoutePath($route->getPath());
+ $this->entityManager->persist($route);
+
+ $event->getCopiedNode()->setProperty(
+ $this->propertyEncoder->localizedSystemName(self::ROUTE_FIELD, $locale),
+ $route->getPath()
+ );
+ }
+
+ $this->entityManager->flush();
+ }
+
/**
* Add route to metadata.
*
@@ -162,10 +228,10 @@ public function handleMetadataLoad(MetadataLoadEvent $event)
$metadata = $event->getMetadata();
$metadata->addFieldMapping(
- 'routePath',
+ self::ROUTE_FIELD,
[
'encoding' => 'system_localized',
- 'property' => 'routePath',
+ 'property' => self::ROUTE_FIELD,
]
);
}
diff --git a/Resources/config/services.xml b/Resources/config/services.xml
index 868f53258..ee95de05b 100644
--- a/Resources/config/services.xml
+++ b/Resources/config/services.xml
@@ -110,6 +110,9 @@
+
+
+
diff --git a/Resources/public/dist/components/articles/edit/main.js b/Resources/public/dist/components/articles/edit/main.js
index b255cfb2a..542a6150e 100644
--- a/Resources/public/dist/components/articles/edit/main.js
+++ b/Resources/public/dist/components/articles/edit/main.js
@@ -1 +1 @@
-define(["jquery","underscore","config","services/suluarticle/article-manager","sulusecurity/services/user-manager","services/sulupreview/preview","sulusecurity/services/security-checker","sulucontent/components/copy-locale-overlay/main","sulucontent/components/open-ghost-overlay/main"],function(a,b,c,d,e,f,g,h,i){"use strict";return{defaults:{options:{config:{}},templates:{url:"/admin/api/articles<% if (!!id) { %>/<%= id %><% } %>?locale=<%= locale %>"},translations:{headline:"sulu_article.edit.title",draftLabel:"sulu-document-manager.draft-label",removeDraft:"sulu-content.delete-draft",unpublish:"sulu-document-manager.unpublish",unpublishConfirmTextNoDraft:"sulu-content.unpublish-confirm-text-no-draft",unpublishConfirmTextWithDraft:"sulu-content.unpublish-confirm-text-with-draft",unpublishConfirmTitle:"sulu-content.unpublish-confirm-title",deleteDraftConfirmTitle:"sulu-content.delete-draft-confirm-title",deleteDraftConfirmText:"sulu-content.delete-draft-confirm-text",openGhostOverlay:{info:"sulu_article.settings.open-ghost-overlay.info","new":"sulu_article.settings.open-ghost-overlay.new",copy:"sulu_article.settings.open-ghost-overlay.copy",ok:"sulu_article.settings.open-ghost-overlay.ok"},copyLocaleOverlay:{info:"sulu_article.settings.copy-locale-overlay.info"}}},layout:function(){return{navigation:{collapsed:!0},content:{shrinkable:!!this.options.id},sidebar:!!this.options.id&&"max"}},header:function(){var a={},d={},e={};return g.hasPermission(this.data,"edit")&&(e.saveDraft={},g.hasPermission(this.data,"live")&&(e.savePublish={},e.publish={}),c.has("sulu_automation.enabled")&&(e.automationInfo={options:{entityId:this.options.id,entityClass:"Sulu\\Bundle\\ArticleBundle\\Document\\ArticleDocument",handlerClass:["Sulu\\Bundle\\ContentBundle\\Automation\\DocumentPublishHandler","Sulu\\Bundle\\ContentBundle\\Automation\\DocumentUnpublishHandler"]}}),a.save={parent:"saveWithDraft",options:{callback:function(){this.sandbox.emit("sulu.toolbar.save","publish")}.bind(this),dropdownItems:e}},a.template={options:{dropdownOptions:{url:"/admin/articles/templates?type="+(this.options.type||this.data.articleType),callback:function(a){this.template=a.template,this.sandbox.emit("sulu.tab.template-change",a)}.bind(this)}}}),g.hasPermission(this.data,"live")&&(d.unpublish={options:{title:this.translations.unpublish,disabled:!this.data.published,callback:this.unpublish.bind(this)}},d.divider={options:{divider:!0}}),g.hasPermission(this.data,"delete")&&(d["delete"]={options:{disabled:!this.options.id,callback:this.deleteArticle.bind(this)}}),d.copyLocale={options:{title:this.sandbox.translate("toolbar.copy-locale"),callback:function(){h.startCopyLocalesOverlay.call(this,this.translations.copyLocaleOverlay).then(function(a){return b.contains(a,this.options.locale)?void this.toEdit(this.options.locale):(this.data.concreteLanguages=b.uniq(this.data.concreteLanguages.concat(a)),void this.sandbox.emit("sulu.labels.success.show","labels.success.copy-locale-desc","labels.success"))}.bind(this))}.bind(this)}},this.sandbox.util.isEmpty(d)||(a.edit={options:{dropdownItems:d}}),a.statePublished={},a.stateTest={},{tabs:{url:"/admin/content-navigations?alias=article&id="+this.options.id+"&locale="+this.options.locale,options:{data:function(){return this.sandbox.util.deepCopy(this.data)}.bind(this),url:function(){return this.templates.url({id:this.options.id,locale:this.options.locale})}.bind(this),config:this.options.config,preview:this.preview},componentOptions:{values:b.defaults(this.data,{type:null})}},toolbar:{buttons:a,languageChanger:{data:this.options.config.languageChanger,preSelected:this.options.locale}}}},initialize:function(){this.bindCustomEvents(),this.showDraftLabel(),this.setHeaderBar(!0),this.loadLocalizations(),this.options.language=this.options.locale},bindCustomEvents:function(){this.sandbox.on("sulu.header.back",this.toList.bind(this)),this.sandbox.on("sulu.tab.dirty",this.setHeaderBar.bind(this)),this.sandbox.on("sulu.toolbar.save",this.save.bind(this)),this.sandbox.on("sulu.tab.data-changed",this.setData.bind(this)),this.sandbox.on("sulu.article.error",this.handleError.bind(this)),this.sandbox.on("husky.tabs.header.item.select",this.tabChanged.bind(this)),this.sandbox.on("sulu.header.language-changed",this.languageChanged.bind(this))},languageChanged:function(a){a.id!==this.options.locale&&(this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),-1===b(this.data.concreteLanguages).indexOf(a.id)?i.openGhost.call(this,this.data,this.translations.openGhostOverlay).then(function(b,c){b?h.copyLocale.call(this,this.data.id,c,[a.id],function(){this.toEdit(a.id)}.bind(this)):this.toEdit(a.id)}.bind(this)).fail(function(){this.sandbox.emit("sulu.header.change-language",this.options.language)}.bind(this)):this.toEdit(a.id))},tabChanged:function(a){this.options.content=a.id},handleError:function(a,b,c){switch(a){default:this.sandbox.emit("sulu.labels.error.show","labels.error.content-save-desc","labels.error"),this.sandbox.emit("sulu.header.toolbar.item.enable","save")}},deleteArticle:function(){this.sandbox.sulu.showDeleteDialog(function(a){a&&d.remove(this.options.id,this.options.locale).then(function(){this.toList()}.bind(this))}.bind(this))},toEdit:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(a||this.options.locale)+"/edit:"+(b||this.options.id)+"/"+(this.options.content||"details"),!0,!0)},toList:function(){1===this.options.config.typeNames.length?this.sandbox.emit("sulu.router.navigate","articles/"+this.options.locale):this.sandbox.emit("sulu.router.navigate","articles:"+(this.options.type||this.data.articleType)+"/"+this.options.locale)},toAdd:function(){1===this.options.config.typeNames.length?this.sandbox.emit("sulu.router.navigate","articles/"+this.options.locale+"/add",!0,!0):this.sandbox.emit("sulu.router.navigate","articles/"+this.options.locale+"/add:"+(this.options.type||this.data.articleType),!0,!0)},save:function(a){this.loadingSave(),this.saveTab(a).then(function(b){this.saved(b.id,b,a)}.bind(this))},setData:function(a){this.data=a},saveTab:function(c){var d=a.Deferred();return this.sandbox.emit("sulu.header.toolbar.item.loading","save"),this.sandbox.once("sulu.tab.saved",function(a,c){d.resolve(b.defaults(c,{type:null}))}.bind(this)),this.sandbox.emit("sulu.tab.save",c),d},setHeaderBar:function(a){var b=!a,c=!a,d=!!a&&!this.data.publishedState;this.setSaveToolbarItems.call(this,"saveDraft",b),this.setSaveToolbarItems.call(this,"savePublish",c),this.setSaveToolbarItems.call(this,"publish",d),this.setSaveToolbarItems.call(this,"unpublish",!!this.data.published),b||c||d?this.sandbox.emit("sulu.header.toolbar.item.enable","save",!1):this.sandbox.emit("sulu.header.toolbar.item.disable","save",!1),this.showState(!!this.data.published)},setSaveToolbarItems:function(a,b){this.sandbox.emit("sulu.header.toolbar.item."+(b?"enable":"disable"),a,!1)},loadingSave:function(){this.sandbox.emit("sulu.header.toolbar.item.loading","save")},afterSaveAction:function(a,b){"back"===a?this.toList():"new"===a?this.toAdd():b&&this.toEdit(this.options.locale,this.data.id)},showDraftLabel:function(){this.sandbox.emit("sulu.header.tabs.label.hide"),this.hasDraft(this.data)||e.find(this.data.changer).then(function(a){this.sandbox.emit("sulu.header.tabs.label.show",this.sandbox.util.sprintf(this.translations.draftLabel,{changed:this.sandbox.date.format(this.data.changed,!0),user:a.username}),[{id:"delete-draft",title:this.translations.removeDraft,skin:"critical",onClick:this.deleteDraft.bind(this)}])}.bind(this))},deleteDraft:function(){this.sandbox.sulu.showDeleteDialog(function(a){a&&(this.sandbox.emit("husky.label.header.loading"),d.removeDraft(this.data.id,this.options.locale).always(function(){this.sandbox.emit("sulu.header.toolbar.item.enable","edit")}.bind(this)).then(function(a){this.sandbox.emit("sulu.router.navigate",this.sandbox.mvc.history.fragment,!0,!0),this.saved(a.id,a)}.bind(this)).fail(function(){this.sandbox.emit("husky.label.header.reset"),this.sandbox.emit("sulu.labels.error.show","labels.error.remove-draft-desc","labels.error")}.bind(this)))}.bind(this),this.translations.deleteDraftConfirmTitle,this.translations.deleteDraftConfirmText)},hasDraft:function(a){return!a.id||!!a.publishedState||!a.published},getUrl:function(a){var c=b.template(this.defaults.templates.url,{id:this.options.id,locale:this.options.locale});return a&&(c+="&action="+a),c},loadComponentData:function(){var b=a.Deferred();return this.options.id?(this.sandbox.util.load(this.getUrl()).done(function(a){this.preview=f.initialize({}),this.preview.start("Sulu\\Bundle\\ArticleBundle\\Document\\ArticleDocument",this.options.id,this.options.locale,a),b.resolve(a)}.bind(this)),b):(b.resolve({}),b)},destroy:function(){this.preview&&f.destroy(this.preview)},showState:function(a){a?(this.sandbox.emit("sulu.header.toolbar.item.hide","stateTest"),this.sandbox.emit("sulu.header.toolbar.item.show","statePublished")):(this.sandbox.emit("sulu.header.toolbar.item.hide","statePublished"),this.sandbox.emit("sulu.header.toolbar.item.show","stateTest"))},unpublish:function(){this.sandbox.sulu.showConfirmationDialog({callback:function(a){a&&(this.sandbox.emit("sulu.header.toolbar.item.loading","edit"),d.unpublish(this.data.id,this.options.locale).always(function(){this.sandbox.emit("sulu.header.toolbar.item.enable","edit")}.bind(this)).then(function(a){this.sandbox.emit("sulu.labels.success.show","labels.success.content-unpublish-desc","labels.success"),this.saved(a.id,a)}.bind(this)).fail(function(){this.sandbox.emit("sulu.labels.error.show","labels.error.content-unpublish-desc","labels.error")}.bind(this)))}.bind(this),title:this.translations.unpublishConfirmTitle,description:this.hasDraft(this.data)?this.translations.unpublishConfirmTextNoDraft:this.translations.unpublishConfirmTextWithDraft})},saved:function(a,b,c){this.setData(b),this.options.id?(this.setHeaderBar(!0),this.showDraftLabel(),this.sandbox.emit("sulu.header.saved",b),this.sandbox.emit("sulu.labels.success.show","labels.success.content-save-desc","labels.success")):this.sandbox.sulu.viewStates.justSaved=!0,this.afterSaveAction(c,!this.options.id)},loadLocalizations:function(){this.sandbox.util.load("/admin/api/localizations").then(function(a){this.localizations=a._embedded.localizations.map(function(a){return{id:a.localization,title:a.localization}})}.bind(this))},getCopyLocaleUrl:function(a,b,c){return d.getCopyLocaleUrl(a,b,c)}}});
\ No newline at end of file
+define(["jquery","underscore","config","services/suluarticle/article-manager","sulusecurity/services/user-manager","services/sulupreview/preview","sulusecurity/services/security-checker","sulucontent/components/copy-locale-overlay/main","sulucontent/components/open-ghost-overlay/main"],function(a,b,c,d,e,f,g,h,i){"use strict";return{defaults:{options:{config:{}},templates:{url:"/admin/api/articles<% if (!!id) { %>/<%= id %><% } %>?locale=<%= locale %>"},translations:{headline:"sulu_article.edit.title",draftLabel:"sulu-document-manager.draft-label",removeDraft:"sulu-content.delete-draft",unpublish:"sulu-document-manager.unpublish",unpublishConfirmTextNoDraft:"sulu-content.unpublish-confirm-text-no-draft",unpublishConfirmTextWithDraft:"sulu-content.unpublish-confirm-text-with-draft",unpublishConfirmTitle:"sulu-content.unpublish-confirm-title",deleteDraftConfirmTitle:"sulu-content.delete-draft-confirm-title",deleteDraftConfirmText:"sulu-content.delete-draft-confirm-text",copy:"sulu_article.edit.copy",openGhostOverlay:{info:"sulu_article.settings.open-ghost-overlay.info","new":"sulu_article.settings.open-ghost-overlay.new",copy:"sulu_article.settings.open-ghost-overlay.copy",ok:"sulu_article.settings.open-ghost-overlay.ok"},copyLocaleOverlay:{info:"sulu_article.settings.copy-locale-overlay.info"}}},layout:function(){return{navigation:{collapsed:!0},content:{shrinkable:!!this.options.id},sidebar:!!this.options.id&&"max"}},header:function(){var a={},d={},e={};return g.hasPermission(this.data,"edit")&&(e.saveDraft={},g.hasPermission(this.data,"live")&&(e.savePublish={},e.publish={}),c.has("sulu_automation.enabled")&&(e.automationInfo={options:{entityId:this.options.id,entityClass:"Sulu\\Bundle\\ArticleBundle\\Document\\ArticleDocument",handlerClass:["Sulu\\Bundle\\ContentBundle\\Automation\\DocumentPublishHandler","Sulu\\Bundle\\ContentBundle\\Automation\\DocumentUnpublishHandler"]}}),a.save={parent:"saveWithDraft",options:{callback:function(){this.sandbox.emit("sulu.toolbar.save","publish")}.bind(this),dropdownItems:e}},a.template={options:{dropdownOptions:{url:"/admin/articles/templates?type="+(this.options.type||this.data.articleType),callback:function(a){this.template=a.template,this.sandbox.emit("sulu.tab.template-change",a)}.bind(this)}}}),g.hasPermission(this.data,"live")&&(d.unpublish={options:{title:this.translations.unpublish,disabled:!this.data.published,callback:this.unpublish.bind(this)}},d.divider={options:{divider:!0}}),g.hasPermission(this.data,"delete")&&(d["delete"]={options:{disabled:!this.options.id,callback:this.deleteArticle.bind(this)}}),d.copyLocale={options:{title:this.sandbox.translate("toolbar.copy-locale"),callback:function(){h.startCopyLocalesOverlay.call(this,this.translations.copyLocaleOverlay).then(function(a){return b.contains(a,this.options.locale)?void this.toEdit(this.options.locale):(this.data.concreteLanguages=b.uniq(this.data.concreteLanguages.concat(a)),void this.sandbox.emit("sulu.labels.success.show","labels.success.copy-locale-desc","labels.success"))}.bind(this))}.bind(this)}},g.hasPermission(this.data,"edit")&&(d.copy={options:{title:this.translations.copy,callback:this.copy.bind(this)}}),this.sandbox.util.isEmpty(d)||(a.edit={options:{dropdownItems:d}}),a.statePublished={},a.stateTest={},{tabs:{url:"/admin/content-navigations?alias=article&id="+this.options.id+"&locale="+this.options.locale,options:{data:function(){return this.sandbox.util.deepCopy(this.data)}.bind(this),url:function(){return this.templates.url({id:this.options.id,locale:this.options.locale})}.bind(this),config:this.options.config,preview:this.preview},componentOptions:{values:b.defaults(this.data,{type:null})}},toolbar:{buttons:a,languageChanger:{data:this.options.config.languageChanger,preSelected:this.options.locale}}}},initialize:function(){this.bindCustomEvents(),this.showDraftLabel(),this.setHeaderBar(!0),this.loadLocalizations(),this.options.language=this.options.locale},bindCustomEvents:function(){this.sandbox.on("sulu.header.back",this.toList.bind(this)),this.sandbox.on("sulu.tab.dirty",this.setHeaderBar.bind(this)),this.sandbox.on("sulu.toolbar.save",this.save.bind(this)),this.sandbox.on("sulu.tab.data-changed",this.setData.bind(this)),this.sandbox.on("sulu.article.error",this.handleError.bind(this)),this.sandbox.on("husky.tabs.header.item.select",this.tabChanged.bind(this)),this.sandbox.on("sulu.header.language-changed",this.languageChanged.bind(this))},languageChanged:function(a){a.id!==this.options.locale&&(this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),-1===b(this.data.concreteLanguages).indexOf(a.id)?i.openGhost.call(this,this.data,this.translations.openGhostOverlay).then(function(b,c){b?h.copyLocale.call(this,this.data.id,c,[a.id],function(){this.toEdit(a.id)}.bind(this)):this.toEdit(a.id)}.bind(this)).fail(function(){this.sandbox.emit("sulu.header.change-language",this.options.language)}.bind(this)):this.toEdit(a.id))},tabChanged:function(a){this.options.content=a.id},handleError:function(a,b,c){switch(a){default:this.sandbox.emit("sulu.labels.error.show","labels.error.content-save-desc","labels.error"),this.sandbox.emit("sulu.header.toolbar.item.enable","save")}},deleteArticle:function(){this.sandbox.sulu.showDeleteDialog(function(a){a&&d.remove(this.options.id,this.options.locale).then(function(){this.toList()}.bind(this))}.bind(this))},toEdit:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(a||this.options.locale)+"/edit:"+(b||this.options.id)+"/"+(this.options.content||"details"),!0,!0)},toList:function(){1===this.options.config.typeNames.length?this.sandbox.emit("sulu.router.navigate","articles/"+this.options.locale):this.sandbox.emit("sulu.router.navigate","articles:"+(this.options.type||this.data.articleType)+"/"+this.options.locale)},toAdd:function(){1===this.options.config.typeNames.length?this.sandbox.emit("sulu.router.navigate","articles/"+this.options.locale+"/add",!0,!0):this.sandbox.emit("sulu.router.navigate","articles/"+this.options.locale+"/add:"+(this.options.type||this.data.articleType),!0,!0)},save:function(a){this.loadingSave(),this.saveTab(a).then(function(b){this.saved(b.id,b,a)}.bind(this))},setData:function(a){this.data=a},saveTab:function(c){var d=a.Deferred();return this.sandbox.emit("sulu.header.toolbar.item.loading","save"),this.sandbox.once("sulu.tab.saved",function(a,c){d.resolve(b.defaults(c,{type:null}))}.bind(this)),this.sandbox.emit("sulu.tab.save",c),d},setHeaderBar:function(a){var b=!a,c=!a,d=!!a&&!this.data.publishedState;this.setSaveToolbarItems.call(this,"saveDraft",b),this.setSaveToolbarItems.call(this,"savePublish",c),this.setSaveToolbarItems.call(this,"publish",d),this.setSaveToolbarItems.call(this,"unpublish",!!this.data.published),b||c||d?this.sandbox.emit("sulu.header.toolbar.item.enable","save",!1):this.sandbox.emit("sulu.header.toolbar.item.disable","save",!1),this.showState(!!this.data.published)},setSaveToolbarItems:function(a,b){this.sandbox.emit("sulu.header.toolbar.item."+(b?"enable":"disable"),a,!1)},loadingSave:function(){this.sandbox.emit("sulu.header.toolbar.item.loading","save")},afterSaveAction:function(a,b){"back"===a?this.toList():"new"===a?this.toAdd():b&&this.toEdit(this.options.locale,this.data.id)},showDraftLabel:function(){this.sandbox.emit("sulu.header.tabs.label.hide"),this.hasDraft(this.data)||e.find(this.data.changer).then(function(a){this.sandbox.emit("sulu.header.tabs.label.show",this.sandbox.util.sprintf(this.translations.draftLabel,{changed:this.sandbox.date.format(this.data.changed,!0),user:a.username}),[{id:"delete-draft",title:this.translations.removeDraft,skin:"critical",onClick:this.deleteDraft.bind(this)}])}.bind(this))},deleteDraft:function(){this.sandbox.sulu.showDeleteDialog(function(a){a&&(this.sandbox.emit("husky.label.header.loading"),d.removeDraft(this.data.id,this.options.locale).always(function(){this.sandbox.emit("sulu.header.toolbar.item.enable","edit")}.bind(this)).then(function(a){this.sandbox.emit("sulu.router.navigate",this.sandbox.mvc.history.fragment,!0,!0),this.saved(a.id,a)}.bind(this)).fail(function(){this.sandbox.emit("husky.label.header.reset"),this.sandbox.emit("sulu.labels.error.show","labels.error.remove-draft-desc","labels.error")}.bind(this)))}.bind(this),this.translations.deleteDraftConfirmTitle,this.translations.deleteDraftConfirmText)},hasDraft:function(a){return!a.id||!!a.publishedState||!a.published},getUrl:function(a){var c=b.template(this.defaults.templates.url,{id:this.options.id,locale:this.options.locale});return a&&(c+="&action="+a),c},loadComponentData:function(){var b=a.Deferred();return this.options.id?(this.sandbox.util.load(this.getUrl()).done(function(a){this.preview=f.initialize({}),this.preview.start("Sulu\\Bundle\\ArticleBundle\\Document\\ArticleDocument",this.options.id,this.options.locale,a),b.resolve(a)}.bind(this)),b):(b.resolve({}),b)},destroy:function(){this.preview&&f.destroy(this.preview)},showState:function(a){a?(this.sandbox.emit("sulu.header.toolbar.item.hide","stateTest"),this.sandbox.emit("sulu.header.toolbar.item.show","statePublished")):(this.sandbox.emit("sulu.header.toolbar.item.hide","statePublished"),this.sandbox.emit("sulu.header.toolbar.item.show","stateTest"))},unpublish:function(){this.sandbox.sulu.showConfirmationDialog({callback:function(a){a&&(this.sandbox.emit("sulu.header.toolbar.item.loading","edit"),d.unpublish(this.data.id,this.options.locale).always(function(){this.sandbox.emit("sulu.header.toolbar.item.enable","edit")}.bind(this)).then(function(a){this.sandbox.emit("sulu.labels.success.show","labels.success.content-unpublish-desc","labels.success"),this.saved(a.id,a)}.bind(this)).fail(function(){this.sandbox.emit("sulu.labels.error.show","labels.error.content-unpublish-desc","labels.error")}.bind(this)))}.bind(this),title:this.translations.unpublishConfirmTitle,description:this.hasDraft(this.data)?this.translations.unpublishConfirmTextNoDraft:this.translations.unpublishConfirmTextWithDraft})},copy:function(){d.copy(this.data.id,this.options.locale).done(function(a){this.toEdit(this.options.locale,a.id)}.bind(this))},saved:function(a,b,c){this.setData(b),this.options.id?(this.setHeaderBar(!0),this.showDraftLabel(),this.sandbox.emit("sulu.header.saved",b),this.sandbox.emit("sulu.labels.success.show","labels.success.content-save-desc","labels.success")):this.sandbox.sulu.viewStates.justSaved=!0,this.afterSaveAction(c,!this.options.id)},loadLocalizations:function(){this.sandbox.util.load("/admin/api/localizations").then(function(a){this.localizations=a._embedded.localizations.map(function(a){return{id:a.localization,title:a.localization}})}.bind(this))},getCopyLocaleUrl:function(a,b,c){return d.getCopyLocaleUrl(a,b,c)}}});
\ No newline at end of file
diff --git a/Resources/public/dist/services/manager.js b/Resources/public/dist/services/manager.js
index 87d3fd2d7..05617b9a5 100644
--- a/Resources/public/dist/services/manager.js
+++ b/Resources/public/dist/services/manager.js
@@ -1 +1 @@
-define(["jquery","services/husky/util"],function(a,b){"use strict";var c={url:_.template('/admin/api/articles<% if (typeof id !== "undefined") { %>/<%= id %><% } %><% if (typeof postfix !== "undefined") { %>/<%= postfix %><% } %><% if (typeof version !== "undefined") { %>/<%= version %><% } %>?locale=<%= locale %><% if (typeof action !== "undefined") { %>&action=<%= action %><% } %><% if (typeof ids !== "undefined") { %>&ids=<%= ids.join(",") %><% } %>')};return{url:c.url,load:function(a,d){return b.load(c.url({id:a,locale:d}))},save:function(a,d,e,f){return b.save(c.url({id:d,locale:e,action:f}),d?"PUT":"POST",a)},remove:function(a,d){return"string"==typeof a?b.save(c.url({id:a,locale:d}),"DELETE"):b.save(c.url({ids:a,locale:d}),"DELETE")},unpublish:function(a,d){return b.save(c.url({id:a,locale:d,action:"unpublish"}),"POST")},removeDraft:function(a,d){return b.save(c.url({id:a,locale:d,action:"remove-draft"}),"POST")},restoreVersion:function(a,d,e){return b.save(c.url({id:a,postfix:"versions",locale:e,version:d,action:"restore"}),"POST")},getCopyLocaleUrl:function(a,b,d){return[c.url({id:a,locale:b,action:"copy-locale"}),"&dest=",d].join("")},getVersionsUrl:function(a,b){return c.url({id:a,postfix:"versions",locale:b})}}});
\ No newline at end of file
+define(["jquery","services/husky/util"],function(a,b){"use strict";var c={url:_.template('/admin/api/articles<% if (typeof id !== "undefined") { %>/<%= id %><% } %><% if (typeof postfix !== "undefined") { %>/<%= postfix %><% } %><% if (typeof version !== "undefined") { %>/<%= version %><% } %>?locale=<%= locale %><% if (typeof action !== "undefined") { %>&action=<%= action %><% } %><% if (typeof ids !== "undefined") { %>&ids=<%= ids.join(",") %><% } %>')};return{url:c.url,load:function(a,d){return b.load(c.url({id:a,locale:d}))},save:function(a,d,e,f){return b.save(c.url({id:d,locale:e,action:f}),d?"PUT":"POST",a)},remove:function(a,d){return"string"==typeof a?b.save(c.url({id:a,locale:d}),"DELETE"):b.save(c.url({ids:a,locale:d}),"DELETE")},unpublish:function(a,d){return b.save(c.url({id:a,locale:d,action:"unpublish"}),"POST")},removeDraft:function(a,d){return b.save(c.url({id:a,locale:d,action:"remove-draft"}),"POST")},restoreVersion:function(a,d,e){return b.save(c.url({id:a,postfix:"versions",locale:e,version:d,action:"restore"}),"POST")},copy:function(a,d){return b.save(c.url({id:a,locale:d,action:"copy"}),"POST")},getCopyLocaleUrl:function(a,b,d){return[c.url({id:a,locale:b,action:"copy-locale"}),"&dest=",d].join("")},getVersionsUrl:function(a,b){return c.url({id:a,postfix:"versions",locale:b})}}});
\ No newline at end of file
diff --git a/Resources/public/js/components/articles/edit/main.js b/Resources/public/js/components/articles/edit/main.js
index c3390c21a..156c6303f 100644
--- a/Resources/public/js/components/articles/edit/main.js
+++ b/Resources/public/js/components/articles/edit/main.js
@@ -42,6 +42,7 @@ define([
unpublishConfirmTitle: 'sulu-content.unpublish-confirm-title',
deleteDraftConfirmTitle: 'sulu-content.delete-draft-confirm-title',
deleteDraftConfirmText: 'sulu-content.delete-draft-confirm-text',
+ copy: 'sulu_article.edit.copy',
openGhostOverlay: {
info: 'sulu_article.settings.open-ghost-overlay.info',
new: 'sulu_article.settings.open-ghost-overlay.new',
@@ -161,6 +162,16 @@ define([
}
};
+ if (SecurityChecker.hasPermission(this.data, 'edit')) {
+ editDropdown.copy = {
+ options: {
+ title: this.translations.copy,
+ callback: this.copy.bind(this)
+ }
+ };
+ }
+
+
if (!this.sandbox.util.isEmpty(editDropdown)) {
buttons.edit = {
options: {
@@ -534,6 +545,12 @@ define([
});
},
+ copy: function() {
+ ArticleManager.copy(this.data.id, this.options.locale).done(function(data) {
+ this.toEdit(this.options.locale, data.id);
+ }.bind(this));
+ },
+
saved: function(id, data, action) {
this.setData(data);
diff --git a/Resources/public/js/services/manager.js b/Resources/public/js/services/manager.js
index 029edb636..cfa69d318 100644
--- a/Resources/public/js/services/manager.js
+++ b/Resources/public/js/services/manager.js
@@ -101,6 +101,16 @@ define(['jquery', 'services/husky/util'], function($, Util) {
);
},
+ /**
+ * Copy given article.
+ *
+ * @param {String} id
+ * @param {String} locale
+ */
+ copy: function(id, locale) {
+ return Util.save(templates.url({id: id, locale: locale, action: 'copy'}), 'POST');
+ },
+
/**
* Returns copy article from a given locale to a array of other locales url.
*
diff --git a/Resources/translations/sulu/backend.de.xlf b/Resources/translations/sulu/backend.de.xlf
index 9cdb1ba72..5fa6691a4 100644
--- a/Resources/translations/sulu/backend.de.xlf
+++ b/Resources/translations/sulu/backend.de.xlf
@@ -134,6 +134,10 @@
Artikel nach Kontakt filtern
+
+
+ Artikel kopieren
+