diff --git a/Admin/ArticleContentNavigationProvider.php b/Admin/ArticleContentNavigationProvider.php index da1181af0..06b0fe5fb 100644 --- a/Admin/ArticleContentNavigationProvider.php +++ b/Admin/ArticleContentNavigationProvider.php @@ -13,6 +13,7 @@ use Sulu\Bundle\AdminBundle\Navigation\ContentNavigationItem; use Sulu\Bundle\AdminBundle\Navigation\ContentNavigationProviderInterface; +use Sulu\Bundle\AdminBundle\Navigation\DisplayCondition; /** * Provides tabs for article-form. @@ -35,6 +36,11 @@ public function getNavigationItems(array $options = []) $seo->setAction('seo'); $seo->setComponent('articles/edit/seo@suluarticle'); $seo->setDisplay(['edit']); + $seo->setDisplayConditions( + [ + new DisplayCondition('type', DisplayCondition::OPERATOR_EQUAL, null), + ] + ); $excerpt = new ContentNavigationItem('content-navigation.contents.excerpt'); $excerpt->setId('excerpt'); @@ -42,6 +48,11 @@ public function getNavigationItems(array $options = []) $excerpt->setAction('excerpt'); $excerpt->setComponent('articles/edit/excerpt@suluarticle'); $excerpt->setDisplay(['edit']); + $excerpt->setDisplayConditions( + [ + new DisplayCondition('type', DisplayCondition::OPERATOR_EQUAL, null), + ] + ); $settings = new ContentNavigationItem('content-navigation.contents.settings'); $settings->setId('settings'); @@ -49,6 +60,11 @@ public function getNavigationItems(array $options = []) $settings->setAction('settings'); $settings->setComponent('articles/edit/settings@suluarticle'); $settings->setDisplay(['edit']); + $settings->setDisplayConditions( + [ + new DisplayCondition('type', DisplayCondition::OPERATOR_EQUAL, null), + ] + ); return [$details, $seo, $excerpt, $settings]; } diff --git a/Controller/ArticleController.php b/Controller/ArticleController.php index e08a9fad0..5c9d73aef 100644 --- a/Controller/ArticleController.php +++ b/Controller/ArticleController.php @@ -21,6 +21,7 @@ use ONGR\ElasticsearchDSL\Query\TermQuery; use ONGR\ElasticsearchDSL\Sort\FieldSort; use Sulu\Bundle\ArticleBundle\Document\Form\ArticleDocumentType; +use Sulu\Bundle\ArticleBundle\Metadata\ArticleViewDocumentIdTrait; use Sulu\Component\Content\Form\Exception\InvalidFormException; use Sulu\Component\DocumentManager\DocumentManagerInterface; use Sulu\Component\Rest\Exception\MissingParameterException; @@ -40,6 +41,7 @@ class ArticleController extends RestController implements ClassResourceInterface const DOCUMENT_TYPE = 'article'; use RequestParametersTrait; + use ArticleViewDocumentIdTrait; /** * Create field-descriptor array. @@ -49,7 +51,7 @@ class ArticleController extends RestController implements ClassResourceInterface private function getFieldDescriptors() { return [ - 'id' => new FieldDescriptor('id', 'public.id', true), + 'uuid' => new FieldDescriptor('uuid', 'public.id', true), 'typeTranslation' => new FieldDescriptor( 'typeTranslation', 'sulu_article.list.type', @@ -86,6 +88,8 @@ public function cgetFieldsAction() */ public function cgetAction(Request $request) { + $locale = $this->getRequestParameter($request, 'locale', true); + $restHelper = $this->get('sulu_core.list_rest_helper'); /** @var Manager $manager */ @@ -96,8 +100,12 @@ public function cgetAction(Request $request) $limit = (int) $restHelper->getLimit(); $page = (int) $restHelper->getPage(); + if (null !== $locale) { + $search->addQuery(new TermQuery('locale', $locale)); + } + if (count($ids = array_filter(explode(',', $request->get('ids', ''))))) { - $search->addQuery(new IdsQuery($ids)); + $search->addQuery(new IdsQuery($this->getViewDocumentIds($ids, $locale))); $limit = count($ids); } @@ -170,7 +178,7 @@ public function getAction($uuid, Request $request) $uuid, $locale, [ - 'load_ghost_content' => false, + 'load_ghost_content' => true, 'load_shadow_content' => false, ] ); @@ -199,6 +207,7 @@ public function postAction(Request $request) $document->setAuthored(new \DateTime()); if (array_key_exists('authored', $data)) { $document->setAuthored(new \DateTime($data['authored'])); + unset($data['authored']); } $document->setAuthors($this->getAuthors($data)); @@ -240,6 +249,7 @@ public function putAction(Request $request, $uuid) if (array_key_exists('authored', $data)) { $document->setAuthored(new \DateTime($data['authored'])); + unset($data['authored']); } $document->setAuthors($this->getAuthors($data)); diff --git a/Document/ArticleViewDocument.php b/Document/ArticleViewDocument.php index c3a2580c4..0cb2e7256 100644 --- a/Document/ArticleViewDocument.php +++ b/Document/ArticleViewDocument.php @@ -28,12 +28,19 @@ class ArticleViewDocument implements ArticleViewDocumentInterface * * @Id */ + protected $id; + + /** + * @var string + * + * @Property(type="string", options={"analyzer": "keyword"}) + */ protected $uuid; /** * @var string * - * @Property(type="string") + * @Property(type="string", options={"analyzer": "keyword"}) */ protected $locale; @@ -203,14 +210,40 @@ class ArticleViewDocument implements ArticleViewDocumentInterface */ protected $publishedState; + /** + * @var LocalizationStateViewObject + * + * @Embedded(class="SuluArticleBundle:LocalizationStateViewObject") + */ + protected $localizationState; + /** * @param string $uuid */ - public function __construct($uuid = null) - { + public function __construct( + $uuid = null + ) { $this->uuid = $uuid; } + /** + * {@inheritdoc} + */ + public function getId() + { + return $this->id; + } + + /** + * {@inheritdoc} + */ + public function setId($id) + { + $this->id = $id; + + return $this; + } + /** * {@inheritdoc} */ @@ -436,7 +469,7 @@ public function getSeo() /** * {@inheritdoc} */ - public function setSeo($seo) + public function setSeo(SeoViewObject $seo) { $this->seo = $seo; @@ -548,4 +581,22 @@ public function setPublishedState($publishedState) return $this; } + + /** + * {@inheritdoc} + */ + public function getLocalizationState() + { + return $this->localizationState; + } + + /** + * {@inheritdoc} + */ + public function setLocalizationState(LocalizationStateViewObject $localizationState) + { + $this->localizationState = $localizationState; + + return $this; + } } diff --git a/Document/ArticleViewDocumentInterface.php b/Document/ArticleViewDocumentInterface.php index 8d9f73e98..66ec6e331 100644 --- a/Document/ArticleViewDocumentInterface.php +++ b/Document/ArticleViewDocumentInterface.php @@ -16,6 +16,22 @@ */ interface ArticleViewDocumentInterface { + /** + * Returns id. + * + * @return string + */ + public function getId(); + + /** + * Set id. + * + * @param string $id + * + * @return $this + */ + public function setId($id); + /** * Returns uuid. * @@ -222,7 +238,7 @@ public function getSeo(); * * @return $this */ - public function setSeo($seo); + public function setSeo(SeoViewObject $seo); /** * Returns authored. @@ -319,4 +335,20 @@ public function getPublishedState(); * @return $this */ public function setPublishedState($publishedState); + + /** + * Get localization state. + * + * @return LocalizationStateViewObject + */ + public function getLocalizationState(); + + /** + * Set localization state. + * + * @param LocalizationStateViewObject $localizationState + * + * @return $this + */ + public function setLocalizationState(LocalizationStateViewObject $localizationState); } diff --git a/Document/Index/ArticleGhostIndexer.php b/Document/Index/ArticleGhostIndexer.php new file mode 100644 index 000000000..f2b1dff7d --- /dev/null +++ b/Document/Index/ArticleGhostIndexer.php @@ -0,0 +1,130 @@ +webspaceManager = $webspaceManager; + $this->documentManager = $documentManager; + } + + /** + * {@inheritdoc} + */ + public function index(ArticleDocument $document) + { + $article = $this->createOrUpdateArticle($document, $document->getLocale()); + $this->createOrUpdateGhosts($document); + $this->dispatchIndexEvent($document, $article); + } + + /** + * {@inheritdoc} + */ + public function remove($document) + { + foreach ($this->webspaceManager->getAllLocalizations() as $localization) { + $articleId = $this->getArticleId($document->getUuid(), $localization->getLocale()); + $this->removeArticle($articleId); + } + } + + /** + * @param ArticleDocument $document + */ + private function createOrUpdateGhosts(ArticleDocument $document) + { + $documentLocale = $document->getLocale(); + /** @var Localization $localization */ + foreach ($this->webspaceManager->getAllLocalizations() as $localization) { + $locale = $localization->getLocale(); + if ($documentLocale !== $locale) { + // Try index the article ghosts. + $this->createOrUpdateArticle( + $this->documentManager->find( + $document->getUuid(), + $locale, + [ + 'load_ghost_content' => true, + ] + ), + $localization->getLocale(), + LocalizationState::GHOST + ); + } + } + } +} diff --git a/Document/Index/ArticleIndexer.php b/Document/Index/ArticleIndexer.php index 99c883da8..777dd91b2 100644 --- a/Document/Index/ArticleIndexer.php +++ b/Document/Index/ArticleIndexer.php @@ -14,12 +14,16 @@ use ONGR\ElasticsearchBundle\Service\Manager; use ONGR\ElasticsearchDSL\Query\MatchAllQuery; use Sulu\Bundle\ArticleBundle\Document\ArticleDocument; +use Sulu\Bundle\ArticleBundle\Document\ArticleViewDocument; +use Sulu\Bundle\ArticleBundle\Document\ArticleViewDocumentInterface; use Sulu\Bundle\ArticleBundle\Document\Index\Factory\ExcerptFactory; use Sulu\Bundle\ArticleBundle\Document\Index\Factory\SeoFactory; +use Sulu\Bundle\ArticleBundle\Document\LocalizationStateViewObject; use Sulu\Bundle\ArticleBundle\Event\Events; use Sulu\Bundle\ArticleBundle\Event\IndexEvent; use Sulu\Bundle\ArticleBundle\Metadata\ArticleTypeTrait; use Sulu\Bundle\SecurityBundle\UserManager\UserManager; +use Sulu\Component\Content\Document\LocalizationState; use Sulu\Component\Content\Document\WorkflowStage; use Sulu\Component\Content\Metadata\Factory\StructureMetadataFactoryInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -113,57 +117,75 @@ public function __construct( } /** - * {@inheritdoc} + * Returns translation for given article type. + * + * @param string $type + * + * @return string */ - public function clear() + private function getTypeTranslation($type) { - $pageSize = 500; - $repository = $this->manager->getRepository($this->documentFactory->getClass('article')); - $search = $repository->createSearch() - ->addQuery(new MatchAllQuery()) - ->setSize($pageSize); - - $count = $repository->count($repository->createSearch()->addQuery(new MatchAllQuery())); - $maxPage = ceil($count / $pageSize); - for ($page = 1; $page <= $maxPage; ++$page) { - $search->setFrom(($page - 1) * $pageSize); - foreach ($repository->execute($search) as $document) { - $this->manager->remove($document); - } - - $this->manager->commit(); + if (!array_key_exists($type, $this->typeConfiguration)) { + return ucfirst($type); } - $this->manager->clearCache(); - $this->manager->flush(); + $typeTranslationKey = $this->typeConfiguration[$type]['translation_key']; + + return $this->translator->trans( + $typeTranslationKey, + [], + 'backend' + ); } /** - * {@inheritdoc} + * @param ArticleDocument $document + * @param ArticleViewDocument $article */ - public function setUnpublished($uuid) + protected function dispatchIndexEvent(ArticleDocument $document, ArticleViewDocument $article) { - $article = $this->manager->find($this->documentFactory->getClass('article'), $uuid); - - if (!$article) { - return; - } - - $article->setPublished(null); - $article->setPublishedState(false); - - $this->manager->persist($article); + $this->eventDispatcher->dispatch(Events::INDEX_EVENT, new IndexEvent($document, $article)); } /** - * {@inheritdoc} + * @param string $uuid + * @param string $locale + * + * @return string */ - public function index(ArticleDocument $document) + protected function getArticleId($uuid, $locale) { - $article = $this->manager->find($this->documentFactory->getClass('article'), $document->getUuid()); + return $uuid . '-' . $locale; + } + + /** + * @param ArticleDocument $document + * @param string $locale + * @param string $localizationState + * + * @return ArticleViewDocumentInterface + */ + protected function createOrUpdateArticle( + ArticleDocument $document, + $locale, + $localizationState = LocalizationState::LOCALIZED + ) { + $articleId = $this->getArticleId($document->getUuid(), $locale); + /** @var ArticleViewDocument $article */ + $article = $this->manager->find($this->documentFactory->getClass('article'), $articleId); + if (!$article) { $article = $this->documentFactory->create('article'); + $article->setId($articleId); $article->setUuid($document->getUuid()); + $article->setLocale($locale); + } else { + // Only index ghosts when the article isn't a ghost himself. + if (LocalizationState::GHOST === $localizationState + && LocalizationState::GHOST !== $article->getLocalizationState()->state + ) { + return null; + } } $structureMetadata = $this->structureMetadataFactory->getStructureMetadata( @@ -184,6 +206,12 @@ public function index(ArticleDocument $document) $article->setPublished($document->getPublished()); $article->setPublishedState($document->getWorkflowStage() === WorkflowStage::PUBLISHED); $article->setTypeTranslation($this->getTypeTranslation($this->getType($structureMetadata))); + $article->setLocalizationState( + new LocalizationStateViewObject( + $localizationState, + (LocalizationState::LOCALIZED === $localizationState) ? null : $document->getLocale() + ) + ); $extensions = $document->getExtensionsData()->toArray(); $article->setExcerpt($this->excerptFactory->create($extensions['excerpt'], $document->getLocale())); @@ -203,17 +231,20 @@ public function index(ArticleDocument $document) } } - $this->eventDispatcher->dispatch(Events::INDEX_EVENT, new IndexEvent($document, $article)); - $this->manager->persist($article); + + return $article; } /** - * {@inheritdoc} + * @param string $id */ - public function remove($document) + protected function removeArticle($id) { - $article = $this->manager->find($this->documentFactory->getClass('article'), $document->getUuid()); + $article = $this->manager->find( + $this->documentFactory->getClass('article'), + $id + ); if (null === $article) { return; } @@ -221,6 +252,16 @@ public function remove($document) $this->manager->remove($article); } + /** + * {@inheritdoc} + */ + public function remove($document) + { + $this->removeArticle( + $this->getArticleId($document->getUuid(), $document->getOriginalLocale()) + ); + } + /** * {@inheritdoc} */ @@ -230,24 +271,54 @@ public function flush() } /** - * Returns translation for given article type. - * - * @param string $type - * - * @return string + * {@inheritdoc} */ - private function getTypeTranslation($type) + public function clear() { - if (!array_key_exists($type, $this->typeConfiguration)) { - return ucfirst($type); + $pageSize = 500; + $repository = $this->manager->getRepository($this->documentFactory->getClass('article')); + $search = $repository->createSearch() + ->addQuery(new MatchAllQuery()) + ->setSize($pageSize); + + $count = $repository->count($repository->createSearch()->addQuery(new MatchAllQuery())); + $maxPage = ceil($count / $pageSize); + for ($page = 1; $page <= $maxPage; ++$page) { + $search->setFrom(($page - 1) * $pageSize); + foreach ($repository->execute($search) as $document) { + $this->manager->remove($document); + } + + $this->manager->commit(); } - $typeTranslationKey = $this->typeConfiguration[$type]['translation_key']; + $this->manager->clearCache(); + $this->manager->flush(); + } - return $this->translator->trans( - $typeTranslationKey, - [], - 'backend' - ); + /** + * {@inheritdoc} + */ + public function setUnpublished($uuid) + { + $article = $this->manager->find($this->documentFactory->getClass('article'), $uuid); + + if (!$article) { + return; + } + + $article->setPublished(null); + $article->setPublishedState(false); + + $this->manager->persist($article); + } + + /** + * {@inheritdoc} + */ + public function index(ArticleDocument $document) + { + $article = $this->createOrUpdateArticle($document, $document->getLocale()); + $this->dispatchIndexEvent($document, $article); } } diff --git a/Document/LocalizationStateViewObject.php b/Document/LocalizationStateViewObject.php new file mode 100644 index 000000000..5e757a3b7 --- /dev/null +++ b/Document/LocalizationStateViewObject.php @@ -0,0 +1,47 @@ +state = $state; + $this->locale = $locale; + } +} diff --git a/Document/Serializer/ArticleSubscriber.php b/Document/Serializer/ArticleSubscriber.php index aea9c1f72..b1a9d1136 100644 --- a/Document/Serializer/ArticleSubscriber.php +++ b/Document/Serializer/ArticleSubscriber.php @@ -93,7 +93,7 @@ public function addTypeOnPostSerialize(ObjectEvent $event) } $structure = $this->structureManager->getStructure($article->getStructureType(), 'article'); - $visitor->addData('type', $context->accept($this->getType($structure->getStructure()))); + $visitor->addData('articleType', $context->accept($this->getType($structure->getStructure()))); } /** diff --git a/Document/Subscriber/ArticleSubscriber.php b/Document/Subscriber/ArticleSubscriber.php index 48f245170..890b88233 100644 --- a/Document/Subscriber/ArticleSubscriber.php +++ b/Document/Subscriber/ArticleSubscriber.php @@ -16,8 +16,10 @@ use Sulu\Bundle\ArticleBundle\Document\Index\IndexerInterface; 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\FlushEvent; use Sulu\Component\DocumentManager\Event\MetadataLoadEvent; use Sulu\Component\DocumentManager\Event\RemoveEvent; use Sulu\Component\DocumentManager\Event\UnpublishEvent; @@ -54,25 +56,43 @@ class ArticleSubscriber implements EventSubscriberInterface */ private $entityManager; + /** + * @var DocumentManagerInterface + */ + private $documentManager; + + /** + * @var array + */ + private $documents = []; + + /** + * @var array + */ + private $liveDocuments = []; + /** * @param IndexerInterface $indexer * @param IndexerInterface $liveIndexer * @param RouteManagerInterface $routeManager * @param RouteRepositoryInterface $routeRepository * @param EntityManagerInterface $entityManager + * @param DocumentManagerInterface $documentManager */ public function __construct( IndexerInterface $indexer, IndexerInterface $liveIndexer, RouteManagerInterface $routeManager, RouteRepositoryInterface $routeRepository, - EntityManagerInterface $entityManager + EntityManagerInterface $entityManager, + DocumentManagerInterface $documentManager ) { $this->indexer = $indexer; $this->liveIndexer = $liveIndexer; $this->routeManager = $routeManager; $this->routeRepository = $routeRepository; $this->entityManager = $entityManager; + $this->documentManager = $documentManager; } /** @@ -82,13 +102,14 @@ public static function getSubscribedEvents() { return [ Events::HYDRATE => [['handleHydrate', -500]], - Events::PERSIST => [['handleRoute', 0], ['handleRouteUpdate', 0], ['handleIndex', -500]], + Events::PERSIST => [['handleRoute', 0], ['handleRouteUpdate', 0], ['handleScheduleIndex', -500]], Events::REMOVE => [['handleRemove', -500], ['handleRemoveLive', -500]], Events::METADATA_LOAD => 'handleMetadataLoad', - Events::PUBLISH => [['handleIndexLive', 0], ['handleIndex', 0]], + Events::PUBLISH => [['handleScheduleIndexLive', 0], ['handleScheduleIndex', 0]], Events::UNPUBLISH => 'handleUnpublish', Events::CONFIGURE_OPTIONS => 'configureOptions', - Events::REMOVE_DRAFT => ['handleIndex', -1024], + Events::REMOVE_DRAFT => ['handleScheduleIndex', -1024], + Events::FLUSH => [['handleFlush', -2048], ['handleFlushLive', -2048]], ]; } @@ -104,7 +125,12 @@ public function handleHydrate(AbstractMappingEvent $event) return; } - $document->setRoute($this->routeRepository->findByPath($document->getRoutePath(), $event->getLocale())); + $route = $this->routeRepository->findByPath($document->getRoutePath(), $document->getOriginalLocale()); + if (!$route) { + return; + } + + $document->setRoute($route); } /** @@ -148,19 +174,84 @@ public function handleRouteUpdate(AbstractMappingEvent $event) } /** - * Indexes for article-document. + * Schedule article document for index. * * @param AbstractMappingEvent $event */ - public function handleIndex(AbstractMappingEvent $event) + public function handleScheduleIndex(AbstractMappingEvent $event) { $document = $event->getDocument(); if (!$document instanceof ArticleDocument) { return; } - $this->indexer->index($document); + $this->documents[$document->getUuid()] = [ + 'uuid' => $document->getUuid(), + 'locale' => $document->getLocale(), + ]; + } + + /** + * Schedule article document for live index. + * + * @param AbstractMappingEvent $event + */ + public function handleScheduleIndexLive(AbstractMappingEvent $event) + { + $document = $event->getDocument(); + if (!$document instanceof ArticleDocument) { + return; + } + + $this->liveDocuments[$document->getUuid()] = [ + 'uuid' => $document->getUuid(), + 'locale' => $document->getLocale(), + ]; + } + + /** + * Index all scheduled article documents with default indexer. + * + * @param FlushEvent $event + */ + public function handleFlush(FlushEvent $event) + { + if (count($this->documents) < 1) { + return; + } + + foreach ($this->documents as $document) { + $this->indexer->index( + $this->documentManager->find($document['uuid'], + $document['locale'] + ) + ); + } $this->indexer->flush(); + $this->documents = []; + } + + /** + * Index all scheduled article documents with live indexer. + * + * @param FlushEvent $event + */ + public function handleFlushLive(FlushEvent $event) + { + if (count($this->liveDocuments) < 1) { + return; + } + + foreach ($this->liveDocuments as $document) { + $this->liveIndexer->index( + $this->documentManager->find( + $document['uuid'], + $document['locale'] + ) + ); + } + $this->liveIndexer->flush(); + $this->liveDocuments = []; } /** diff --git a/Metadata/ArticleViewDocumentIdTrait.php b/Metadata/ArticleViewDocumentIdTrait.php new file mode 100644 index 000000000..0ff5f807b --- /dev/null +++ b/Metadata/ArticleViewDocumentIdTrait.php @@ -0,0 +1,46 @@ +getViewDocumentId($uuid, $locale); + } + + return $ids; + } +} diff --git a/Resources/config/serializer/Document.ArticleViewDocument.xml b/Resources/config/serializer/Document.ArticleViewDocument.xml index d3bbdbe71..1bf3b7587 100644 --- a/Resources/config/serializer/Document.ArticleViewDocument.xml +++ b/Resources/config/serializer/Document.ArticleViewDocument.xml @@ -1,7 +1,8 @@ - + + @@ -11,5 +12,6 @@ + diff --git a/Resources/config/serializer/Document.LocalizationStateViewObject.xml b/Resources/config/serializer/Document.LocalizationStateViewObject.xml new file mode 100644 index 000000000..0a358b119 --- /dev/null +++ b/Resources/config/serializer/Document.LocalizationStateViewObject.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Resources/config/services.xml b/Resources/config/services.xml index 1b3871961..ba4c73e69 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -31,7 +31,7 @@ %sulu_article.documents% + class="Sulu\Bundle\ArticleBundle\Document\Index\ArticleGhostIndexer"> @@ -41,6 +41,8 @@ %sulu_article.types% + + @@ -100,6 +102,7 @@ + diff --git a/Resources/public/dist/components/articles/edit/details/main.js b/Resources/public/dist/components/articles/edit/details/main.js index 3a7786b9e..8a6a6444c 100644 --- a/Resources/public/dist/components/articles/edit/details/main.js +++ b/Resources/public/dist/components/articles/edit/details/main.js @@ -1 +1 @@ -define(["underscore","jquery","suluarticle/services/article-manager"],function(a,b,c){"use strict";return{layout:function(){return{extendExisting:!0,content:{width:this.options.preview?"fixed":"max",rightSpace:!1,leftSpace:!1}}},initialize:function(){this.saved=!0,this.render(),this.bindCustomEvents(),this.listenForChange()},bindCustomEvents:function(){this.sandbox.on("sulu.tab.template-change",function(a){this.checkRenderTemplate(a.template)},this),this.sandbox.on("sulu.content.contents.default-template",function(a){this.template=a,this.sandbox.emit("sulu.header.toolbar.item.change","template",a)}.bind(this)),this.sandbox.on("sulu.tab.save",this.save.bind(this))},listenForChange:function(){this.sandbox.dom.on(this.$el,"keyup",a.debounce(this.setDirty.bind(this),10),"input, textarea"),this.sandbox.dom.on(this.$el,"change",a.debounce(this.setDirty.bind(this),10),'input[type="checkbox"], select'),this.sandbox.on("sulu.content.changed",this.setDirty.bind(this))},setDirty:function(){this.saved=!1,this.sandbox.emit("sulu.tab.dirty")},save:function(b){if(!this.sandbox.form.validate(this.formId))return void this.sandbox.emit("sulu.tab.dirty",!0);var d=this.sandbox.form.getData(this.formId);d.template=this.template,a.each(d,function(a,b){this.data[b]=a}.bind(this)),c.save(this.data,this.options.locale,b).then(function(a){this.data=a,this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,d)}.bind(this))},render:function(){this.checkRenderTemplate(this.data.template||null)},checkRenderTemplate:function(a){return a&&this.template===a?this.sandbox.emit("sulu.header.toolbar.item.enable","template",!1):(this.sandbox.emit("sulu.header.toolbar.item.loading","template"),void(""===this.template||this.saved?this.loadFormTemplate(a):this.showRenderTemplateDialog(a)))},showRenderTemplateDialog:function(a){this.sandbox.emit("sulu.overlay.show-warning","sulu.overlay.be-careful","content.template.dialog.content",function(){this.sandbox.emit("sulu.header.toolbar.item.enable","template",!1),this.template&&this.sandbox.emit("sulu.header.toolbar.item.change","template",this.template,!1)}.bind(this),function(){this.loadFormTemplate(a)}.bind(this))},loadFormTemplate:function(a){if(a||(a=this.options.config.types[this.options.type||this.data.type]["default"]),this.template=a,this.formId="#content-form-container",this.$container=this.sandbox.dom.createElement('
'),this.html(this.$container),this.sandbox.form.getObject(this.formId)){var b=this.data;this.data=this.sandbox.form.getData(this.formId),b.id&&(this.data.id=b.id),this.data=this.sandbox.util.extend({},b,this.data)}require([this.getTemplateUrl(a)],function(a){this.renderFormTemplate(a)}.bind(this))},getTemplateUrl:function(a){var b="text!/admin/content/template/form";return b+=a?"/"+a+".html":".html",b+="?type=article&language="+this.options.locale,this.data.id&&(b+="&uuid="+this.data.id),b},renderFormTemplate:function(a){this.sandbox.dom.html(this.formId,this.sandbox.util.template(a,{translate:this.sandbox.translate,content:this.data,options:this.options})),this.data.id||this.$find("#routePath").parent().remove(),this.createForm(this.data).then(function(){this.changeTemplateDropdownHandler()}.bind(this))},changeTemplateDropdownHandler:function(){this.template&&this.sandbox.emit("sulu.header.toolbar.item.change","template",this.template),this.sandbox.emit("sulu.header.toolbar.item.enable","template",!1)},createForm:function(a){var b=this.sandbox.form.create(this.formId),c=this.sandbox.data.deferred();return b.initialized.then(function(){this.sandbox.form.setData(this.formId,a).then(function(){this.sandbox.start(this.$el,{reset:!0}).then(function(){if(this.initSortableBlock(),this.bindFormEvents(),c.resolve(),this.options.preview){this.options.preview.bindDomEvents(this.$el);var a=this.data;a.template=this.template,this.options.preview.updateContext({template:this.template},a)}}.bind(this))}.bind(this))}.bind(this)),c.promise()},initSortableBlock:function(){var a,b=this.sandbox.dom.find(".sortable",this.$el);b&&b.length>0&&(this.sandbox.dom.sortable(b,"destroy"),a=this.sandbox.dom.sortable(b,{handle:".move",forcePlaceholderSize:!0}),this.sandbox.dom.unbind(a,"sortupdate"),a.bind("sortupdate",function(a){this.updatePreviewProperty(a.currentTarget,null),this.sandbox.emit("sulu.content.changed")}.bind(this)))},bindFormEvents:function(){this.sandbox.dom.on(this.formId,"form-remove",function(a,b){this.initSortableBlock(),this.setDirty(),this.updatePreviewProperty(a.currentTarget,b)}.bind(this)),this.sandbox.dom.on(this.formId,"form-add",function(a,b,c,d){var e=this.sandbox.dom.children(this.$find('[data-mapper-property="'+b+'"]')),f=void 0!==d&&e.length>d?e[d]:this.sandbox.dom.last(e);this.sandbox.start(f),this.setDirty(),this.initSortableBlock(),this.updatePreviewProperty(a.currentTarget,b)}.bind(this)),this.sandbox.dom.on(this.formId,"init-sortable",function(a){this.initSortableBlock()}.bind(this))},loadComponentData:function(){var a=b.Deferred();return a.resolve(this.options.data()),a},updatePreviewProperty:function(a,b){if(this.options.preview){var c=this.sandbox.form.getData(this.formId);!b&&a&&(b=this.sandbox.dom.data(a,"mapperProperty")),this.options.preview.updateProperty(b,c[b])}}}}); \ No newline at end of file +define(["underscore","jquery","services/suluarticle/article-manager"],function(a,b,c){"use strict";return{layout:function(){return{extendExisting:!0,content:{width:this.options.preview?"fixed":"max",rightSpace:!1,leftSpace:!1}}},initialize:function(){this.saved=!0,this.render(),this.bindCustomEvents(),this.listenForChange()},bindCustomEvents:function(){this.sandbox.on("sulu.tab.template-change",function(a){this.checkRenderTemplate(a.template)},this),this.sandbox.on("sulu.content.contents.default-template",function(a){this.template=a,this.sandbox.emit("sulu.header.toolbar.item.change","template",a)}.bind(this)),this.sandbox.on("sulu.tab.save",this.save.bind(this))},listenForChange:function(){this.sandbox.dom.on(this.$el,"keyup",a.debounce(this.setDirty.bind(this),10),"input, textarea"),this.sandbox.dom.on(this.$el,"change",a.debounce(this.setDirty.bind(this),10),'input[type="checkbox"], select'),this.sandbox.on("sulu.content.changed",this.setDirty.bind(this))},setDirty:function(){this.saved=!1,this.sandbox.emit("sulu.tab.dirty")},save:function(b){if(!this.sandbox.form.validate(this.formId))return void this.sandbox.emit("sulu.tab.dirty",!0);var d=this.sandbox.form.getData(this.formId);d.template=this.template,a.each(d,function(a,b){this.data[b]=a}.bind(this)),c.save(this.data,this.data.id,this.options.locale,b).then(function(a){return this.data=a,this.ghost&&!this.data.type?void this.sandbox.emit("sulu.router.navigate","articles/"+this.options.locale+"/edit:"+this.data.id+"/details",!0,!0):void this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,d)}.bind(this))},render:function(){this.checkRenderTemplate(this.data.template||null)},checkRenderTemplate:function(a){return a&&this.template===a?this.sandbox.emit("sulu.header.toolbar.item.enable","template",!1):(this.sandbox.emit("sulu.header.toolbar.item.loading","template"),void(""===this.template||this.saved?this.loadFormTemplate(a):this.showRenderTemplateDialog(a)))},showRenderTemplateDialog:function(a){this.sandbox.emit("sulu.overlay.show-warning","sulu.overlay.be-careful","content.template.dialog.content",function(){this.sandbox.emit("sulu.header.toolbar.item.enable","template",!1),this.template&&this.sandbox.emit("sulu.header.toolbar.item.change","template",this.template,!1)}.bind(this),function(){this.loadFormTemplate(a)}.bind(this))},loadFormTemplate:function(a){if(a||(a=this.options.config.types[this.options.type||this.data.articleType]["default"]),this.template=a,this.formId="#content-form-container",this.$container=this.sandbox.dom.createElement('
'),this.html(this.$container),this.sandbox.form.getObject(this.formId)){var b=this.data;this.data=this.sandbox.form.getData(this.formId),b.id&&(this.data.id=b.id),this.data=this.sandbox.util.extend({},b,this.data)}require([this.getTemplateUrl(a)],function(a){this.renderFormTemplate(a)}.bind(this))},getTemplateUrl:function(a){var b="text!/admin/content/template/form";return b+=a?"/"+a+".html":".html",b+="?type=article&language="+this.options.locale,this.data.id&&(b+="&uuid="+this.data.id),b},renderFormTemplate:function(a){this.sandbox.dom.html(this.formId,this.sandbox.util.template(a,{translate:this.sandbox.translate,content:this.data,options:this.options})),(!this.data.id||this.data.type&&"ghost"===this.data.type.name)&&(this.$find("#routePath").parent().remove(),this.data.routePath=null),this.data.type&&"ghost"===this.data.type.name&&(this.ghost={locale:this.data.type.value,title:this.data.title},this.data={id:this.data.id,articleType:this.data.articleType}),this.createForm(this.data).then(function(){this.changeTemplateDropdownHandler()}.bind(this))},changeTemplateDropdownHandler:function(){this.template&&this.sandbox.emit("sulu.header.toolbar.item.change","template",this.template),this.sandbox.emit("sulu.header.toolbar.item.enable","template",!1)},createForm:function(a){var b=this.sandbox.form.create(this.formId),c=this.sandbox.data.deferred();return b.initialized.then(function(){this.sandbox.form.setData(this.formId,a).then(function(){this.ghost&&this.sandbox.dom.attr("#title","placeholder",this.ghost.locale+": "+this.ghost.title),this.sandbox.start(this.$el,{reset:!0}).then(function(){if(this.initSortableBlock(),this.bindFormEvents(),c.resolve(),this.options.preview){this.options.preview.bindDomEvents(this.$el);var a=this.data;a.template=this.template,this.options.preview.updateContext({template:this.template},a)}}.bind(this))}.bind(this))}.bind(this)),c.promise()},initSortableBlock:function(){var a,b=this.sandbox.dom.find(".sortable",this.$el);b&&b.length>0&&(this.sandbox.dom.sortable(b,"destroy"),a=this.sandbox.dom.sortable(b,{handle:".move",forcePlaceholderSize:!0}),this.sandbox.dom.unbind(a,"sortupdate"),a.bind("sortupdate",function(a){this.updatePreviewProperty(a.currentTarget,null),this.sandbox.emit("sulu.content.changed")}.bind(this)))},bindFormEvents:function(){this.sandbox.dom.on(this.formId,"form-remove",function(a,b){this.initSortableBlock(),this.setDirty(),this.updatePreviewProperty(a.currentTarget,b)}.bind(this)),this.sandbox.dom.on(this.formId,"form-add",function(a,b,c,d){var e=this.sandbox.dom.children(this.$find('[data-mapper-property="'+b+'"]')),f=void 0!==d&&e.length>d?e[d]:this.sandbox.dom.last(e);this.sandbox.start(f),this.setDirty(),this.initSortableBlock(),this.updatePreviewProperty(a.currentTarget,b)}.bind(this)),this.sandbox.dom.on(this.formId,"init-sortable",function(a){this.initSortableBlock()}.bind(this))},loadComponentData:function(){var a=b.Deferred();return a.resolve(this.options.data()),a},updatePreviewProperty:function(a,b){if(this.options.preview){var c=this.sandbox.form.getData(this.formId);!b&&a&&(b=this.sandbox.dom.data(a,"mapperProperty")),this.options.preview.updateProperty(b,c[b])}}}}); \ No newline at end of file diff --git a/Resources/public/dist/components/articles/edit/excerpt/main.js b/Resources/public/dist/components/articles/edit/excerpt/main.js index 0d4093f97..2dd31c4df 100644 --- a/Resources/public/dist/components/articles/edit/excerpt/main.js +++ b/Resources/public/dist/components/articles/edit/excerpt/main.js @@ -1 +1 @@ -define(["suluarticle/services/article-manager"],function(a){"use strict";return{type:"excerpt-tab",parseData:function(a){return a.ext.excerpt},getTemplate:function(){return"text!/admin/content/template/form/excerpt.html?language="+this.options.locale},save:function(b,c){var d=this.options.data();d.ext.excerpt=b,a.save(d,this.options.locale,c).then(function(a){this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,b)}.bind(this))}}}); \ No newline at end of file +define(["services/suluarticle/article-manager"],function(a){"use strict";return{type:"excerpt-tab",parseData:function(a){return a.ext.excerpt},getTemplate:function(){return"text!/admin/content/template/form/excerpt.html?language="+this.options.locale},save:function(b,c){var d=this.options.data();d.ext.excerpt=b,a.save(d,d.id,this.options.locale,c).then(function(a){this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,b)}.bind(this))}}}); \ No newline at end of file diff --git a/Resources/public/dist/components/articles/edit/main.js b/Resources/public/dist/components/articles/edit/main.js index 501331306..0de9b6561 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","suluarticle/services/article-manager","sulusecurity/services/user-manager","services/sulupreview/preview","sulusecurity/services/security-checker"],function(a,b,c,d,e,f,g){"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"}},layout:function(){return{navigation:{collapsed:!0},content:{shrinkable:!!this.options.id},sidebar:!!this.options.id&&"max"}},header:function(){var a={},b={},d={};return g.hasPermission(this.data,"edit")&&(d.saveDraft={},g.hasPermission(this.data,"live")&&(d.savePublish={},d.publish={}),c.has("sulu_automation.enabled")&&(d.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:d}},a.template={options:{dropdownOptions:{url:"/admin/articles/templates?type="+(this.options.type||this.data.type),callback:function(a){this.template=a.template,this.sandbox.emit("sulu.tab.template-change",a)}.bind(this)}}}),g.hasPermission(this.data,"live")&&(b.unpublish={options:{title:this.translations.unpublish,disabled:!this.data.published,callback:this.unpublish.bind(this)}},b.divider={options:{divider:!0}}),g.hasPermission(this.data,"delete")&&(b["delete"]={options:{disabled:!this.options.id,callback:this.deleteArticle.bind(this)}}),this.sandbox.util.isEmpty(b)||(a.edit={options:{dropdownItems:b}}),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:this.data}},toolbar:{buttons:a}}},initialize:function(){this.bindCustomEvents(),this.showDraftLabel(),this.setHeaderBar(!0)},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("sulu.header.language-changed",function(a){this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),this.toEdit(a.id)}.bind(this))},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["delete"](this.options.id).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)+"/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.type)+"/"+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.type),!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(b){var c=a.Deferred();return this.sandbox.emit("sulu.header.toolbar.item.loading","save"),this.sandbox.once("sulu.tab.saved",function(a,b){c.resolve(b)}.bind(this)),this.sandbox.emit("sulu.tab.save",b),c},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)}}}); \ 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"],function(a,b,c,d,e,f,g){"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"}},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)}}),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)},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",function(a){this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),this.toEdit(a.id)}.bind(this))},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["delete"](this.options.id).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)}}}); \ No newline at end of file diff --git a/Resources/public/dist/components/articles/edit/seo/main.js b/Resources/public/dist/components/articles/edit/seo/main.js index 754e76970..c197af945 100644 --- a/Resources/public/dist/components/articles/edit/seo/main.js +++ b/Resources/public/dist/components/articles/edit/seo/main.js @@ -1 +1 @@ -define(["suluarticle/services/article-manager"],function(a){"use strict";return{type:"seo-tab",parseData:function(a){return a.ext.seo},getUrl:function(){var a=this.options.data();return this.options.excerptUrlPrefix+a.route},save:function(b,c){var d=this.options.data();d.ext.seo=b,a.save(d,this.options.locale,c).then(function(a){this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,b)}.bind(this))}}}); \ No newline at end of file +define(["services/suluarticle/article-manager"],function(a){"use strict";return{type:"seo-tab",parseData:function(a){return a.ext.seo},getUrl:function(){var a=this.options.data();return this.options.excerptUrlPrefix+a.route},save:function(b,c){var d=this.options.data();d.ext.seo=b,a.save(d,d.id,this.options.locale,c).then(function(a){this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,b)}.bind(this))}}}); \ No newline at end of file diff --git a/Resources/public/dist/components/articles/edit/settings/main.js b/Resources/public/dist/components/articles/edit/settings/main.js index e0b4a1be6..aaa037b6a 100644 --- a/Resources/public/dist/components/articles/edit/settings/main.js +++ b/Resources/public/dist/components/articles/edit/settings/main.js @@ -1 +1 @@ -define(["underscore","jquery","sulusecurity/components/users/models/user","suluarticle/services/article-manager","text!/admin/articles/template/settings.html"],function(a,b,c,d,e){"use strict";var f={templates:{form:e},translations:{authored:"sulu_article.authored",authors:"sulu_article.authors",changelog:"sulu.content.form.settings.changelog",changed:"sulu.content.form.settings.changelog.changed",created:"sulu.content.form.settings.changelog.created",userNotFound:"sulu.content.form.settings.changelog.user-not-found"}};return{type:"form-tab",defaults:f,parseData:function(b){return{id:b.id,authored:b.authored,authors:a.map(b.authors,function(a){return"c"+a}),creator:b.creator,changer:b.changer,created:b.created,changed:b.changed}},tabInitialize:function(){this.sandbox.emit("sulu.tab.initialize",this.name),this.sandbox.on("sulu.tab.saved",this.saved.bind(this))},submit:function(b){if(this.sandbox.form.validate(this.formId)){var c=this.sandbox.form.getData(this.formId);a.each(c,function(a,b){this.data[b]=a}.bind(this)),this.save(this.data,b)}},save:function(b,c){b.authors=a.map(b.authors,function(a){return a.substr(1)}),d.save(b,this.options.locale,c).then(function(a){this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,b)}.bind(this))},saved:function(a){this.data=this.parseData(a)},getTemplate:function(){return this.templates.form({translations:this.translations})},getFormId:function(){return"#settings-form"},listenForChange:function(){this.sandbox.dom.on(this.formId,"change keyup",this.setDirty.bind(this)),this.sandbox.on("sulu.content.changed",this.setDirty.bind(this)),this.sandbox.on("husky.ckeditor.changed",this.setDirty.bind(this)),this.updateChangelog(this.data)},updateChangelog:function(a){var c=function(a){this.sandbox.dom.text("#created .name",a),e.resolve()},d=function(a){this.sandbox.dom.text("#changed .name",a),f.resolve()},e=b.Deferred(),f=b.Deferred();a.creator===a.changer?this.loadUser(a.creator).done(function(a){d.call(this,a),c.call(this,a)}.bind(this)).fail(function(){d.call(this,this.translations.userNotFound),c.call(this,this.translations.userNotFound)}.bind(this)):(this.loadUser(a.creator).done(function(a){c.call(this,a)}.bind(this)).fail(function(){c.call(this,this.translations.userNotFound)}.bind(this)),this.loadUser(a.changer).done(function(a){d.call(this,a)}.bind(this)).fail(function(){d.call(this,this.translations.userNotFound)}.bind(this))),this.sandbox.dom.text("#created .date",this.sandbox.date.format(a.created,!0)),this.sandbox.dom.text("#changed .date",this.sandbox.date.format(a.changed,!0)),this.sandbox.data.when([e,f]).then(function(){this.sandbox.dom.show("#changelog-container")}.bind(this))},loadUser:function(a){var d=b.Deferred(),e=new c({id:a});return e.fetch({global:!1,success:function(a){d.resolve(a.get("fullName"))}.bind(this),error:function(){d.reject()}.bind(this)}),d}}}); \ No newline at end of file +define(["underscore","jquery","sulusecurity/components/users/models/user","services/suluarticle/article-manager","text!/admin/articles/template/settings.html"],function(a,b,c,d,e){"use strict";var f={templates:{form:e},translations:{authored:"sulu_article.authored",authors:"sulu_article.authors",changelog:"sulu.content.form.settings.changelog",changed:"sulu.content.form.settings.changelog.changed",created:"sulu.content.form.settings.changelog.created",userNotFound:"sulu.content.form.settings.changelog.user-not-found"}};return{type:"form-tab",defaults:f,parseData:function(b){return{id:b.id,authored:b.authored,authors:a.map(b.authors,function(a){return"c"+a}),creator:b.creator,changer:b.changer,created:b.created,changed:b.changed}},tabInitialize:function(){this.sandbox.emit("sulu.tab.initialize",this.name),this.sandbox.on("sulu.tab.saved",this.saved.bind(this))},submit:function(b){if(this.sandbox.form.validate(this.formId)){var c=this.sandbox.form.getData(this.formId);a.each(c,function(a,b){this.data[b]=a}.bind(this)),this.save(this.data,b)}},save:function(b,c){b.authors=a.map(b.authors,function(a){return a.substr(1)}),d.save(b,b.id,this.options.locale,c).then(function(a){this.sandbox.emit("sulu.tab.saved",a.id,a)}.bind(this)).fail(function(a){this.sandbox.emit("sulu.article.error",a.status,b)}.bind(this))},saved:function(a){this.data=this.parseData(a)},getTemplate:function(){return this.templates.form({translations:this.translations})},getFormId:function(){return"#settings-form"},listenForChange:function(){this.sandbox.dom.on(this.formId,"change keyup",this.setDirty.bind(this)),this.sandbox.on("sulu.content.changed",this.setDirty.bind(this)),this.sandbox.on("husky.ckeditor.changed",this.setDirty.bind(this)),this.updateChangelog(this.data)},updateChangelog:function(a){var c=function(a){this.sandbox.dom.text("#created .name",a),e.resolve()},d=function(a){this.sandbox.dom.text("#changed .name",a),f.resolve()},e=b.Deferred(),f=b.Deferred();a.creator===a.changer?this.loadUser(a.creator).done(function(a){d.call(this,a),c.call(this,a)}.bind(this)).fail(function(){d.call(this,this.translations.userNotFound),c.call(this,this.translations.userNotFound)}.bind(this)):(this.loadUser(a.creator).done(function(a){c.call(this,a)}.bind(this)).fail(function(){c.call(this,this.translations.userNotFound)}.bind(this)),this.loadUser(a.changer).done(function(a){d.call(this,a)}.bind(this)).fail(function(){d.call(this,this.translations.userNotFound)}.bind(this))),this.sandbox.dom.text("#created .date",this.sandbox.date.format(a.created,!0)),this.sandbox.dom.text("#changed .date",this.sandbox.date.format(a.changed,!0)),this.sandbox.data.when([e,f]).then(function(){this.sandbox.dom.show("#changelog-container")}.bind(this))},loadUser:function(a){var d=b.Deferred(),e=new c({id:a});return e.fetch({global:!1,success:function(a){d.resolve(a.get("fullName"))}.bind(this),error:function(){d.reject()}.bind(this)}),d}}}); \ No newline at end of file diff --git a/Resources/public/dist/components/articles/list/main.js b/Resources/public/dist/components/articles/list/main.js index f32de7308..bd86560b1 100644 --- a/Resources/public/dist/components/articles/list/main.js +++ b/Resources/public/dist/components/articles/list/main.js @@ -1 +1 @@ -define(["underscore"],function(a){"use strict";var b={options:{config:{}},templates:{list:['
','
','
','
'].join(""),draftIcon:'',publishedIcon:'',route:["articles","<% if (!!type) { %>:<%=type%><% } %>","/<%=locale%>"].join("")},translations:{headline:"sulu_article.list.title",unpublished:"public.unpublished",publishedWithDraft:"public.published-with-draft"}};return{defaults:b,header:function(){var b,c=this.options.config.types,d=this.options.config.typeNames,e={icon:"plus-circle",title:"public.add-new"},f=!1,g=null;return 1===d.length?e.callback=function(){this.toAdd(d[0])}.bind(this):(e.dropdownItems=a.map(d,function(a){return{title:c[a].title,callback:function(){this.toAdd(a)}.bind(this)}}.bind(this)),b=[],this.options.config.displayTabAll===!0&&b.push({name:"public.all",key:null}),a.each(d,function(a){b.push({id:a,name:c[a].title,key:a}),a===this.options.type&&(g=c[a].title)}.bind(this)),f={componentOptions:{callback:this.typeChange.bind(this),preselector:"name",preselect:g},data:b}),{noBack:!0,tabs:f,toolbar:{buttons:{addArticle:{options:e},deleteSelected:{}},languageChanger:{data:this.options.config.languageChanger,preSelected:this.options.locale}}}},layout:{content:{width:"max"}},initialize:function(){this.render(),this.bindCustomEvents()},render:function(){this.$el.html(this.templates.list()),this.sandbox.sulu.initListToolbarAndList.call(this,"article","/admin/api/articles/fields",{el:this.$find(".list-toolbar-container"),instanceName:"articles",template:this.sandbox.sulu.buttons.get({settings:{options:{dropdownItems:[{type:"columnOptions"}]}}})},{el:this.sandbox.dom.find(".datagrid-container"),url:"/admin/api/articles?sortBy=authored&sortOrder=desc&locale="+this.options.locale+(this.options.type?"&type="+this.options.type:""),searchInstanceName:"articles",searchFields:["title"],resultKey:"articles",instanceName:"articles",actionCallback:function(a){this.toEdit(a)}.bind(this),viewOptions:{table:{actionIconColumn:"title",badges:[{column:"title",callback:function(a,b){var c="",d=this.translations.unpublished;return a.published&&!a.publishedState&&(d=this.translations.publishedWithDraft,c+=this.templates.publishedIcon({title:d})),a.publishedState||(c+=this.templates.draftIcon({title:d})),b.title=c,b.cssClass="badge-none",b}.bind(this)}]}}})},toEdit:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/edit:"+a+"/details")},toAdd:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/add"+(this.options.config.typeNames.length>1?":"+a:""))},toList:function(a){this.sandbox.emit("sulu.router.navigate","articles/"+(a||this.options.locale))},deleteItems:function(b){this.sandbox.util.save("/admin/api/articles?ids="+b.join(","),"DELETE").then(function(){a.each(b,function(a){this.sandbox.emit("husky.datagrid.articles.record.remove",a)}.bind(this))}.bind(this))},typeChange:function(a){var b=this.templates.route({type:a.key,locale:this.options.locale});this.sandbox.emit("husky.datagrid.articles.url.update",{type:a.key}),this.sandbox.emit("sulu.router.navigate",b,!1,!1)},bindCustomEvents:function(){this.sandbox.on("husky.datagrid.articles.number.selections",function(a){var b=a>0?"enable":"disable";this.sandbox.emit("sulu.header.toolbar.item."+b,"deleteSelected",!1)}.bind(this)),this.sandbox.on("sulu.toolbar.delete",function(){this.sandbox.emit("husky.datagrid.articles.items.get-selected",this.deleteItems.bind(this))}.bind(this)),this.sandbox.on("sulu.header.language-changed",function(a){this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),this.toList(a.id)}.bind(this))}}}); \ No newline at end of file +define(["underscore"],function(a){"use strict";var b={options:{config:{}},templates:{list:['
','
','
','
'].join(""),draftIcon:'',publishedIcon:'',route:["articles","<% if (!!type) { %>:<%=type%><% } %>","/<%=locale%>"].join("")},translations:{headline:"sulu_article.list.title",unpublished:"public.unpublished",publishedWithDraft:"public.published-with-draft"}};return{defaults:b,header:function(){var b,c=this.options.config.types,d=this.options.config.typeNames,e={icon:"plus-circle",title:"public.add-new"},f=!1,g=null;return 1===d.length?e.callback=function(){this.toAdd(d[0])}.bind(this):(e.dropdownItems=a.map(d,function(a){return{title:c[a].title,callback:function(){this.toAdd(a)}.bind(this)}}.bind(this)),b=[],this.options.config.displayTabAll===!0&&b.push({name:"public.all",key:null}),a.each(d,function(a){b.push({id:a,name:c[a].title,key:a}),a===this.options.type&&(g=c[a].title)}.bind(this)),f={componentOptions:{callback:this.typeChange.bind(this),preselector:"name",preselect:g},data:b}),{noBack:!0,tabs:f,toolbar:{buttons:{addArticle:{options:e},deleteSelected:{}},languageChanger:{data:this.options.config.languageChanger,preSelected:this.options.locale}}}},layout:{content:{width:"max"}},initialize:function(){this.render(),this.bindCustomEvents()},render:function(){this.$el.html(this.templates.list()),this.sandbox.sulu.initListToolbarAndList.call(this,"article","/admin/api/articles/fields",{el:this.$find(".list-toolbar-container"),instanceName:"articles",template:this.sandbox.sulu.buttons.get({settings:{options:{dropdownItems:[{type:"columnOptions"}]}}})},{el:this.sandbox.dom.find(".datagrid-container"),url:"/admin/api/articles?sortBy=authored&sortOrder=desc&locale="+this.options.locale+(this.options.type?"&type="+this.options.type:""),searchInstanceName:"articles",searchFields:["title"],resultKey:"articles",idKey:"uuid",instanceName:"articles",actionCallback:function(a){this.toEdit(a)}.bind(this),viewOptions:{table:{actionIconColumn:"title",badges:[{column:"title",callback:function(a,b){return!(!a.localizationState||"ghost"!==a.localizationState.state||a.localizationState.locale===this.options.language)&&(b.title=a.localizationState.locale,b)}.bind(this)},{column:"title",callback:function(a,b){var c="",d=this.translations.unpublished;return a.published&&!a.publishedState&&(d=this.translations.publishedWithDraft,c+=this.templates.publishedIcon({title:d})),a.publishedState||(c+=this.templates.draftIcon({title:d})),b.title=c,b.cssClass="badge-none",b}.bind(this)}]}}})},toEdit:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/edit:"+a+"/details")},toAdd:function(a,b){this.sandbox.emit("sulu.router.navigate","articles/"+(b||this.options.locale)+"/add"+(this.options.config.typeNames.length>1?":"+a:""))},toList:function(a){1!==this.options.config.typeNames.length&&this.options.type?this.sandbox.emit("sulu.router.navigate","articles:"+this.options.type+"/"+(a||this.options.locale)):this.sandbox.emit("sulu.router.navigate","articles/"+(a||this.options.locale))},deleteItems:function(b){this.sandbox.util.save("/admin/api/articles?ids="+b.join(","),"DELETE").then(function(){a.each(b,function(a){this.sandbox.emit("husky.datagrid.articles.record.remove",a)}.bind(this))}.bind(this))},typeChange:function(a){var b=this.templates.route({type:a.key,locale:this.options.locale});this.options.type=a.key,this.sandbox.emit("husky.datagrid.articles.url.update",{type:a.key}),this.sandbox.emit("sulu.router.navigate",b,!1,!1)},bindCustomEvents:function(){this.sandbox.on("husky.datagrid.articles.number.selections",function(a){var b=a>0?"enable":"disable";this.sandbox.emit("sulu.header.toolbar.item."+b,"deleteSelected",!1)}.bind(this)),this.sandbox.on("sulu.toolbar.delete",function(){this.sandbox.emit("husky.datagrid.articles.items.get-selected",this.deleteItems.bind(this))}.bind(this)),this.sandbox.on("sulu.header.language-changed",function(a){this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey,a.id),this.toList(a.id)}.bind(this))}}}); \ No newline at end of file diff --git a/Resources/public/dist/main.js b/Resources/public/dist/main.js index d800a7ef1..72682a6ae 100644 --- a/Resources/public/dist/main.js +++ b/Resources/public/dist/main.js @@ -1 +1 @@ -require.config({paths:{suluarticle:"../../suluarticle/dist",suluarticlecss:"../../suluarticle/css","type/article-selection":"../../suluarticle/dist/validation/types/article-selection","services/suluarticle/article-manager":"../../suluarticle/dist/services/manager"}}),define(["underscore","config"],function(a,b){"use strict";var c=function(){var c=b.get("sulu-content").locales,d=[];return a.each(c,function(a){d=d.concat(Object.keys(a))}),d};return{name:"Sulu Article Bundle",initialize:function(d){d.components.addSource("suluarticle","/bundles/suluarticle/dist/components"),d.sandbox.urlManager.setUrl("article","articles/<%= locale %>/edit:<%= id %>/details");var e=c(),f={defaultLocale:e[0],locales:e,languageChanger:a.map(e,function(a){return{id:a,title:a}}),settingsKey:"articleLanguage",typeNames:Object.keys(b.get("sulu_article").types),types:b.get("sulu_article").types,displayTabAll:b.get("sulu_article").displayTabAll};b.set("sulu_article",f);var g=function(){return d.sandbox.sulu.getUserSetting(f.settingsKey)||f.defaultLocale};d.sandbox.mvc.routes.push({route:"articles",callback:function(){return d.sandbox.emit("sulu.router.navigate","articles/"+g())}}),1===f.typeNames.length?(d.sandbox.mvc.routes.push({route:"articles/:locale",callback:function(a){return'
"}}),d.sandbox.mvc.routes.push({route:"articles/:locale/add",callback:function(a,b){return'
"}})):(f.displayTabAll||d.sandbox.mvc.routes.push({route:"articles(/:locale)",callback:function(){return d.sandbox.emit("sulu.router.navigate","articles:"+f.typeNames[0]+"/"+g())}}),f.displayTabAll===!0&&d.sandbox.mvc.routes.push({route:"articles/:locale",callback:function(a){return'
"}}),d.sandbox.mvc.routes.push({route:"articles::type",callback:function(a){return d.sandbox.emit("sulu.router.navigate","articles:"+a+"/"+g())}}),d.sandbox.mvc.routes.push({route:"articles::type/:locale",callback:function(a,b){return'
'}}),d.sandbox.mvc.routes.push({route:"articles/:locale/add::type",callback:function(a,b){return'
'}})),d.sandbox.mvc.routes.push({route:"articles/:locale/edit::id/:content",callback:function(a,b){return'
"}})}}}); \ No newline at end of file +require.config({paths:{suluarticle:"../../suluarticle/dist",suluarticlecss:"../../suluarticle/css","type/article-selection":"../../suluarticle/dist/validation/types/article-selection","services/suluarticle/article-manager":"../../suluarticle/dist/services/manager"}}),define(["underscore","config"],function(a,b){"use strict";var c=function(){var c=b.get("sulu-content").locales,d=[];return a.each(c,function(a){d=d.concat(Object.keys(a))}),d};return{name:"Sulu Article Bundle",initialize:function(d){d.components.addSource("suluarticle","/bundles/suluarticle/dist/components"),d.sandbox.urlManager.setUrl("article","articles/<%= locale %>/edit:<%= id %>/details");var e=c(),f={defaultLocale:e[0],locales:e,languageChanger:a.map(e,function(a){return{id:a,title:a}}),settingsKey:"articleLanguage",typeNames:Object.keys(b.get("sulu_article").types),types:b.get("sulu_article").types,displayTabAll:b.get("sulu_article").displayTabAll};b.set("sulu_article",f);var g=function(){return d.sandbox.sulu.getUserSetting(f.settingsKey)||f.defaultLocale};d.sandbox.mvc.routes.push({route:"articles",callback:function(){return d.sandbox.emit("sulu.router.navigate","articles/"+g())}}),1===f.typeNames.length?(d.sandbox.mvc.routes.push({route:"articles/:locale",callback:function(a){return'
"}}),d.sandbox.mvc.routes.push({route:"articles/:locale/add",callback:function(a,b){return'
"}})):(f.displayTabAll||d.sandbox.mvc.routes.push({route:"articles(/:locale)",callback:function(){return d.sandbox.emit("sulu.router.navigate","articles:"+f.typeNames[0]+"/"+g())}}),f.displayTabAll===!0&&d.sandbox.mvc.routes.push({route:"articles/:locale",callback:function(a){return'
"}}),d.sandbox.mvc.routes.push({route:"articles::type",callback:function(a){return d.sandbox.emit("sulu.router.navigate","articles:"+a+"/"+g())}}),d.sandbox.mvc.routes.push({route:"articles::type/:locale",callback:function(a,b){return'
'}}),d.sandbox.mvc.routes.push({route:"articles/:locale/add::type",callback:function(a,b){return'
'}})),d.sandbox.mvc.routes.push({route:"articles/:locale/edit::id/:content",callback:function(a,b,c){return'
"}})}}}); \ No newline at end of file diff --git a/Resources/public/dist/services/article-manager.js b/Resources/public/dist/services/article-manager.js deleted file mode 100644 index 565bcf949..000000000 --- a/Resources/public/dist/services/article-manager.js +++ /dev/null @@ -1 +0,0 @@ -define(["jquery","services/husky/util"],function(a,b){"use strict";var c="/admin/api/articles";return{save:function(a,d,e){var f="POST",g=c,h=[];return a.id&&(f="PUT",g+="/"+a.id),h.push("locale="+d),e&&h.push("action="+e),b.save(g+"?"+h.join("&"),f,a)},"delete":function(a){return b.save([c,"/",a].join(""),"DELETE")},unpublish:function(a,d){return b.save([c,"/",a,"?action=unpublish&locale="+d].join(""),"POST")},removeDraft:function(a,d){return b.save([c,"/",a,"?action=remove-draft&locale="+d].join(""),"POST")}}}); \ No newline at end of file diff --git a/Resources/public/dist/services/manager.js b/Resources/public/dist/services/manager.js index 57134cf53..7beecf1bb 100644 --- a/Resources/public/dist/services/manager.js +++ b/Resources/public/dist/services/manager.js @@ -1 +1 @@ -define(["jquery","underscore","services/husky/util"],function(a,b,c){var d={url:b.template('/admin/api/articles<% if (typeof id !== "undefined") { %>/<%= id %><% } %>?locale=<%= locale %>')};return{url:d.url,load:function(a,b){return c.load(d.url({id:a,locale:b}))},save:function(a,b,e){return c.save(d.url({id:b,locale:e}),b?"PUT":"POST",a)},remove:function(a,b){return c.save(d.url({id:a,locale:b}),"DELETE")}}}); \ 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 %><% } %>?locale=<%= locale %><% if (typeof action !== "undefined") { %>&action=<%= action %><% } %>')};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 b.save(c.url({id: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")}}}); \ No newline at end of file diff --git a/Resources/public/js/components/articles/edit/details/main.js b/Resources/public/js/components/articles/edit/details/main.js index 8c3d9da48..b8fd4236f 100644 --- a/Resources/public/js/components/articles/edit/details/main.js +++ b/Resources/public/js/components/articles/edit/details/main.js @@ -10,7 +10,7 @@ define([ 'underscore', 'jquery', - 'suluarticle/services/article-manager' + 'services/suluarticle/article-manager' ], function(_, $, ArticleManager) { 'use strict'; @@ -79,8 +79,20 @@ define([ this.data[key] = value; }.bind(this)); - ArticleManager.save(this.data, this.options.locale, action).then(function(response) { + ArticleManager.save(this.data, this.data.id, this.options.locale, action).then(function(response) { this.data = response; + + if (this.ghost && !this.data.type) { + this.sandbox.emit( + 'sulu.router.navigate', + 'articles/' + this.options.locale + '/edit:' + this.data.id + '/details', + true, + true + ); + + return; + } + this.sandbox.emit('sulu.tab.saved', response.id, response); }.bind(this)).fail(function(xhr) { this.sandbox.emit('sulu.article.error', xhr.status, data); @@ -136,7 +148,7 @@ define([ */ loadFormTemplate: function(template) { if (!template) { - template = this.options.config.types[(this.options.type || this.data.type)].default; + template = this.options.config.types[(this.options.type || this.data.articleType)].default; } this.template = template; @@ -190,9 +202,22 @@ define([ options: this.options })); - if (!this.data.id) { + if (!this.data.id || (this.data.type && this.data.type.name === 'ghost')) { // route-path will be generator on post-request this.$find('#routePath').parent().remove(); + this.data.routePath = null; + } + + if (this.data.type && this.data.type.name === 'ghost') { + this.ghost = { + locale: this.data.type.value, + title: this.data.title + }; + + this.data = { + id: this.data.id, + articleType: this.data.articleType + }; } this.createForm(this.data).then(function() { @@ -218,6 +243,10 @@ define([ formObject.initialized.then(function() { this.sandbox.form.setData(this.formId, data).then(function() { + if (!!this.ghost) { + this.sandbox.dom.attr('#title', 'placeholder', this.ghost.locale + ': ' + this.ghost.title); + } + this.sandbox.start(this.$el, {reset: true}).then(function() { this.initSortableBlock(); this.bindFormEvents(); diff --git a/Resources/public/js/components/articles/edit/excerpt/main.js b/Resources/public/js/components/articles/edit/excerpt/main.js index 9d4fc41f6..c85a4bc46 100644 --- a/Resources/public/js/components/articles/edit/excerpt/main.js +++ b/Resources/public/js/components/articles/edit/excerpt/main.js @@ -7,7 +7,9 @@ * with this source code in the file LICENSE. */ -define(['suluarticle/services/article-manager'], function(ArticleManager) { +define([ + 'services/suluarticle/article-manager' +], function(ArticleManager) { 'use strict'; @@ -27,7 +29,7 @@ define(['suluarticle/services/article-manager'], function(ArticleManager) { var content = this.options.data(); content.ext.excerpt = data; - ArticleManager.save(content, this.options.locale, action).then(function(response) { + ArticleManager.save(content, content.id, this.options.locale, action).then(function(response) { this.sandbox.emit('sulu.tab.saved', response.id, response); }.bind(this)).fail(function(xhr) { this.sandbox.emit('sulu.article.error', xhr.status, data); diff --git a/Resources/public/js/components/articles/edit/main.js b/Resources/public/js/components/articles/edit/main.js index b984d7680..39ee09ed9 100644 --- a/Resources/public/js/components/articles/edit/main.js +++ b/Resources/public/js/components/articles/edit/main.js @@ -11,7 +11,7 @@ define([ 'jquery', 'underscore', 'config', - 'suluarticle/services/article-manager', + 'services/suluarticle/article-manager', 'sulusecurity/services/user-manager', 'services/sulupreview/preview', 'sulusecurity/services/security-checker' @@ -92,7 +92,7 @@ define([ buttons.template = { options: { dropdownOptions: { - url: '/admin/articles/templates?type=' + (this.options.type || this.data.type), + url: '/admin/articles/templates?type=' + (this.options.type || this.data.articleType), callback: function(item) { this.template = item.template; this.sandbox.emit('sulu.tab.template-change', item); @@ -152,12 +152,16 @@ define([ preview: this.preview }, componentOptions: { - values: this.data + values: _.defaults(this.data, {type: null}) } }, toolbar: { - buttons: buttons + buttons: buttons, + languageChanger: { + data: this.options.config.languageChanger, + preSelected: this.options.locale + } } }; }, @@ -174,6 +178,7 @@ define([ 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', function(item) { this.sandbox.sulu.saveUserSetting(this.options.config.settingsKey, item.id); @@ -181,6 +186,16 @@ define([ }.bind(this)); }, + /** + * Tab changed event, save the new tab id to `this.options.content`. + * Can be removed when issue #72 is solved: https://github.com/sulu/SuluArticleBundle/issues/72 + * + * @param {Object} item + */ + tabChanged: function(item) { + this.options.content = item.id; + }, + /** * Handles the error based on its error code. * @@ -207,14 +222,14 @@ define([ }, toEdit: function(locale, id) { - this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale) + '/edit:' + (id || this.options.id) + '/details', true, true); + this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale) + '/edit:' + (id || this.options.id) + '/' + (this.options.content || 'details'), true, true); }, toList: function() { if (this.options.config.typeNames.length === 1) { this.sandbox.emit('sulu.router.navigate', 'articles/' + this.options.locale); } else { - this.sandbox.emit('sulu.router.navigate', 'articles:' + (this.options.type || this.data.type) + '/' + this.options.locale); + this.sandbox.emit('sulu.router.navigate', 'articles:' + (this.options.type || this.data.articleType) + '/' + this.options.locale); } }, @@ -222,7 +237,7 @@ define([ if (this.options.config.typeNames.length === 1) { this.sandbox.emit('sulu.router.navigate', 'articles/' + this.options.locale + '/add', true, true); } else { - this.sandbox.emit('sulu.router.navigate', 'articles/' + this.options.locale + '/add:' + (this.options.type || this.data.type), true, true); + this.sandbox.emit('sulu.router.navigate', 'articles/' + this.options.locale + '/add:' + (this.options.type || this.data.articleType), true, true); } }, @@ -245,7 +260,7 @@ define([ this.sandbox.emit('sulu.header.toolbar.item.loading', 'save'); this.sandbox.once('sulu.tab.saved', function(id, data) { - promise.resolve(data); + promise.resolve(_.defaults(data, {type: null})); }.bind(this)); this.sandbox.emit('sulu.tab.save', action); diff --git a/Resources/public/js/components/articles/edit/seo/main.js b/Resources/public/js/components/articles/edit/seo/main.js index c5066db5f..120cd036d 100644 --- a/Resources/public/js/components/articles/edit/seo/main.js +++ b/Resources/public/js/components/articles/edit/seo/main.js @@ -7,7 +7,7 @@ * with this source code in the file LICENSE. */ -define(['suluarticle/services/article-manager'], function(ArticleManager) { +define(['services/suluarticle/article-manager'], function(ArticleManager) { 'use strict'; @@ -29,7 +29,7 @@ define(['suluarticle/services/article-manager'], function(ArticleManager) { var content = this.options.data(); content.ext.seo = data; - ArticleManager.save(content, this.options.locale, action).then(function(response) { + ArticleManager.save(content, content.id, this.options.locale, action).then(function(response) { this.sandbox.emit('sulu.tab.saved', response.id, response); }.bind(this)).fail(function(xhr) { this.sandbox.emit('sulu.article.error', xhr.status, data); diff --git a/Resources/public/js/components/articles/edit/settings/main.js b/Resources/public/js/components/articles/edit/settings/main.js index 80d63a5ff..dbb5046f6 100644 --- a/Resources/public/js/components/articles/edit/settings/main.js +++ b/Resources/public/js/components/articles/edit/settings/main.js @@ -11,7 +11,7 @@ define([ 'underscore', 'jquery', 'sulusecurity/components/users/models/user', - 'suluarticle/services/article-manager', + 'services/suluarticle/article-manager', 'text!/admin/articles/template/settings.html' ], function(_, $, User, ArticleManager, form) { @@ -96,7 +96,7 @@ define([ return item.substr(1); }); - ArticleManager.save(data, this.options.locale, action).then(function(response) { + ArticleManager.save(data, data.id, this.options.locale, action).then(function(response) { this.sandbox.emit('sulu.tab.saved', response.id, response); }.bind(this)).fail(function(xhr) { this.sandbox.emit('sulu.article.error', xhr.status, data); diff --git a/Resources/public/js/components/articles/list/main.js b/Resources/public/js/components/articles/list/main.js index 5df41c056..28083b345 100644 --- a/Resources/public/js/components/articles/list/main.js +++ b/Resources/public/js/components/articles/list/main.js @@ -164,6 +164,7 @@ define(['underscore'], function(_) { searchInstanceName: 'articles', searchFields: ['title'], resultKey: 'articles', + idKey: 'uuid', instanceName: 'articles', actionCallback: function(id) { this.toEdit(id); @@ -172,6 +173,21 @@ define(['underscore'], function(_) { table: { actionIconColumn: 'title', badges: [ + { + column: 'title', + callback: function(item, badge) { + if (!!item.localizationState && + item.localizationState.state === 'ghost' && + item.localizationState.locale !== this.options.language + ) { + badge.title = item.localizationState.locale; + + return badge; + } + + return false; + }.bind(this) + }, { column: 'title', callback: function(item, badge) { @@ -208,7 +224,11 @@ define(['underscore'], function(_) { }, toList: function(locale) { - this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale)); + if (this.options.config.typeNames.length === 1 || !this.options.type) { + this.sandbox.emit('sulu.router.navigate', 'articles/' + (locale || this.options.locale)); + } else { + this.sandbox.emit('sulu.router.navigate', 'articles:' + (this.options.type) + '/' + (locale || this.options.locale)); + } }, deleteItems: function(ids) { @@ -221,6 +241,9 @@ define(['underscore'], function(_) { typeChange: function(item) { var url = this.templates.route({type: item.key, locale: this.options.locale}); + // Save the tab key. Can be removed when issue #72 is solved: + // https://github.com/sulu/SuluArticleBundle/issues/72 + this.options.type = item.key; this.sandbox.emit('husky.datagrid.articles.url.update', {type: item.key}); this.sandbox.emit('sulu.router.navigate', url, false, false); diff --git a/Resources/public/js/main.js b/Resources/public/js/main.js index 60572c255..60d4b9858 100644 --- a/Resources/public/js/main.js +++ b/Resources/public/js/main.js @@ -131,8 +131,8 @@ define(['underscore', 'config'], function(_, Config) { app.sandbox.mvc.routes.push({ route: 'articles/:locale/edit::id/:content', - callback: function(locale, id) { - return '
'; + callback: function(locale, id, content) { + return '
'; } }); } diff --git a/Resources/public/js/services/article-manager.js b/Resources/public/js/services/article-manager.js deleted file mode 100644 index 142d6e065..000000000 --- a/Resources/public/js/services/article-manager.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of the Sulu CMS. - * - * (c) MASSIVE ART WebServices GmbH - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -define(['jquery', 'services/husky/util'], function($, Util) { - 'use strict'; - - var baseUrl = '/admin/api/articles'; - - return { - save: function(data, locale, action) { - var method = 'POST', url = baseUrl, requestParameters = []; - - if (!!data.id) { - method = 'PUT'; - url += '/' + data.id; - } - - requestParameters.push('locale=' + locale); - - if (!!action) { - requestParameters.push('action=' + action); - } - - return Util.save( - url + '?' + requestParameters.join('&'), - method, - data - ); - }, - - delete: function(id) { - return Util.save( - [baseUrl, '/', id].join(''), - 'DELETE' - ); - }, - - unpublish: function(id, locale) { - return Util.save( - [baseUrl, '/', id, '?action=unpublish&locale=' + locale].join(''), - 'POST' - ); - }, - - removeDraft: function(id, locale) { - return Util.save( - [baseUrl, '/', id, '?action=remove-draft&locale=' + locale].join(''), - 'POST' - ); - } - } -}); diff --git a/Resources/public/js/services/manager.js b/Resources/public/js/services/manager.js index 72f34e1a3..a921c8144 100644 --- a/Resources/public/js/services/manager.js +++ b/Resources/public/js/services/manager.js @@ -1,5 +1,5 @@ /* - * This file is part of Sulu. + * This file is part of the Sulu CMS. * * (c) MASSIVE ART WebServices GmbH * @@ -7,25 +7,77 @@ * with this source code in the file LICENSE. */ -define(['jquery', 'underscore', 'services/husky/util'], function($, _, Util) { +define(['jquery', 'services/husky/util'], function($, Util) { + 'use strict'; var templates = { - url: _.template('/admin/api/articles<% if (typeof id !== "undefined") { %>/<%= id %><% } %>?locale=<%= locale %>') + url: _.template( + '/admin/api/articles' + + '<% if (typeof id !== "undefined") { %>/<%= id %><% } %>' + + '?locale=<%= locale %>' + + '<% if (typeof action !== "undefined") { %>&action=<%= action %><% } %>' + ) }; return { url: templates.url, + /** + * Load article. + * + * @param {String} id + * @param {String} locale + */ load: function(id, locale) { return Util.load(templates.url({id: id, locale: locale})); }, - save: function(data, id, locale) { - return Util.save(templates.url({id: id, locale: locale}), !id ? 'POST' : 'PUT', data); + /** + * Save article. + * + * @param {Array} data + * @param {String} id + * @param {String} locale + * @param {String} action + */ + save: function(data, id, locale, action) { + return Util.save(templates.url({id: id, locale: locale, action: action}), !id ? 'POST' : 'PUT', data); }, + /** + * Remove article. + * + * @param {String} id + * @param {String} locale + */ remove: function(id, locale) { return Util.save(templates.url({id: id, locale: locale}), 'DELETE'); + }, + + /** + * Unpublish article. + * + * @param {String} id + * @param {String} locale + */ + unpublish: function(id, locale) { + return Util.save( + templates.url({id: id, locale: locale, action: 'unpublish'}), + 'POST' + ); + }, + + /** + * Remove article. + * + * @param {String} id + * @param {String} locale + */ + removeDraft: function(id, locale) { + return Util.save( + templates.url({id: id, locale: locale, action: 'remove-draft'}), + 'POST' + ); } }; }); diff --git a/Teaser/ArticleTeaserProvider.php b/Teaser/ArticleTeaserProvider.php index e6a935e83..38d9848a8 100644 --- a/Teaser/ArticleTeaserProvider.php +++ b/Teaser/ArticleTeaserProvider.php @@ -13,6 +13,7 @@ use ONGR\ElasticsearchBundle\Service\Manager; use ONGR\ElasticsearchDSL\Query\IdsQuery; +use Sulu\Bundle\ArticleBundle\Metadata\ArticleViewDocumentIdTrait; use Sulu\Bundle\ContentBundle\Teaser\Configuration\TeaserConfiguration; use Sulu\Bundle\ContentBundle\Teaser\Provider\TeaserProviderInterface; use Sulu\Bundle\ContentBundle\Teaser\Teaser; @@ -22,6 +23,8 @@ */ class ArticleTeaserProvider implements TeaserProviderInterface { + use ArticleViewDocumentIdTrait; + /** * @var Manager */ @@ -78,9 +81,11 @@ public function find(array $ids, $locale) return []; } + $articleIds = $this->getViewDocumentIds($ids, $locale); + $repository = $this->searchManager->getRepository($this->articleDocumentClass); $search = $repository->createSearch(); - $search->addQuery(new IdsQuery($ids)); + $search->addQuery(new IdsQuery($articleIds)); $result = []; foreach ($repository->execute($search) as $item) { diff --git a/Tests/Functional/Controller/ArticleControllerTest.php b/Tests/Functional/Controller/ArticleControllerTest.php index 4b31e5e97..fd65f4d19 100644 --- a/Tests/Functional/Controller/ArticleControllerTest.php +++ b/Tests/Functional/Controller/ArticleControllerTest.php @@ -55,7 +55,7 @@ public function testPostWithoutAuthors($title = 'Test-Article', $template = 'def $response = json_decode($client->getResponse()->getContent(), true); $this->assertEquals($title, $response['title']); - $this->assertEquals(self::$typeMap[$template], $response['type']); + $this->assertEquals(self::$typeMap[$template], $response['articleType']); $this->assertEquals($template, $response['template']); $this->assertEquals(new \DateTime('2016-01-01'), new \DateTime($response['authored'])); $this->assertEquals([$this->getTestUser()->getContact()->getId()], $response['authors']); @@ -76,7 +76,7 @@ public function testPost($title = 'Test-Article', $template = 'default') $response = json_decode($client->getResponse()->getContent(), true); $this->assertEquals($title, $response['title']); - $this->assertEquals(self::$typeMap[$template], $response['type']); + $this->assertEquals(self::$typeMap[$template], $response['articleType']); $this->assertEquals($template, $response['template']); $this->assertEquals(new \DateTime('2016-01-01'), new \DateTime($response['authored'])); $this->assertEquals([1, 2, 3], $response['authors']); @@ -99,14 +99,16 @@ public function testGet() } } - public function testPut($title = 'Sulu is awesome') + public function testPut($title = 'Sulu is awesome', $locale = 'de', $article = null) { - $article = $this->testPost(); + if (!$article) { + $article = $this->testPost(); + } $client = $this->createAuthenticatedClient(); $client->request( 'PUT', - '/api/articles/' . $article['id'] . '?locale=de', + '/api/articles/' . $article['id'] . '?locale=' . $locale, ['title' => $title, 'template' => 'default', 'authored' => '2016-01-01', 'authors' => [1, 3]] ); @@ -117,6 +119,83 @@ public function testPut($title = 'Sulu is awesome') $this->assertEquals($title, $response['title']); $this->assertEquals(new \DateTime('2016-01-01'), new \DateTime($response['authored'])); $this->assertEquals([1, 3], $response['authors']); + + return $article; + } + + public function testPutTranslation() + { + $article = $this->testPut('Sulu ist toll', 'de'); + $this->testPut('Sulu is nice', 'en', $article); + } + + public function testGetGhost() + { + $title = 'Sulu ist toll'; + $article = $this->testPut($title, 'de'); + + $client = $this->createAuthenticatedClient(); + $client->request('GET', '/api/articles/' . $article['id'] . '?locale=en'); + + $this->assertHttpStatusCode(200, $client->getResponse()); + + $response = json_decode($client->getResponse()->getContent(), true); + $this->assertNotEquals($article['title'], $response['title']); + $this->assertEquals($title, $response['title']); + $this->assertEquals(new \DateTime('2016-01-01'), new \DateTime($response['authored'])); + $this->assertEquals([1, 3], $response['authors']); + $this->assertEquals(['name' => 'ghost', 'value' => 'de'], $response['type']); + } + + public function testCGetGhost() + { + $this->purgeIndex(); + + $title1 = 'Sulu ist toll - Test 1'; + $article1 = $this->testPut($title1, 'de'); + + $title2 = 'Sulu ist toll - Test 2'; + $article2 = $this->testPut($title2, 'de'); + $title2_EN = $title2 . ' (EN)'; + $this->testPut($title2_EN, 'en', $article2); + + $client = $this->createAuthenticatedClient(); + + // Retrieve articles in 'de'. + $client->request('GET', '/api/articles?locale=de&type=blog'); + $this->assertHttpStatusCode(200, $client->getResponse()); + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals(2, $response['total']); + $this->assertCount(2, $response['_embedded']['articles']); + + $items = array_map( + function ($item) { + return [$item['uuid'], $item['title']]; + }, + $response['_embedded']['articles'] + ); + + $this->assertContains([$article1['id'], $title1], $items); + $this->assertContains([$article2['id'], $title2], $items); + + // Retrieve articles in 'en'. + $client->request('GET', '/api/articles?locale=en&type=blog'); + $this->assertHttpStatusCode(200, $client->getResponse()); + $response = json_decode($client->getResponse()->getContent(), true); + + $this->assertEquals(2, $response['total']); + $this->assertCount(2, $response['_embedded']['articles']); + + $items = array_map( + function ($item) { + return [$item['uuid'], $item['title']]; + }, + $response['_embedded']['articles'] + ); + + $this->assertContains([$article1['id'], $title1], $items); + $this->assertContains([$article2['id'], $title2_EN], $items); } public function testPutExtensions( @@ -195,7 +274,7 @@ public function testPutDifferentTemplate($title = 'Sulu', $description = 'Sulu i $this->assertNotEquals($article['title'], $response['title']); $this->assertEquals($title, $response['title']); $this->assertEquals('simple', $response['template']); - $this->assertEquals(self::$typeMap['simple'], $response['type']); + $this->assertEquals(self::$typeMap['simple'], $response['articleType']); $this->assertEquals($description, $response['description']); } @@ -238,7 +317,7 @@ public function testCGet() $items = array_map( function ($item) { - return [$item['id'], $item['title']]; + return [$item['uuid'], $item['title']]; }, $response['_embedded']['articles'] ); @@ -291,7 +370,7 @@ public function testCGetSearch() $this->assertEquals(1, $response['total']); $this->assertCount(1, $response['_embedded']['articles']); - $this->assertEquals($article2['id'], $response['_embedded']['articles'][0]['id']); + $this->assertEquals($article2['id'], $response['_embedded']['articles'][0]['uuid']); $this->assertEquals($article2['title'], $response['_embedded']['articles'][0]['title']); } @@ -313,7 +392,7 @@ public function testCGetSearchCaseInsensitive() $this->assertEquals(1, $response['total']); $this->assertCount(1, $response['_embedded']['articles']); - $this->assertEquals($article2['id'], $response['_embedded']['articles'][0]['id']); + $this->assertEquals($article2['id'], $response['_embedded']['articles'][0]['uuid']); $this->assertEquals($article2['title'], $response['_embedded']['articles'][0]['title']); } @@ -335,9 +414,9 @@ public function testCGetSort() $this->assertEquals(2, $response['total']); $this->assertCount(2, $response['_embedded']['articles']); - $this->assertEquals($article2['id'], $response['_embedded']['articles'][0]['id']); + $this->assertEquals($article2['id'], $response['_embedded']['articles'][0]['uuid']); $this->assertEquals($article2['title'], $response['_embedded']['articles'][0]['title']); - $this->assertEquals($article1['id'], $response['_embedded']['articles'][1]['id']); + $this->assertEquals($article1['id'], $response['_embedded']['articles'][1]['uuid']); $this->assertEquals($article1['title'], $response['_embedded']['articles'][1]['title']); } @@ -362,7 +441,7 @@ public function testCGetTypes() $items = array_map( function ($item) { - return [$item['id'], $item['title']]; + return [$item['uuid'], $item['title']]; }, $response['_embedded']['articles'] ); @@ -381,7 +460,7 @@ function ($item) { $items = array_map( function ($item) { - return [$item['id'], $item['title']]; + return [$item['uuid'], $item['title']]; }, $response['_embedded']['articles'] ); diff --git a/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php b/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php index 0f8ba22f0..144410403 100644 --- a/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php +++ b/Tests/Unit/Document/Subscriber/ArticleSubscriberTest.php @@ -19,6 +19,7 @@ use Sulu\Bundle\RouteBundle\Entity\RouteRepositoryInterface; use Sulu\Bundle\RouteBundle\Manager\RouteManagerInterface; use Sulu\Bundle\RouteBundle\Model\RouteInterface; +use Sulu\Component\DocumentManager\DocumentManagerInterface; use Sulu\Component\DocumentManager\Event\HydrateEvent; use Sulu\Component\DocumentManager\Event\PersistEvent; @@ -49,6 +50,11 @@ class ArticleSubscriberTest extends \PHPUnit_Framework_TestCase */ private $entityManager; + /** + * @var DocumentManagerInterface + */ + private $documentManager; + /** * @var ArticleSubscriber */ @@ -66,6 +72,7 @@ protected function setUp() $this->routeManager = $this->prophesize(RouteManagerInterface::class); $this->routeRepository = $this->prophesize(RouteRepositoryInterface::class); $this->entityManager = $this->prophesize(EntityManagerInterface::class); + $this->documentManager = $this->prophesize(DocumentManagerInterface::class); $this->document = $this->prophesize(ArticleDocument::class); @@ -74,7 +81,8 @@ protected function setUp() $this->liveIndexer->reveal(), $this->routeManager->reveal(), $this->routeRepository->reveal(), - $this->entityManager->reveal() + $this->entityManager->reveal(), + $this->documentManager->reveal() ); } @@ -97,6 +105,7 @@ public function testHandleHydrate() $route = $this->prophesize(RouteInterface::class); $this->document->getRoutePath()->willReturn('/test'); $this->document->setRoute($route->reveal())->shouldBeCalled(); + $this->document->getOriginalLocale()->willReturn('de'); $this->routeRepository->findByPath('/test', 'de')->willReturn($route->reveal()); $this->articleSubscriber->handleHydrate($this->prophesizeEvent(HydrateEvent::class)); diff --git a/Tests/app/Resources/webspaces/sulu.io.xml b/Tests/app/Resources/webspaces/sulu.io.xml index 5f1b6f44e..90916716b 100644 --- a/Tests/app/Resources/webspaces/sulu.io.xml +++ b/Tests/app/Resources/webspaces/sulu.io.xml @@ -8,6 +8,7 @@ + default diff --git a/Tests/travis.php.ini b/Tests/travis.php.ini index ffbecf14b..92a5ffdcc 100644 --- a/Tests/travis.php.ini +++ b/Tests/travis.php.ini @@ -1 +1 @@ -memory_limit = 1536M +memory_limit = 2048M diff --git a/UPGRADE.md b/UPGRADE.md new file mode 100644 index 000000000..9bda29eb8 --- /dev/null +++ b/UPGRADE.md @@ -0,0 +1,7 @@ +# Upgrade + +## 0.2.0 + +Reindex elastic search indexes: +* bin/adminconsole sulu:article:index-rebuild ###LOCALE### -live +* bin/adminconsole sulu:article:index-rebuild ###LOCALE### diff --git a/composer.json b/composer.json index c5b5a8f50..fd848eae5 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "symfony/monolog-bundle": "2.4.*", "doctrine/doctrine-bundle": "1.4.*", "jackalope/jackalope-doctrine-dbal": "^1.2.5", - "phpunit/phpunit": ">=4.8", + "phpunit/phpunit": "^4.8 || ^5.0", "php-task/task-bundle": "@dev", "php-task/php-task": "@dev"