├── Command
├── ExportCommand.php
└── ImportCommand.php
├── Controller
├── ContentController.php
├── Crud
│ ├── ContentController.php
│ ├── PageController.php
│ └── ScopeController.php
├── PageController.php
└── ToolsController.php
├── DependencyInjection
├── Compiler
│ ├── ElementPass.php
│ └── FormThemePass.php
├── Configuration.php
└── SherlockodeAdvancedContentExtension.php
├── Doctrine
├── MigrationHelper.php
├── MigrationHelperAwareInterface.php
└── MigrationHelperInterface.php
├── Element
├── AbstractElement.php
└── ElementInterface.php
├── Event
├── AcbFilePostValidate.php
└── AcbFilePreSubmitEvent.php
├── EventListener
├── AcbFileListener.php
├── ContentListener.php
├── PageListener.php
└── VersionListener.php
├── Exception
└── InvalidElementException.php
├── Export
├── ContentExport.php
├── ElementExport.php
├── PageExport.php
└── ScopeExport.php
├── FieldType
├── AbstractFieldType.php
├── AbstractInputType.php
├── Content.php
├── FieldTypeInterface.php
├── File.php
├── Iframe.php
├── Image.php
├── ImageCarousel.php
├── Link.php
├── RelativeLink.php
├── Separator.php
├── Text.php
├── TextArea.php
├── Title.php
├── Video.php
└── Wysiwyg.php
├── Form
├── DataTransformer
│ └── StringToEntity.php
└── Type
│ ├── AcbContentType.php
│ ├── AcbFileType.php
│ ├── ColumnType.php
│ ├── ContentDataType.php
│ ├── ContentType.php
│ ├── ElementAdvancedType.php
│ ├── ElementDesignType.php
│ ├── ElementHideOnType.php
│ ├── ElementType.php
│ ├── ElementsType.php
│ ├── EntityType.php
│ ├── ExportType.php
│ ├── ImageCarouselType.php
│ ├── ImageType.php
│ ├── ImportType.php
│ ├── LinkType.php
│ ├── PageMetaType.php
│ ├── PageType.php
│ ├── PageTypeType.php
│ ├── PictureEntryType.php
│ ├── PictureType.php
│ ├── RepeatedChildWrappedType.php
│ ├── RepeaterType.php
│ ├── RowType.php
│ ├── ScopeChoiceType.php
│ ├── ScopeType.php
│ ├── TitleType.php
│ ├── VideoType.php
│ └── WysiwygType.php
├── Import
├── AbstractImport.php
├── ContentImport.php
├── ElementImport.php
├── ImportResult.php
└── PageImport.php
├── LICENSE
├── LayoutType
├── AbstractLayoutType.php
├── Column.php
├── LayoutTypeInterface.php
└── Row.php
├── Manager
├── ConfigurationManager.php
├── ContentManager.php
├── ElementManager.php
├── ExportManager.php
├── ImportManager.php
├── MimeTypeManager.php
├── PageManager.php
├── UploadManager.php
├── UrlBuilderManager.php
└── VersionManager.php
├── Model
├── Content.php
├── ContentInterface.php
├── ContentVersion.php
├── ContentVersionInterface.php
├── LocaleScope.php
├── LocaleScopeInterface.php
├── Page.php
├── PageInterface.php
├── PageMeta.php
├── PageMetaInterface.php
├── PageMetaVersion.php
├── PageMetaVersionInterface.php
├── PageType.php
├── PageTypeInterface.php
├── PageVersion.php
├── PageVersionInterface.php
├── ScopableInterface.php
├── Scope.php
├── ScopeInterface.php
├── Version.php
└── VersionInterface.php
├── Naming
├── ClientOriginalNamer.php
├── NamerInterface.php
└── UniqueNamer.php
├── README.md
├── Resources
├── config
│ ├── controllers.xml
│ ├── doctrine-mapping
│ │ ├── Content.orm.xml
│ │ ├── ContentVersion.orm.xml
│ │ ├── Page.orm.xml
│ │ ├── PageMetaVersion.orm.xml
│ │ ├── PageType.orm.xml
│ │ └── PageVersion.orm.xml
│ ├── field_types.xml
│ ├── form.xml
│ ├── import_export.xml
│ ├── layout_types.xml
│ ├── listeners.xml
│ ├── mime_type.xml
│ ├── routing
│ │ ├── all.xml
│ │ ├── base.xml
│ │ ├── content.xml
│ │ ├── content_crud.xml
│ │ ├── page.xml
│ │ ├── page_crud.xml
│ │ ├── scope_crud.xml
│ │ └── tools.xml
│ └── services.xml
├── doc
│ ├── custom_field_type.md
│ ├── data_migration.md
│ ├── elements.md
│ ├── entities.md
│ ├── export.md
│ ├── field_types.md
│ ├── import.md
│ ├── import
│ │ ├── Content
│ │ │ └── standalone_content.yaml
│ │ ├── Page
│ │ │ └── custom_page.yaml
│ │ └── files
│ │ │ └── background.png
│ ├── tools.md
│ └── usage.md
├── js
│ ├── acb-collection.js
│ ├── acb-notification.js
│ ├── acb-slide-collection.js
│ ├── content.js
│ ├── export.js
│ ├── form.js
│ ├── history.js
│ ├── index.js
│ ├── layout.js
│ ├── slide.js
│ ├── slug.js
│ └── utils.js
├── public
│ ├── css
│ │ ├── acb.scss
│ │ ├── advanced-content.css
│ │ ├── field-list.scss
│ │ ├── field.scss
│ │ ├── history.scss
│ │ ├── index.scss
│ │ ├── page.scss
│ │ ├── slide.scss
│ │ └── tools.scss
│ └── js
│ │ └── speakingurl.min.js
├── translations
│ ├── AdvancedContentBundle.en.yml
│ └── AdvancedContentBundle.fr.yml
└── views
│ ├── Common
│ └── Macros
│ │ ├── classes.html.twig
│ │ ├── collapse.html.twig
│ │ ├── date.html.twig
│ │ └── tabs.html.twig
│ ├── Content
│ ├── _button_submit_slide.html.twig
│ ├── _edit_element.html.twig
│ ├── _field_form.html.twig
│ ├── _field_preview.html.twig
│ ├── _form.html.twig
│ ├── _select_new_field.html.twig
│ ├── create_content.html.twig
│ ├── edit_content.html.twig
│ ├── list.html.twig
│ └── show.html.twig
│ ├── Field
│ ├── front
│ │ ├── content.html.twig
│ │ ├── iframe.html.twig
│ │ ├── image.html.twig
│ │ ├── image_carousel.html.twig
│ │ ├── link.html.twig
│ │ ├── separator.html.twig
│ │ ├── text.html.twig
│ │ ├── textarea.html.twig
│ │ ├── title.html.twig
│ │ ├── video.html.twig
│ │ └── wysiwyg.html.twig
│ └── preview
│ │ ├── content.html.twig
│ │ ├── iframe.html.twig
│ │ ├── image.html.twig
│ │ ├── image_carousel.html.twig
│ │ ├── link.html.twig
│ │ ├── no_preview.html.twig
│ │ ├── separator.html.twig
│ │ ├── text.html.twig
│ │ ├── textarea.html.twig
│ │ ├── title.html.twig
│ │ ├── video.html.twig
│ │ └── wysiwyg.html.twig
│ ├── Form
│ ├── base_theme.html.twig
│ ├── common.html.twig
│ ├── content.html.twig
│ └── theme.html.twig
│ ├── Layout
│ ├── front
│ │ ├── column.html.twig
│ │ └── row.html.twig
│ └── preview
│ │ ├── column.html.twig
│ │ └── row.html.twig
│ ├── Page
│ ├── _form.html.twig
│ ├── create.html.twig
│ ├── edit.html.twig
│ └── list.html.twig
│ ├── Tools
│ ├── _pageTypes.html.twig
│ ├── _scopes.html.twig
│ └── index.html.twig
│ ├── Version
│ ├── _line.html.twig
│ ├── _list.html.twig
│ ├── content_list.html.twig
│ └── page_list.html.twig
│ └── layout.html.twig
├── Scope
├── LocaleScopeHandler.php
├── ScopeHandler.php
└── ScopeHandlerInterface.php
├── SherlockodeAdvancedContentBundle.php
├── Slug
├── SlugProvider.php
└── SlugProviderInterface.php
├── Twig
└── Extension
│ ├── ContentExtension.php
│ └── ScopeExtension.php
├── User
├── AnonymousUserProvider.php
└── UserProviderInterface.php
└── composer.json
/Controller/Crud/ScopeController.php:
--------------------------------------------------------------------------------
1 | em = $em;
34 | $this->configurationManager = $configurationManager;
35 | }
36 |
37 | /**
38 | * @param int $id
39 | *
40 | * @return Response
41 | */
42 | public function deleteAction($id)
43 | {
44 | $scope = $this->em->getRepository($this->configurationManager->getEntityClass('scope'))->find($id);
45 |
46 | if (!$scope instanceof ScopeInterface) {
47 | throw $this->createNotFoundException(
48 | sprintf('Entity %s with ID %s not found', $this->configurationManager->getEntityClass('scope'), $id)
49 | );
50 | }
51 |
52 | $this->em->remove($scope);
53 | $this->em->flush();
54 |
55 | return $this->redirectToRoute('sherlockode_acb_tools_index');
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/DependencyInjection/Compiler/ElementPass.php:
--------------------------------------------------------------------------------
1 | has('sherlockode_advanced_content.element_manager')) {
14 | return;
15 | }
16 | $definition = $container->findDefinition('sherlockode_advanced_content.element_manager');
17 | $taggedServices = $container->findTaggedServiceIds('sherlockode_advanced_content.fieldtype');
18 | foreach ($taggedServices as $id => $tags) {
19 | $definition->addMethodCall('addFieldType', [new Reference($id)]);
20 | }
21 |
22 | $taggedServices = $container->findTaggedServiceIds('sherlockode_advanced_content.layouttype');
23 | foreach ($taggedServices as $id => $tags) {
24 | $definition->addMethodCall('addLayoutType', [new Reference($id)]);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/DependencyInjection/Compiler/FormThemePass.php:
--------------------------------------------------------------------------------
1 | has('twig')) {
14 | return;
15 | }
16 |
17 | $theme = 'bootstrap_5_layout.html.twig';
18 | if (Kernel::VERSION_ID < 50300) {
19 | $theme = 'bootstrap_4_layout.html.twig';
20 | }
21 | $container->getDefinition('sherlockode_advanced_content.content_extension')->setArgument('$baseFormTheme', $theme);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Doctrine/MigrationHelperAwareInterface.php:
--------------------------------------------------------------------------------
1 | getDefaultIconClass();
13 | }
14 |
15 | /**
16 | * @return string
17 | */
18 | protected function getDefaultIconClass()
19 | {
20 | return 'fa-solid fa-gear';
21 | }
22 |
23 | /**
24 | * Add element's field(s) to content form
25 | *
26 | * @param FormBuilderInterface $builder
27 | *
28 | * @return void
29 | */
30 | public function buildContentElement(FormBuilderInterface $builder)
31 | {
32 | $builder->add('elementType', HiddenType::class);
33 | $builder->add('position', HiddenType::class);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Element/ElementInterface.php:
--------------------------------------------------------------------------------
1 | uploadedFile = $uploadedFile;
29 | $this->fileName = $fileName;
30 | }
31 |
32 | /**
33 | * @return UploadedFile
34 | */
35 | public function getUploadedFile(): UploadedFile
36 | {
37 | return $this->uploadedFile;
38 | }
39 |
40 | /**
41 | * @return string
42 | */
43 | public function getFileName(): string
44 | {
45 | return $this->fileName;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/EventListener/AcbFileListener.php:
--------------------------------------------------------------------------------
1 | uploadManager = $uploadManager;
31 | }
32 |
33 | /**
34 | * @return string[]
35 | */
36 | public static function getSubscribedEvents(): array
37 | {
38 | return [
39 | AcbFilePreSubmitEvent::NAME => 'onPreSubmit',
40 | AcbFilePostValidate::NAME => 'onPostValidate',
41 | ];
42 | }
43 |
44 | /**
45 | * @param AcbFilePreSubmitEvent $event
46 | *
47 | * @return void
48 | */
49 | public function onPreSubmit(AcbFilePreSubmitEvent $event): void
50 | {
51 | $this->files = array_merge($this->files, [['file' => $event->getUploadedFile(), 'fileName' => $event->getFileName()]]);
52 |
53 | }
54 |
55 | /**
56 | * @return void
57 | */
58 | public function onPostValidate(): void
59 | {
60 | foreach ($this->files as $file) {
61 | if (null !== $file['file'] ?? null && null !== $file['fileName'] ?? null) {
62 | $this->uploadManager->upload($file['file'], $file['fileName']);
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/EventListener/ContentListener.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
30 | $this->versionManager = $versionManager;
31 | }
32 |
33 | /**
34 | * @param LifecycleEventArgs $args
35 | */
36 | public function postLoad(LifecycleEventArgs $args)
37 | {
38 | $entity = $args->getEntity();
39 |
40 | if (!$entity instanceof ContentInterface) {
41 | return;
42 | }
43 | if ($entity->getPage() !== null) {
44 | return;
45 | }
46 |
47 | $entity->setData($this->versionManager->getContentData($entity), false);
48 | }
49 |
50 | /**
51 | * @param OnFlushEventArgs $args
52 | */
53 | public function onFlush(OnFlushEventArgs $args)
54 | {
55 | $em = $args->getEntityManager();
56 | $uow = $em->getUnitOfWork();
57 |
58 | $entities = [
59 | ...$uow->getScheduledEntityInsertions(),
60 | ...$uow->getScheduledEntityUpdates()
61 | ];
62 |
63 | $contentVersionClassMetadata = $em->getClassMetadata($this->configurationManager->getEntityClass('content_version'));
64 | $contentClassMetadata = $em->getClassMetadata($this->configurationManager->getEntityClass('content'));
65 | foreach ($entities as $entity) {
66 | if (!$entity instanceof ContentInterface) {
67 | continue;
68 | }
69 | if ($entity->getPage() !== null) {
70 | continue;
71 | }
72 |
73 | $contentVersion = $this->versionManager->getNewContentVersion($entity);
74 | $em->persist($contentVersion);
75 | $uow->computeChangeSet($contentVersionClassMetadata, $contentVersion);
76 | $uow->recomputeSingleEntityChangeSet($contentClassMetadata, $entity);
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/EventListener/VersionListener.php:
--------------------------------------------------------------------------------
1 | getEntity();
19 |
20 | if (!$entity instanceof VersionInterface || !$entity->isAutoSave()) {
21 | return;
22 | }
23 |
24 | if ($entity instanceof ContentVersionInterface && $entity->getContent()->getPage() === null) {
25 | $versions = $entity->getContent()->getVersions();
26 | } elseif ($entity instanceof PageVersionInterface) {
27 | $versions = $entity->getPage()->getVersions();
28 | } else {
29 | return;
30 | }
31 |
32 | $count = 0;
33 | foreach ($versions as $version) {
34 | if (!$version->isAutoSave()) {
35 | continue;
36 | }
37 | if ($version->getUserId() !== $entity->getUserId()) {
38 | continue;
39 | }
40 | if ($version->getCreatedAt() < $entity->getCreatedAt()) {
41 | $count++;
42 | }
43 | if ($count >= 10) {
44 | // Keep only the last 10 drafts by same user
45 | $args->getEntityManager()->remove($version);
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Exception/InvalidElementException.php:
--------------------------------------------------------------------------------
1 | elementExport = $elementExport;
26 | $this->scopeExport = $scopeExport;
27 | }
28 |
29 | /**
30 | * @param ContentInterface $content
31 | *
32 | * @return array
33 | */
34 | public function exportData(ContentInterface $content)
35 | {
36 | $data = [];
37 | $data['name'] = $content->getName();
38 | $data = array_merge($data, $this->scopeExport->getEntityScopes($content));
39 |
40 | $elements = $content->getData() ?? [];
41 | $data['children'] = $this->exportElements($elements);
42 |
43 | $data = [
44 | 'contents' => [
45 | $content->getSlug() => $data,
46 | ],
47 | ];
48 |
49 | return $data;
50 | }
51 |
52 | /**
53 | * @param array|array[] $elements
54 | *
55 | * @return array
56 | */
57 | public function exportElements($elements)
58 | {
59 | if (!is_array($elements)) {
60 | return [];
61 | }
62 | if (count($elements) === 0) {
63 | return [];
64 | }
65 |
66 | $data = [];
67 | foreach ($elements as $element) {
68 | $data[] = $this->elementExport->getElementExportData($element);
69 | }
70 |
71 | return $data;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Export/PageExport.php:
--------------------------------------------------------------------------------
1 | scopeExport = $scopeExport;
26 | }
27 |
28 | /**
29 | * @param PageInterface $page
30 | *
31 | * @return array
32 | */
33 | public function exportData(PageInterface $page)
34 | {
35 | $data = [];
36 | $data['status'] = $page->getStatus();
37 | if ($page->getPageType() instanceof PageTypeInterface) {
38 | $data['pageType'] = $page->getPageType()->getName();
39 | }
40 | $data = array_merge($data, $this->scopeExport->getEntityScopes($page));
41 | if ($page->getContent() !== null) {
42 | $data['content'] = $this->contentExport->exportElements($page->getContent()->getData());
43 | }
44 |
45 | $pageMeta = $page->getPageMeta();
46 | if ($pageMeta !== null) {
47 | $data['meta'] = [
48 | 'title' => $pageMeta->getTitle(),
49 | 'slug' => $pageMeta->getSlug(),
50 | 'meta_title' => $pageMeta->getMetaTitle(),
51 | 'meta_description' => $pageMeta->getMetaDescription(),
52 | ];
53 | }
54 |
55 | $data = [
56 | 'pages' => [
57 | $page->getPageIdentifier() => $data,
58 | ],
59 | ];
60 |
61 | return $data;
62 | }
63 |
64 | /**
65 | * @param ContentExport $contentExport
66 | */
67 | public function setContentExport(ContentExport $contentExport)
68 | {
69 | $this->contentExport = $contentExport;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Export/ScopeExport.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
30 | $this->scopeHandler = $scopeHandler;
31 | }
32 |
33 | /**
34 | * @param ScopableInterface $entity
35 | *
36 | * @return array
37 | */
38 | public function getEntityScopes(ScopableInterface $entity): array
39 | {
40 | if (!$this->configurationManager->isScopesEnabled()) {
41 | return [];
42 | }
43 |
44 | $scopes = [];
45 | foreach ($entity->getScopes() as $scope) {
46 | $scopes[] = $this->scopeHandler->getDataFromScope($scope);
47 | }
48 |
49 | return [
50 | 'scopes' => $scopes,
51 | ];
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/FieldType/AbstractInputType.php:
--------------------------------------------------------------------------------
1 | $fieldOptions['minLength']]);
26 | }
27 | if (isset($fieldOptions['maxLength'])) {
28 | $formFieldOptions['constraints'][] = new Length(['max' => $fieldOptions['maxLength']]);
29 | }
30 |
31 | return $formFieldOptions;
32 | }
33 |
34 | /**
35 | * @return string
36 | */
37 | public function getFieldGroup()
38 | {
39 | return 'simple';
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/FieldType/Content.php:
--------------------------------------------------------------------------------
1 | scopeHandler = $scopeHandler;
22 | }
23 |
24 | /**
25 | * @return string
26 | */
27 | public function getFormFieldType()
28 | {
29 | return AcbContentType::class;
30 | }
31 |
32 | /**
33 | * Get field's code
34 | *
35 | * @return string
36 | */
37 | public function getCode()
38 | {
39 | return 'content';
40 | }
41 |
42 | /**
43 | * @param mixed $element
44 | *
45 | * @return array
46 | */
47 | public function getRawValue($element)
48 | {
49 | $element['entity'] = null;
50 |
51 | $contentSlug = $element['content'] ?? null;
52 | if ($contentSlug === null) {
53 | return $element;
54 | }
55 |
56 | $element['entity'] = $this->scopeHandler->getEntityForCurrentScope('content', ['slug' => $contentSlug]);
57 |
58 | return $element;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/FieldType/FieldTypeInterface.php:
--------------------------------------------------------------------------------
1 | urlBuilderManager = $urlBuilderManager;
21 | }
22 |
23 | /**
24 | * @return string
25 | */
26 | public function getFormFieldType()
27 | {
28 | return AcbFileType::class;
29 | }
30 |
31 | protected function getDefaultIconClass()
32 | {
33 | return 'fa-solid fa-paperclip';
34 | }
35 |
36 | /**
37 | * Get field's code
38 | *
39 | * @return string
40 | */
41 | public function getCode()
42 | {
43 | return 'file';
44 | }
45 |
46 | /**
47 | * @param array $value
48 | *
49 | * @return string
50 | */
51 | protected function getFilename($value)
52 | {
53 | return $this->urlBuilderManager->getFileUrl($value['src'] ?? '');
54 | }
55 |
56 | /**
57 | * @param mixed $element
58 | *
59 | * @return mixed
60 | */
61 | public function getRawValue($element)
62 | {
63 | $element['url'] = $this->getFilename($element);
64 |
65 | if (isset($element['delete'])) {
66 | unset($element['delete']);
67 | }
68 |
69 | return $element;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/FieldType/Iframe.php:
--------------------------------------------------------------------------------
1 | get('value')
32 | ->add('src', UrlType::class, ['label' => 'field_type.iframe.src'])
33 | ->add('width', IntegerType::class, ['required' => false, 'label' => 'field_type.iframe.width'])
34 | ->add('height', IntegerType::class, ['required' => false, 'label' => 'field_type.iframe.height'])
35 | ;
36 | }
37 |
38 | /**
39 | * Get field's code
40 | *
41 | * @return string
42 | */
43 | public function getCode()
44 | {
45 | return 'iframe';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/FieldType/Image.php:
--------------------------------------------------------------------------------
1 | $source) {
38 | $element['sources'][$key] = parent::getRawValue($source);
39 | }
40 | }
41 |
42 | return $element;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/FieldType/ImageCarousel.php:
--------------------------------------------------------------------------------
1 | $imageData) {
41 | $url = $this->getFilename($imageData);
42 | if (empty($url)) {
43 | unset($element['images'][$key]);
44 | continue;
45 | }
46 |
47 | $imageData['url'] = $url;
48 | if (isset($imageData['delete'])) {
49 | unset($imageData['delete']);
50 | }
51 | $element['images'][$key] = $imageData;
52 | }
53 |
54 | return $element;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/FieldType/Link.php:
--------------------------------------------------------------------------------
1 | $this->getUrlFormType(),
32 | ];
33 | }
34 |
35 | /**
36 | * @return string
37 | */
38 | protected function getUrlFormType()
39 | {
40 | return UrlType::class;
41 | }
42 |
43 | /**
44 | * Get field's code
45 | *
46 | * @return string
47 | */
48 | public function getCode()
49 | {
50 | return 'link';
51 | }
52 |
53 | /**
54 | * @param mixed $element
55 | *
56 | * @return mixed
57 | */
58 | public function getRawValue($element)
59 | {
60 | $url = $this->getUrlValue($element);
61 |
62 | if (!$url) {
63 | return null;
64 | }
65 |
66 | $element['url'] = $url;
67 |
68 | return $element;
69 | }
70 |
71 | /**
72 | * @param array $value
73 | *
74 | * @return string
75 | */
76 | protected function getUrlValue($value)
77 | {
78 | return $value['url'] ?? '';
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/FieldType/RelativeLink.php:
--------------------------------------------------------------------------------
1 | urlBuilderManager = $urlBuilderManager;
21 | }
22 |
23 | public function getPreviewTemplate()
24 | {
25 | return '@SherlockodeAdvancedContent/Field/preview/link.html.twig';
26 | }
27 |
28 | /**
29 | * Get field's code
30 | *
31 | * @return string
32 | */
33 | public function getCode()
34 | {
35 | return 'relative_link';
36 | }
37 |
38 | /**
39 | * @return string
40 | */
41 | protected function getUrlFormType()
42 | {
43 | return TextType::class;
44 | }
45 |
46 | /**
47 | * @param array $value
48 | *
49 | * @return string
50 | */
51 | protected function getUrlValue($value)
52 | {
53 | return $this->urlBuilderManager->getFullUrl($value['url'] ?? '');
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/FieldType/Separator.php:
--------------------------------------------------------------------------------
1 | $fieldOptions['nbRows']];
21 | }
22 |
23 | return $formFieldOptions;
24 | }
25 |
26 | /**
27 | * @return string
28 | */
29 | public function getFormFieldType()
30 | {
31 | return TextareaType::class;
32 | }
33 |
34 | /**
35 | * Get field's code
36 | *
37 | * @return string
38 | */
39 | public function getCode()
40 | {
41 | return 'textarea';
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/FieldType/Title.php:
--------------------------------------------------------------------------------
1 | em = $em;
34 | $this->entityClass = $entityClass;
35 | $this->identifierField = $identifierField;
36 | }
37 |
38 | /**
39 | * Transforms a string into an entity
40 | *
41 | * @param string $valueAsString
42 | *
43 | * @return object|null
44 | */
45 | public function transform($valueAsString)
46 | {
47 | if (empty($valueAsString)) {
48 | return null;
49 | }
50 |
51 | $entity = $this->em->getRepository($this->entityClass)->findOneBy([
52 | $this->identifierField => $valueAsString,
53 | ]);
54 |
55 | return $entity;
56 | }
57 |
58 | /**
59 | * Transforms an entity into a string
60 | *
61 | * @param object $entity
62 | *
63 | * @return string
64 | */
65 | public function reverseTransform($entity)
66 | {
67 | if (empty($entity)) {
68 | return null;
69 | }
70 |
71 | $propertyAccessor = PropertyAccess::createPropertyAccessor();
72 |
73 | return $propertyAccessor->getValue($entity, $this->identifierField);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Form/Type/AcbContentType.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
30 | $this->em = $em;
31 | }
32 |
33 | /**
34 | * @param FormBuilderInterface $builder
35 | * @param array $options
36 | */
37 | public function buildForm(FormBuilderInterface $builder, array $options)
38 | {
39 | $contents = $this->em->getRepository($this->configurationManager->getEntityClass('content'))->findBy([
40 | 'page' => null,
41 | ], ['slug' => 'ASC']);
42 | $slugs = [];
43 | foreach ($contents as $content) {
44 | $slugs[$content->getSlug()] = $content->getSlug();
45 | }
46 |
47 | $builder
48 | ->add('content', ChoiceType::class, [
49 | 'label' => false,
50 | 'choices' => $slugs,
51 | ])
52 | ;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Form/Type/ContentDataType.php:
--------------------------------------------------------------------------------
1 | add('class', TextType::class, [
15 | 'label' => 'configuration.advanced.class',
16 | 'required' => false,
17 | ])
18 | ->add('id', TextType::class, [
19 | 'label' => 'configuration.advanced.id',
20 | 'required' => false,
21 | ])
22 | ->add('hide_on', ElementHideOnType::class, [
23 | 'label' => 'configuration.advanced.hide_on',
24 | 'required' => false,
25 | ])
26 | ;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Form/Type/ElementHideOnType.php:
--------------------------------------------------------------------------------
1 | setDefaults([
25 | 'choices' => [
26 | 'responsive.devices.mobile_portrait' => 'xs',
27 | 'responsive.devices.mobile_landscape' => 'sm',
28 | 'responsive.devices.tablet_portrait' => 'md',
29 | 'responsive.devices.tablet_landscape' => 'lg',
30 | 'responsive.devices.desktop' => 'xl',
31 | ],
32 | 'multiple' => true,
33 | 'expanded' => true,
34 | ]);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Form/Type/ElementType.php:
--------------------------------------------------------------------------------
1 | buildContentElement($builder);
23 | $builder->add('extra', FormType::class, [
24 | 'label' => false,
25 | ]);
26 | $builder->get('extra')->add('advanced', ElementAdvancedType::class, [
27 | 'label' => false,
28 | ]);
29 | $builder->get('extra')->add('design', ElementDesignType::class, [
30 | 'label' => false,
31 | ]);
32 | }
33 |
34 | public function buildView(FormView $view, FormInterface $form, array $options)
35 | {
36 | $view->vars['panel_label'] = $options['element_type']->getFormFieldLabel();
37 | $view->vars['field_icon'] = $options['element_type']->getIconClass();
38 | }
39 |
40 | /**
41 | * @param OptionsResolver $resolver
42 | */
43 | public function configureOptions(OptionsResolver $resolver)
44 | {
45 | $resolver->setRequired(['element_type']);
46 | $resolver->setDefaults([
47 | 'translation_domain' => 'AdvancedContentBundle',
48 | ]);
49 | }
50 |
51 | public function getBlockPrefix()
52 | {
53 | return 'acb_element';
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Form/Type/EntityType.php:
--------------------------------------------------------------------------------
1 | addModelTransformer(new StringToEntity($options['em'], $options['class'], 'id'));
15 | }
16 |
17 | public function getParent()
18 | {
19 | return SymfonyEntityType::class;
20 | }
21 |
22 | public function getBlockPrefix()
23 | {
24 | return 'acb_entity';
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Form/Type/ImageCarouselType.php:
--------------------------------------------------------------------------------
1 | add('images', RepeaterType::class, [
16 | 'entry_type' => ImageType::class,
17 | 'label' => 'field_type.image_carousel.images',
18 | 'constraints' => [
19 | new Count(null, 1, null, null, null, null, null, null, $options['validation_groups']),
20 | ],
21 | 'error_bubbling' => false,
22 | ])
23 | ->add('displayArrows', CheckboxType::class, [
24 | 'label' => 'field_type.image_carousel.display_arrows',
25 | 'required' => false,
26 | ])
27 | ->add('displayPagination', CheckboxType::class, [
28 | 'label' => 'field_type.image_carousel.display_pagination',
29 | 'required' => false,
30 | ])
31 | ;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Form/Type/ImageType.php:
--------------------------------------------------------------------------------
1 | mimeTypeManager = $mimeTypeManager;
24 | }
25 |
26 | public function buildForm(FormBuilderInterface $builder, array $options)
27 | {
28 | $builder->remove('title');
29 | $builder
30 | ->add('alt', TextType::class, [
31 | 'label' => 'field_type.image.alt',
32 | 'required' => false,
33 | ])
34 | ;
35 | }
36 |
37 | /**
38 | * @return string
39 | */
40 | public function getParent()
41 | {
42 | return AcbFileType::class;
43 | }
44 |
45 | /**
46 | * @return string
47 | */
48 | public function getBlockPrefix()
49 | {
50 | return 'acb_image';
51 | }
52 |
53 | /**
54 | * @param OptionsResolver $resolver
55 | */
56 | public function configureOptions(OptionsResolver $resolver)
57 | {
58 | $resolver->setDefaults([
59 | 'translation_domain' => 'AdvancedContentBundle',
60 | 'mime_types' => array_flip(array_map('ucfirst', $this->mimeTypeManager->getImageMimeTypesChoices())),
61 | 'mime_types_constraint' => $this->mimeTypeManager->getMimeTypesByCode(MimeTypeManager::MIME_TYPE_IMAGE),
62 | ]);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Form/Type/ImportType.php:
--------------------------------------------------------------------------------
1 | add('file', FileType::class, ['label' => 'tools.import.file'])
16 | ;
17 | }
18 |
19 | public function configureOptions(OptionsResolver $resolver)
20 | {
21 | $resolver->setDefaults([
22 | 'translation_domain' => 'AdvancedContentBundle',
23 | ]);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Form/Type/LinkType.php:
--------------------------------------------------------------------------------
1 | add('url', $options['url_form_type'], [
18 | 'label' => 'field_type.link.url',
19 | 'constraints' => [
20 | new NotBlank(null, null, null, null, $options['validation_groups']),
21 | ],
22 | ])
23 | ->add('title', TextType::class, [
24 | 'label' => 'field_type.link.title',
25 | 'constraints' => [
26 | new NotBlank(null, null, null, null, $options['validation_groups']),
27 | ],
28 | ])
29 | ;
30 | }
31 |
32 | /**
33 | * @param OptionsResolver $resolver
34 | */
35 | public function configureOptions(OptionsResolver $resolver)
36 | {
37 | $resolver->setDefaults([
38 | 'translation_domain' => 'AdvancedContentBundle',
39 | 'url_form_type' => UrlType::class,
40 | ]);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Form/Type/PageTypeType.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
25 | }
26 |
27 | public function buildForm(FormBuilderInterface $builder, array $options)
28 | {
29 | $builder
30 | ->add('name', TextType::class, [
31 | 'label' => 'page_type.form.name',
32 | 'constraints' => [
33 | new NotBlank(null, null, null, null, $options['validation_groups']),
34 | ],
35 | ])
36 | ;
37 | }
38 |
39 | public function configureOptions(OptionsResolver $resolver)
40 | {
41 | $resolver->setDefaults([
42 | 'data_class' => $this->configurationManager->getEntityClass('page_type'),
43 | 'translation_domain' => 'AdvancedContentBundle',
44 | ]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Form/Type/PictureEntryType.php:
--------------------------------------------------------------------------------
1 | remove('alt');
17 | $builder->remove('mime_type');
18 | $builder
19 | ->add('media_query', TextType::class, [
20 | 'label' => 'field_type.image.media_query',
21 | 'constraints' => [
22 | new NotBlank(null, null, null, null, $options['validation_groups']),
23 | ],
24 | ])
25 | ;
26 |
27 | $builder->addEventListener(
28 | FormEvents::PRE_SUBMIT,
29 | function (FormEvent $event) use ($options) {
30 | $data = $event->getData();
31 | if (isset($data['mime_type'])) {
32 | // Remove mime type data to prevent form extra fields error
33 | unset($data['mime_type']);
34 | }
35 | $event->setData($data);
36 | },
37 | 1
38 | );
39 | }
40 |
41 | /**
42 | * @return string
43 | */
44 | public function getParent()
45 | {
46 | return ImageType::class;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Form/Type/PictureType.php:
--------------------------------------------------------------------------------
1 | add('image', ImageType::class, [
18 | 'label' => 'field_type.image.picture_main',
19 | 'row_attr' => ['class' => 'picture-main-image'],
20 | ])
21 | ->add('sources', CollectionType::class, [
22 | 'label' => 'field_type.image.picture_sources',
23 | 'entry_type' => PictureEntryType::class,
24 | 'allow_add' => true,
25 | 'allow_delete' => true,
26 | 'row_attr' => ['class' => 'picture-sources'],
27 | 'entry_options' => [
28 | 'attr' => ['class' => 'picture-source'],
29 | 'label' => false,
30 | ],
31 | ]);
32 |
33 | $builder->addEventListener(
34 | FormEvents::PRE_SUBMIT,
35 | function (FormEvent $event) use ($options) {
36 | $data = $event->getData();
37 | $globalMimeTypes = $data['image']['mime_type'] ?? [];
38 | if (isset($data['sources']) && is_array($data['sources'])) {
39 | foreach ($data['sources'] as $key => $source) {
40 | $data['sources'][$key]['mime_type'] = $globalMimeTypes;
41 | }
42 | }
43 |
44 | $event->setData($data);
45 | }
46 | );
47 | }
48 |
49 | /**
50 | * @param OptionsResolver $resolver
51 | */
52 | public function configureOptions(OptionsResolver $resolver)
53 | {
54 | $resolver->setDefaults([
55 | 'row_attr' => ['class' => 'picture-field'],
56 | ]);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Form/Type/RepeatedChildWrappedType.php:
--------------------------------------------------------------------------------
1 | add('wrapped_child', $options['child_form'], $options['child_options'])
23 | ->add('position', HiddenType::class, ['data' => $options['position']])
24 | ;
25 |
26 | $dataCallback = function (FormEvent $event) {
27 | $data = $event->getData();
28 |
29 | $data = ['wrapped_child' => $data];
30 |
31 | $event->setData($data);
32 | };
33 |
34 | $builder->addEventListener(FormEvents::PRE_SET_DATA, $dataCallback, -5);
35 | }
36 |
37 | public function configureOptions(OptionsResolver $resolver)
38 | {
39 | $resolver->setDefaults([
40 | 'position' => 0,
41 | 'child_options'=> [],
42 | ]);
43 | $resolver->setRequired(['child_form']);
44 | $resolver->setNormalizer('child_options', function (Options $options, $value) {
45 | unset($value['property_path']);
46 |
47 | return $value;
48 | });
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Form/Type/RowType.php:
--------------------------------------------------------------------------------
1 | add('columns_gap', IntegerType::class, [
17 | 'label' => 'layout_type.row.config.columns_gap',
18 | 'required' => false,
19 | 'attr' => ['placeholder' => 'layout_type.row.config.columns_gap_placeholder'],
20 | ])
21 | ->add('mobile_reverse_columns', CheckboxType::class, [
22 | 'label' => 'layout_type.row.config.mobile_reverse_columns',
23 | 'required' => false,
24 | ])
25 | ->add('justify_content', ChoiceType::class, [
26 | 'label' => 'layout_type.row.config.justify_content',
27 | 'required' => false,
28 | 'choices' => [
29 | 'layout_type.row.config.justify_contents.start' => 'start',
30 | 'layout_type.row.config.justify_contents.end' => 'end',
31 | 'layout_type.row.config.justify_contents.center' => 'center',
32 | 'layout_type.row.config.justify_contents.between' => 'between',
33 | 'layout_type.row.config.justify_contents.around' => 'around',
34 | ],
35 | 'placeholder' => false,
36 | ])
37 | ;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Form/Type/ScopeChoiceType.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
32 | $this->scopeHandler = $scopeHandler;
33 | }
34 |
35 | /**
36 | * {@inheritdoc}
37 | */
38 | public function configureOptions(OptionsResolver $resolver)
39 | {
40 | $resolver->setDefaults([
41 | 'class' => $this->configurationManager->getEntityClass('scope'),
42 | 'group_by' => $this->scopeHandler->getScopeGroupBy(),
43 | 'choice_label' => 'optionTitle',
44 | 'multiple' => true,
45 | 'expanded' => false,
46 | 'required' => false,
47 | 'by_reference' => false,
48 | ]);
49 | }
50 |
51 | /**
52 | * {@inheritdoc}
53 | */
54 | public function getParent(): ?string
55 | {
56 | return EntityType::class;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Form/Type/ScopeType.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
25 | }
26 |
27 | public function buildForm(FormBuilderInterface $builder, array $options)
28 | {
29 | $builder
30 | ->add('locale', TextType::class, [
31 | 'label' => false,
32 | 'constraints' => [
33 | new NotBlank(null, null, null, null, $options['validation_groups']),
34 | ],
35 | ])
36 | ;
37 | }
38 |
39 | public function configureOptions(OptionsResolver $resolver)
40 | {
41 | $resolver->setDefaults([
42 | 'data_class' => $this->configurationManager->getEntityClass('scope'),
43 | 'translation_domain' => 'AdvancedContentBundle',
44 | ]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Form/Type/TitleType.php:
--------------------------------------------------------------------------------
1 | add('text', TextType::class, [
23 | 'label' => 'field_type.title.text',
24 | 'constraints' => [
25 | new NotBlank(null, null, null, null, $options['validation_groups']),
26 | ],
27 | ])
28 | ->add('level', ChoiceType::class, [
29 | 'choices' => $choices,
30 | 'label' => 'field_type.title.level',
31 | ])
32 | ;
33 | }
34 |
35 | public function configureOptions(OptionsResolver $resolver)
36 | {
37 | $resolver->setDefaults([
38 | 'translation_domain' => 'AdvancedContentBundle',
39 | ]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Form/Type/VideoType.php:
--------------------------------------------------------------------------------
1 | add('url', UrlType::class, [
18 | 'label' => 'field_type.video.url',
19 | 'constraints' => [
20 | new NotBlank(null, null, null, null, $options['validation_groups']),
21 | ],
22 | ])
23 | ->add('muted', CheckboxType::class, [
24 | 'label' => 'field_type.video.muted',
25 | 'required' => false,
26 | ])
27 | ->add('autoplay', CheckboxType::class, [
28 | 'label' => 'field_type.video.autoplay',
29 | 'required' => false,
30 | ])
31 | ->add('loop', CheckboxType::class, [
32 | 'label' => 'field_type.video.loop',
33 | 'required' => false,
34 | ])
35 | ->add('controls', CheckboxType::class, [
36 | 'label' => 'field_type.video.controls',
37 | 'required' => false,
38 | ])
39 | ->add('height', NumberType::class, [
40 | 'label' => 'field_type.video.height',
41 | 'required' => false,
42 | ])
43 | ->add('width', NumberType::class, [
44 | 'label' => 'field_type.video.width',
45 | 'required' => false,
46 | ])
47 | ;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Form/Type/WysiwygType.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
23 | }
24 |
25 | public function configureOptions(OptionsResolver $resolver)
26 | {
27 | $toolbar = $this->configurationManager->getDefaultWysiwygToolbar();
28 | $resolver->setDefaults([
29 | 'config' => ['toolbar' => $toolbar],
30 | ]);
31 | }
32 |
33 | public function getParent()
34 | {
35 | return CKEditorType::class;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Import/ImportResult.php:
--------------------------------------------------------------------------------
1 | status = self::UNKNOWN;
24 | }
25 |
26 | /**
27 | * @return int
28 | */
29 | public function getStatus()
30 | {
31 | return $this->status;
32 | }
33 |
34 | /**
35 | * @return bool
36 | */
37 | public function isSuccess()
38 | {
39 | return $this->status == self::SUCCESS;
40 | }
41 |
42 | /**
43 | * @return $this
44 | */
45 | public function success()
46 | {
47 | $this->status = self::SUCCESS;
48 |
49 | return $this;
50 | }
51 |
52 | /**
53 | * @return $this
54 | */
55 | public function failure()
56 | {
57 | $this->status = self::FAILURE;
58 |
59 | return $this;
60 | }
61 |
62 | /**
63 | * @return array
64 | */
65 | public function getMessages()
66 | {
67 | return $this->messages;
68 | }
69 |
70 | /**
71 | * @param string $message
72 | *
73 | * @return $this
74 | */
75 | public function addMessage($message)
76 | {
77 | $this->messages[] = $message;
78 |
79 | return $this;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2023 Sherlockode
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is furnished
10 | to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LayoutType/AbstractLayoutType.php:
--------------------------------------------------------------------------------
1 | getCode() . '.label';
17 | }
18 |
19 | /**
20 | * @return string
21 | */
22 | public function getFrontTemplate()
23 | {
24 | return '@SherlockodeAdvancedContent/Layout/front/' . $this->getCode() . '.html.twig';
25 | }
26 |
27 | /**
28 | * @return string
29 | */
30 | public function getPreviewTemplate()
31 | {
32 | return '@SherlockodeAdvancedContent/Layout/preview/'. $this->getCode() .'.html.twig';
33 | }
34 |
35 | /**
36 | * Add element's field(s) to content form
37 | *
38 | * @param FormBuilderInterface $builder
39 | *
40 | * @return void
41 | */
42 | public function buildContentElement(FormBuilderInterface $builder)
43 | {
44 | parent::buildContentElement($builder);
45 |
46 | $builder->add('elements', ElementsType::class, [
47 | 'label' => false,
48 | 'row_attr' => [
49 | 'class' => 'acb-layout-elements-container',
50 | ],
51 | ]);
52 |
53 | $configurationFormType = $this->getConfigurationFormType();
54 | if ($configurationFormType !== null) {
55 | $builder->add('config', $configurationFormType, [
56 | 'label' => false,
57 | ]);
58 | }
59 | }
60 |
61 | /**
62 | * @param array $element
63 | *
64 | * @return array
65 | */
66 | public function getRawData($element)
67 | {
68 | $elements = $element['elements'] ?? [];
69 | uasort($elements, function ($a, $b) {
70 | return ($a['position'] ?? 0) <=> ($b['position'] ?? 0);
71 | });
72 |
73 | return [
74 | 'elements' => $elements,
75 | 'config' => $element['config'] ?? [],
76 | 'extra' => $element['extra'] ?? [],
77 | ];
78 | }
79 |
80 | /**
81 | * Get layout configuration form type
82 | *
83 | * @return string
84 | */
85 | abstract protected function getConfigurationFormType(): ?string;
86 | }
87 |
--------------------------------------------------------------------------------
/LayoutType/Column.php:
--------------------------------------------------------------------------------
1 | config = $config;
20 | }
21 |
22 | /**
23 | * Get entity class configuration for given type
24 | *
25 | * @param string $type
26 | *
27 | * @return string
28 | *
29 | * @throws \RuntimeException
30 | */
31 | public function getEntityClass($type)
32 | {
33 | if (!isset($this->config['entity_class'][$type])) {
34 | throw new \RuntimeException('You are trying to access a configuration that does not exist.');
35 | }
36 |
37 | return $this->config['entity_class'][$type];
38 | }
39 |
40 | /**
41 | * @return array
42 | */
43 | public function getEntityClasses()
44 | {
45 | return $this->config['entity_class'];
46 | }
47 |
48 | /**
49 | * @return mixed
50 | */
51 | public function getImageDirectory()
52 | {
53 | return $this->config['upload']['image_directory'];
54 | }
55 |
56 | /**
57 | * @return string
58 | */
59 | public function getInitDirectory()
60 | {
61 | return $this->config['init_command']['directory'];
62 | }
63 |
64 | /**
65 | * @return string
66 | */
67 | public function getInitFilesDirectory()
68 | {
69 | return $this->config['init_command']['files_directory'];
70 | }
71 |
72 | /**
73 | * @return bool
74 | */
75 | public function initCanUpdate()
76 | {
77 | return $this->config['init_command']['allow_update'];
78 | }
79 |
80 | /**
81 | * @return string
82 | */
83 | public function getDefaultWysiwygToolbar()
84 | {
85 | return $this->getDefaultOptionValue('wysiwyg_toolbar');
86 | }
87 |
88 | /**
89 | * @return bool
90 | */
91 | public function getDefaultDateIncludeTime()
92 | {
93 | return $this->getDefaultOptionValue('date_include_time');
94 | }
95 |
96 | /**
97 | * @return bool
98 | */
99 | public function isScopesEnabled()
100 | {
101 | return $this->config['scopes']['enabled'];
102 | }
103 |
104 | /**
105 | * @param string $option
106 | *
107 | * @return mixed
108 | */
109 | private function getDefaultOptionValue($option)
110 | {
111 | return $this->config['default_options'][$option];
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Manager/ContentManager.php:
--------------------------------------------------------------------------------
1 | configurationManager = $configurationManager;
39 | $this->em = $em;
40 | $this->slugProvider = $slugProvider;
41 | }
42 |
43 | /**
44 | * Get content by its id
45 | *
46 | * @param int $id
47 | *
48 | * @return null|ContentInterface
49 | */
50 | public function getContentById($id)
51 | {
52 | return $this->em->getRepository($this->configurationManager->getEntityClass('content'))->find($id);
53 | }
54 |
55 | /**
56 | * Get all contents
57 | *
58 | * @return array
59 | */
60 | public function getContents()
61 | {
62 | return $this->em->getRepository($this->configurationManager->getEntityClass('content'))->findAll();
63 | }
64 |
65 | /**
66 | * @param ContentInterface $content
67 | *
68 | * @return ContentInterface
69 | */
70 | public function duplicate(ContentInterface $content): ContentInterface
71 | {
72 | $newContent = clone $content;
73 | $this->slugProvider->setContentValidSlug($newContent);
74 | $newContent->setPage(null);
75 |
76 | return $newContent;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Manager/PageManager.php:
--------------------------------------------------------------------------------
1 | slugProvider = $slugProvider;
22 | }
23 |
24 | /**
25 | * @param PageInterface $page
26 | *
27 | * @return PageInterface
28 | */
29 | public function duplicate(PageInterface $page): PageInterface
30 | {
31 | $newPage = clone $page;
32 | $this->slugProvider->setPageValidIdentifier($newPage);
33 |
34 | $pageMeta = $newPage->getPageMeta();
35 | if ($pageMeta !== null) {
36 | $this->slugProvider->setPageValidSlug($newPage);
37 | }
38 |
39 | $content = $newPage->getContent();
40 | if ($content !== null) {
41 | $this->slugProvider->setContentValidSlug($content);
42 | }
43 |
44 | return $newPage;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Manager/UrlBuilderManager.php:
--------------------------------------------------------------------------------
1 | uploadManager = $uploadManager;
31 | $this->assetPackages = $assetPackages;
32 | $this->requestStack = $requestStack;
33 | }
34 |
35 | /**
36 | * @param string $fileName
37 | *
38 | * @return string
39 | */
40 | public function getFileUrl(string $fileName): string
41 | {
42 | if (!$fileName) {
43 | return '';
44 | }
45 |
46 | $filePath = $this->uploadManager->getTargetDir() . DIRECTORY_SEPARATOR . $fileName;
47 | if (!file_exists($filePath)) {
48 | return '';
49 | }
50 |
51 | return $this->assetPackages->getUrl($this->uploadManager->getWebPath() . '/' . $fileName);
52 | }
53 |
54 | /**
55 | * @param string $url
56 | *
57 | * @return string
58 | */
59 | public function getFullUrl(string $url): string
60 | {
61 | if (!$url) {
62 | return '';
63 | }
64 |
65 | if (substr($url, 0, 1) === '#') {
66 | return $url;
67 | }
68 | if (substr($url, 0, 4) === 'http') {
69 | return $url;
70 | }
71 |
72 | if (method_exists($this->requestStack, 'getMainRequest')) {
73 | // SF >= 5.3
74 | $mainRequest = $this->requestStack->getMainRequest();
75 | } else {
76 | // compat SF < 5.3
77 | $mainRequest = $this->requestStack->getMasterRequest();
78 | }
79 | if (!$mainRequest) {
80 | return $url;
81 | }
82 |
83 | return $mainRequest->getSchemeAndHttpHost() . '/' . ltrim($url, '/');
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Model/ContentInterface.php:
--------------------------------------------------------------------------------
1 | data = [];
23 | parent::__construct();
24 | }
25 |
26 | /**
27 | * @return ContentInterface
28 | */
29 | public function getContent(): ContentInterface
30 | {
31 | return $this->content;
32 | }
33 |
34 | /**
35 | * @param ContentInterface $content
36 | *
37 | * @return $this
38 | */
39 | public function setContent(ContentInterface $content): self
40 | {
41 | $this->content = $content;
42 |
43 | return $this;
44 | }
45 |
46 | /**
47 | * @return array
48 | */
49 | public function getData()
50 | {
51 | $data = $this->data ?? [];
52 | uasort($data, function ($a, $b) {
53 | return ($a['position'] ?? 0) <=> ($b['position'] ?? 0);
54 | });
55 |
56 | return $data;
57 | }
58 |
59 | /**
60 | * @param array $data
61 | *
62 | * @return $this
63 | */
64 | public function setData(array $data)
65 | {
66 | $this->data = $data;
67 |
68 | return $this;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Model/ContentVersionInterface.php:
--------------------------------------------------------------------------------
1 | locale;
18 | }
19 |
20 | /**
21 | * @param string $locale
22 | *
23 | * @return $this
24 | */
25 | public function setLocale($locale): self
26 | {
27 | $this->locale = $locale;
28 |
29 | return $this;
30 | }
31 |
32 | /**
33 | * @return string
34 | */
35 | public function getOptionTitle()
36 | {
37 | return (string)$this->locale;
38 | }
39 |
40 | /**
41 | * @return string
42 | */
43 | public function getUnicityIdentifier()
44 | {
45 | return (string)$this->locale;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Model/LocaleScopeInterface.php:
--------------------------------------------------------------------------------
1 | pageMeta;
41 | }
42 |
43 | /**
44 | * @param PageMetaInterface $pageMeta
45 | *
46 | * @return $this
47 | */
48 | public function setPageMeta(PageMetaInterface $pageMeta): self
49 | {
50 | $this->pageMeta = $pageMeta;
51 |
52 | return $this;
53 | }
54 |
55 | /**
56 | * @return string
57 | */
58 | public function getTitle()
59 | {
60 | return $this->title;
61 | }
62 |
63 | /**
64 | * @param string $title
65 | *
66 | * @return $this
67 | */
68 | public function setTitle($title)
69 | {
70 | $this->title = $title;
71 |
72 | return $this;
73 | }
74 |
75 | /**
76 | * @return string
77 | */
78 | public function getSlug()
79 | {
80 | return $this->slug;
81 | }
82 |
83 | /**
84 | * @param string $slug
85 | *
86 | * @return $this
87 | */
88 | public function setSlug($slug)
89 | {
90 | $this->slug = $slug;
91 |
92 | return $this;
93 | }
94 |
95 | /**
96 | * @return string
97 | */
98 | public function getMetaTitle()
99 | {
100 | return $this->metaTitle;
101 | }
102 |
103 | /**
104 | * @param string $metaTitle
105 | *
106 | * @return $this
107 | */
108 | public function setMetaTitle($metaTitle)
109 | {
110 | $this->metaTitle = $metaTitle;
111 |
112 | return $this;
113 | }
114 |
115 | /**
116 | * @return string
117 | */
118 | public function getMetaDescription()
119 | {
120 | return $this->metaDescription;
121 | }
122 |
123 | /**
124 | * @param string $metaDescription
125 | *
126 | * @return $this
127 | */
128 | public function setMetaDescription($metaDescription)
129 | {
130 | $this->metaDescription = $metaDescription;
131 |
132 | return $this;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/Model/PageMetaVersionInterface.php:
--------------------------------------------------------------------------------
1 | id;
23 | }
24 |
25 | /**
26 | * @return string
27 | */
28 | public function getName()
29 | {
30 | return $this->name;
31 | }
32 |
33 | /**
34 | * @param string $name
35 | *
36 | * @return $this
37 | */
38 | public function setName($name)
39 | {
40 | $this->name = $name;
41 |
42 | return $this;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Model/PageTypeInterface.php:
--------------------------------------------------------------------------------
1 | page;
28 | }
29 |
30 | /**
31 | * @param PageInterface $page
32 | *
33 | * @return $this
34 | */
35 | public function setPage(PageInterface $page): self
36 | {
37 | $this->page = $page;
38 |
39 | return $this;
40 | }
41 |
42 | /**
43 | * @return ContentVersionInterface|null
44 | */
45 | public function getContentVersion(): ?ContentVersionInterface
46 | {
47 | return $this->contentVersion;
48 | }
49 |
50 | /**
51 | * @param ContentVersionInterface $contentVersion
52 | *
53 | * @return $this
54 | */
55 | public function setContentVersion(ContentVersionInterface $contentVersion): self
56 | {
57 | $this->contentVersion = $contentVersion;
58 |
59 | return $this;
60 | }
61 |
62 | /**
63 | * @return PageMetaVersionInterface|null
64 | */
65 | public function getPageMetaVersion(): ?PageMetaVersionInterface
66 | {
67 | return $this->pageMetaVersion;
68 | }
69 |
70 | /**
71 | * @param PageMetaVersionInterface $pageMetaVersion
72 | *
73 | * @return $this
74 | */
75 | public function setPageMetaVersion(PageMetaVersionInterface $pageMetaVersion): self
76 | {
77 | $this->pageMetaVersion = $pageMetaVersion;
78 |
79 | return $this;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Model/PageVersionInterface.php:
--------------------------------------------------------------------------------
1 | id;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Model/ScopeInterface.php:
--------------------------------------------------------------------------------
1 | autoSave = false;
30 | }
31 |
32 | /**
33 | * @return int
34 | */
35 | public function getId(): int
36 | {
37 | return $this->id;
38 | }
39 |
40 | /**
41 | * @return int|null
42 | */
43 | public function getUserId(): ?int
44 | {
45 | return $this->userId;
46 | }
47 |
48 | /**
49 | * @param int|null $userId
50 | *
51 | * @return $this
52 | */
53 | public function setUserId(?int $userId): self
54 | {
55 | $this->userId = $userId;
56 |
57 | return $this;
58 | }
59 |
60 | /**
61 | * @return \DateTimeInterface
62 | */
63 | public function getCreatedAt(): \DateTimeInterface
64 | {
65 | return $this->createdAt;
66 | }
67 |
68 | /**
69 | * @param \DateTimeInterface $createdAt
70 | *
71 | * @return $this
72 | */
73 | public function setCreatedAt(\DateTimeInterface $createdAt): self
74 | {
75 | $this->createdAt = $createdAt;
76 |
77 | return $this;
78 | }
79 |
80 | /**
81 | * @return bool
82 | */
83 | public function isAutoSave(): bool
84 | {
85 | return $this->autoSave;
86 | }
87 |
88 | /**
89 | * @param bool $autoSave
90 | *
91 | * @return $this
92 | */
93 | public function setAutoSave(bool $autoSave): self
94 | {
95 | $this->autoSave = $autoSave;
96 |
97 | return $this;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Model/VersionInterface.php:
--------------------------------------------------------------------------------
1 | getFilename();
18 |
19 | if ($file instanceof UploadedFile) {
20 | $fileName = $file->getClientOriginalName();
21 | }
22 |
23 | return $fileName;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Naming/NamerInterface.php:
--------------------------------------------------------------------------------
1 | getExtension();
18 | $fileName = $file->getFilename();
19 |
20 | if ($file instanceof UploadedFile) {
21 | $extension = $file->getClientOriginalExtension();
22 | $fileName = $file->getClientOriginalName();
23 | }
24 |
25 | $fileName = str_replace('.' . $extension, '', $fileName);
26 |
27 | return sprintf('%s_%s.%s', $fileName, md5(uniqid()), $extension);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Resources/config/doctrine-mapping/Content.orm.xml:
--------------------------------------------------------------------------------
1 |
2 |
description'
42 | config:
43 | size: 6
44 | meta:
45 | title: Custom Title
46 | slug: custom-page
47 | meta_description: "Custom Meta Description"
48 |
--------------------------------------------------------------------------------
/Resources/doc/import/files/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sherlockode/advanced-content-bundle/bce811a0cea0460436a00e3e627f3f8d2668a3a6/Resources/doc/import/files/background.png
--------------------------------------------------------------------------------
/Resources/doc/tools.md:
--------------------------------------------------------------------------------
1 | # Tools
2 |
3 | ----
4 |
5 | The page acb/tools allows you to [import](import.md) / [export](export.md) your entities.
6 | It also includes a CRUD system for scopes and page types
7 |
8 | ## Configuration
9 |
10 | ----
11 |
12 | By default, the template used for this page is `@SherlockodeAdvancedContent/Tools/index.html.twig`
13 | You can override this by adding your own file in the configuration :
14 |
15 | ```yaml
16 | # config/packages/sherlockode_advanced_content.yml
17 | sherlockode_advanced_content:
18 | templates:
19 | tools: 'dir/template.html.twig'
20 | ```
21 |
22 | If you are using our extension for Sonata ([SonataBundle](https://github.com/sherlockode/SonataAdvancedContentBundle/)),
23 | there is already a customized template for Sonata that will change the default template to `SherlockodeSonataAdvancedContent/Tools/index.html.twig`
24 | To bypass this and use your template, you will also have to add the following configuration:
25 |
26 | ```yaml
27 | # config/packages/sherlockode_sonata_advanced_content.yml
28 | sherlockode_sonata_advanced_content:
29 | use_bundle_templates:
30 | tools: false
31 | ```
32 |
33 | ## Import / Exports
34 |
35 | ----
36 |
37 | On this page, you will be able to :
38 | - import your entities : upload any yaml file containing your entity.
39 | As long as you respect the [format](import.md), you can include as many entities in the file as you want
40 | - export your entities : you will be able to select which entity/entities you want to export.
41 | This will result in a zip file being downloaded in your browser.
42 |
43 |
44 | ## Scopes
45 |
46 | ----
47 |
48 | By defaut, scopes are not enabled on the bundle.
49 | If you want to handle scopes on your Pages and Contents, you need to enable scope management and also create some scopes.
50 | By default, the provided Scope class is locale-based. You can override the entity if it does not meet your requirements.
51 | Scopes can be created on the tools page.
52 |
53 | ```yaml
54 | # config/packages/sherlockode_advanced_content.yml
55 | sherlockode_advanced_content:
56 | scopes:
57 | enabled: true
58 | ```
59 |
60 | ## Page Types
61 |
62 | ----
63 |
64 | Typing pages allows you to categorize them and use different layouts.
65 | However, if this functionality is not useful to you, you can setup your pages without any page type.
66 |
--------------------------------------------------------------------------------
/Resources/js/acb-collection.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 |
3 | let collectionClass = 'acb-collection-list';
4 | let Collection = {};
5 | Collection.init = function(element) {
6 | if (element.hasClass(collectionClass) && element.data('index') === undefined) {
7 | element.data('index', element.children('.acb-collection-item').length);
8 | }
9 |
10 | element.find('.' + collectionClass).each(function() {
11 | Collection.init($(this));
12 | });
13 | };
14 |
15 | $(function () {
16 | 'use strict';
17 |
18 | $('body').on('click', '.btn-add-acb-collection', function () {
19 | let collectionHolder = $(this).closest('.acb-collection-widget').find('.' + collectionClass);
20 | let prototypeTarget = $(this).data('target') || 'prototype';
21 |
22 | if (collectionHolder.length) {
23 | addCollectionRow(collectionHolder.first(), prototypeTarget);
24 | }
25 | });
26 |
27 | $('body').on('click', '.btn-remove-acb-collection', function () {
28 | let collectionHolder = $(this).closest('.acb-collection-widget').find('.' + collectionClass);
29 | $(this).closest('.acb-collection-item').remove();
30 | collectionHolder.trigger('acb-collection-remove-item');
31 | });
32 |
33 | function addCollectionRow(collectionHolder, prototypeTarget = 'prototype') {
34 | let prototype = collectionHolder.data(prototypeTarget);
35 | let index = collectionHolder.data('index');
36 |
37 | let newRow = $(prototype.replace(/__name__/g, index));
38 | collectionHolder.data('index', index + 1);
39 |
40 | collectionHolder.append(newRow);
41 | collectionHolder.trigger('acb-collection-append-new-item', [newRow]);
42 | }
43 | });
44 |
45 | export default Collection;
46 |
--------------------------------------------------------------------------------
/Resources/js/acb-notification.js:
--------------------------------------------------------------------------------
1 | let notifAlert = function (message) {
2 | alert(message);
3 | };
4 |
5 | let notifConfirm = function (message, callback) {
6 | if (confirm(message)) {
7 | callback();
8 | }
9 | };
10 |
11 | export {notifAlert, notifConfirm};
12 |
--------------------------------------------------------------------------------
/Resources/js/acb-slide-collection.js:
--------------------------------------------------------------------------------
1 | import slide from './slide';
2 | import Collection from './acb-collection';
3 |
4 | slide.element.on('slideContentUpdated', function() {
5 | Collection.init(slide.content);
6 | });
7 |
--------------------------------------------------------------------------------
/Resources/js/export.js:
--------------------------------------------------------------------------------
1 | import jQuery from "jquery";
2 |
3 | jQuery(function ($) {
4 | $('.acb-export-all').on('change', function () {
5 | let checked = $(this).prop('checked');
6 | $(this).closest('.acb-export-entities').find('.acb-export-entity input[type="checkbox"]').each(function () {
7 | $(this).prop('checked', checked);
8 | });
9 | });
10 | });
11 |
12 |
--------------------------------------------------------------------------------
/Resources/js/history.js:
--------------------------------------------------------------------------------
1 | import $ from "jquery";
2 | import { notifConfirm } from './acb-notification.js';
3 | import { hasFormChanged, setFormChanged, isFormUpdating } from './form.js';
4 |
5 | let isAddingVersion = false;
6 | let pageDraftFields = $('[data-page-draft]');
7 | if (pageDraftFields.length > 0) {
8 | pageDraftFields.on('change', function() {
9 | setFormChanged(true);
10 | });
11 | }
12 |
13 | setInterval(function() {
14 | if (isFormUpdating() !== false || isAddingVersion !== false || hasFormChanged() === false) {
15 | return;
16 | }
17 | let history = $('.version-history-table');
18 | if (history.length === 0) {
19 | return;
20 | }
21 |
22 | let dataToPost = {'__field_name__': $('#content-data-json').val()};
23 | if (pageDraftFields.length > 0) {
24 | let pageDraftData = {};
25 | pageDraftFields.each(function (index, element) {
26 | pageDraftData[$(element).data('page-draft')] = $(element).val();
27 | });
28 | dataToPost['__page_meta__'] = pageDraftData;
29 | }
30 |
31 | setFormChanged(false);
32 | isAddingVersion = true;
33 | $.ajax({
34 | url: history.data('save-draft-url'),
35 | data: dataToPost,
36 | type: 'POST'
37 | }).done(function (data) {
38 | if (data.success) {
39 | $('.version-history > table tbody').replaceWith($(data.html).find('table tbody'));
40 | } else {
41 | setFormChanged(true);
42 | }
43 | isAddingVersion = false;
44 | });
45 | }, 20 * 1000);
46 | $('body').on('click', '.version-history .see-all', function () {
47 | $(this).remove();
48 | });
49 | $('body').on('click', '.version-history .acb-version-load', function() {
50 | window.location = $(this).closest('.version-history-table').data('load-version-url') + '?versionId=' + $(this).closest('tr').data('version-id');
51 | });
52 | $('body').on('click', '.version-history .acb-version-remove', function() {
53 | let history = $(this).closest('.version-history-table');
54 | let versionLine = $(this).closest('tr');
55 | notifConfirm($(this).data('confirm-delete'), function() {
56 | $.ajax({
57 | url: history.data('remove-version-url'),
58 | data: {'versionId': versionLine.data('version-id')},
59 | type: 'POST'
60 | }).done(function (data) {
61 | if (data.success) {
62 | $('.version-history > table tbody').replaceWith($(data.html).find('table tbody'));
63 | }
64 | });
65 | });
66 | });
67 |
--------------------------------------------------------------------------------
/Resources/js/slide.js:
--------------------------------------------------------------------------------
1 | import $ from 'jquery';
2 |
3 | class Slide
4 | {
5 | constructor() {
6 | this.closeBtn = $('');
7 | this.header = $('
# | 19 |{{ 'content.form.name'|trans }} | 20 |{{ 'actions'|trans }} | 21 |
---|---|---|
{{ content.id }} | 27 |{{ content.name }} | 28 |29 | {{ 'show'|trans }} 30 | | {{ 'edit'|trans }} 31 | | {{ 'delete'|trans }} 32 | | {{ 'duplicate'|trans }} 33 | | 34 |
8 | {{ value }} 9 |
10 | -------------------------------------------------------------------------------- /Resources/views/Field/front/textarea.html.twig: -------------------------------------------------------------------------------- 1 | {% set attributes = acb_get_element_attributes(extra|default([])) %} 2 | {% set style = attributes.style|default('') %} 3 | 4 |8 | {{ value|nl2br }} 9 |
10 | -------------------------------------------------------------------------------- /Resources/views/Field/front/title.html.twig: -------------------------------------------------------------------------------- 1 | {% set attributes = acb_get_element_attributes(extra|default([])) %} 2 | {% set style = attributes.style|default('') %} 3 | 4 | {% if level > 0 and level < 7 %} 5 | {% set tag = 'h' ~ level %} 6 | {% else %} 7 | {% set tag = 'h1' %} 8 | {% endif %} 9 | <{{ tag }} class="{{ attributes.classes }}" 10 | {% if attributes.id %}id="{{ attributes.id }}"{% endif %} 11 | {% if style|trim is not empty %}style="{{ style }}"{% endif %} 12 | > 13 | {{ text }} 14 | {{ tag }}> 15 | -------------------------------------------------------------------------------- /Resources/views/Field/front/video.html.twig: -------------------------------------------------------------------------------- 1 | {% if url is defined and url is not empty %} 2 | {% set options = 'playsinline' %} 3 | {% set urlOptions = [] %} 4 | {% if muted is defined and muted == true %} 5 | {% set options = options ~ ' muted' %} 6 | {% set urlOptions = urlOptions|merge([{'param': 'muted', 'value': 1}]) %} 7 | {% endif %} 8 | {% if autoplay is defined and autoplay == true %} 9 | {% set options = options ~ ' autoplay' %} 10 | {% set urlOptions = urlOptions|merge([{'param': 'autoplay', 'value': 1}]) %} 11 | {% endif %} 12 | {% if loop is defined and loop == true %} 13 | {% set options = options ~ ' loop' %} 14 | {% set urlOptions = urlOptions|merge([{'param': 'loop', 'value': 1}]) %} 15 | {% endif %} 16 | {% if controls is defined and controls == true %} 17 | {% set options = options ~ ' controls' %} 18 | {% set urlOptions = urlOptions|merge([{'param': 'controls', 'value': 1}]) %} 19 | {% endif %} 20 | 21 | {% set videoHeight = '' %} 22 | {% if height is defined and height is not empty %} 23 | {% set videoHeight = 'height="' ~ height ~ '"' %} 24 | {% set urlOptions = urlOptions|merge([{'param': 'height', 'value': height}]) %} 25 | {% endif %} 26 | 27 | {% set videoWidth = '' %} 28 | {% if width is defined and width is not empty %} 29 | {% set videoWidth = 'width="' ~ width ~ '"' %} 30 | {% set urlOptions = urlOptions|merge([{'param': 'width', 'value': width}]) %} 31 | {% endif %} 32 | 33 | {% set attributes = acb_get_element_attributes(extra|default([]), 'inline') %} 34 | {% set style = attributes.style|default('') %} 35 | 36 | {% if '.mp4' in url %} 37 | 45 | {% else %} 46 | {% for option in urlOptions %} 47 | {% set url = url ~ ('?' in url ? '&' : '?') ~ option.param ~ '=' ~ option.value %} 48 | {% endfor %} 49 | 59 | {% endif %} 60 | {% endif %} 61 | -------------------------------------------------------------------------------- /Resources/views/Field/front/wysiwyg.html.twig: -------------------------------------------------------------------------------- 1 | {% set attributes = acb_get_element_attributes(extra|default([])) %} 2 | {% set style = attributes.style|default('') %} 3 | 4 |
3 | {% if sources is defined and sources|length > 0 %}
4 |
13 |
14 | {% if sources is defined and sources|length > 0 %}
15 |
{{ 'field_type.missing_preview'|trans }}
5 |{{ value }}
2 | -------------------------------------------------------------------------------- /Resources/views/Field/preview/textarea.html.twig: -------------------------------------------------------------------------------- 1 |{{ value|nl2br }}
2 | -------------------------------------------------------------------------------- /Resources/views/Field/preview/title.html.twig: -------------------------------------------------------------------------------- 1 | {% if level > 0 and level < 7 %} 2 | {% set tag = 'h' ~ level %} 3 | {% else %} 4 | {% set tag = 'h1' %} 5 | {% endif %} 6 | <{{ tag }}>{{ text }}{{ tag }}> 7 | -------------------------------------------------------------------------------- /Resources/views/Field/preview/video.html.twig: -------------------------------------------------------------------------------- 1 | {% if url is defined and url is not empty %} 2 | {% set options = 'playsinline' %} 3 | {% set urlOptions = [] %} 4 | {% if muted is defined and muted == true %} 5 | {% set options = options ~ ' muted' %} 6 | {% set urlOptions = urlOptions|merge([{'param': 'muted', 'value': 1}]) %} 7 | {% endif %} 8 | {% if autoplay is defined and autoplay == true %} 9 | {% set options = options ~ ' autoplay' %} 10 | {% set urlOptions = urlOptions|merge([{'param': 'autoplay', 'value': 1}]) %} 11 | {% endif %} 12 | {% if loop is defined and loop == true %} 13 | {% set options = options ~ ' loop' %} 14 | {% set urlOptions = urlOptions|merge([{'param': 'loop', 'value': 1}]) %} 15 | {% endif %} 16 | {% if controls is defined and controls == true %} 17 | {% set options = options ~ ' controls' %} 18 | {% set urlOptions = urlOptions|merge([{'param': 'controls', 'value': 1}]) %} 19 | {% endif %} 20 | 21 | {% set videoHeight = '' %} 22 | {% if height is defined and height is not empty %} 23 | {% set videoHeight = 'height="' ~ height ~ '"' %} 24 | {% set urlOptions = urlOptions|merge([{'param': 'height', 'value': height}]) %} 25 | {% endif %} 26 | 27 | {% set videoWidth = '' %} 28 | {% if width is defined and width is not empty %} 29 | {% set videoWidth = 'width="' ~ width ~ '"' %} 30 | {% set urlOptions = urlOptions|merge([{'param': 'width', 'value': width}]) %} 31 | {% endif %} 32 | 33 | {% if '.mp4' in url %} 34 | 35 | {% else %} 36 | {% for option in urlOptions %} 37 | {% set url = url ~ ('?' in url ? '&' : '?') ~ option.param ~ '=' ~ option.value %} 38 | {% endfor %} 39 | 46 | {% endif %} 47 | {% endif %} 48 | -------------------------------------------------------------------------------- /Resources/views/Field/preview/wysiwyg.html.twig: -------------------------------------------------------------------------------- 1 | {{ value|raw }} 2 | -------------------------------------------------------------------------------- /Resources/views/Form/base_theme.html.twig: -------------------------------------------------------------------------------- 1 | {% extends acb_base_form_theme() %} 2 | -------------------------------------------------------------------------------- /Resources/views/Form/theme.html.twig: -------------------------------------------------------------------------------- 1 | {% extends '@SherlockodeAdvancedContent/Form/base_theme.html.twig' %} 2 | 3 | {% trans_default_domain 'AdvancedContentBundle' %} 4 | 5 | {% block form_row %} 6 | {% if form.parent and form.vars.compound and (form.parent.vars.name == 'value' or (form.parent.parent and form.parent.parent.vars.name == 'value')) %} 7 | {% set row_attr = row_attr|default({})|merge({'class': row_attr.class|default('') ~ ' acb-field-element-compound'}) %} 8 | {% endif %} 9 | {{ parent() }} 10 | {% endblock %} 11 | 12 | {% block collection_widget %} 13 | 25 | {% endblock collection_widget %} 26 | 27 | {% block collection_entry_widget %} 28 |# | 19 |{{ 'page.label'|trans }} | 20 |{{ 'actions'|trans }} | 21 |
---|---|---|
{{ page.id }} | 27 |{{ page.pageMeta.title }} | 28 |29 | {{ 'edit'|trans }} 30 | | {{ 'delete'|trans }} 31 | | {{ 'duplicate'|trans }} 32 | | 33 |
# | 11 |{{ 'page_type.form.name'|trans }} | 12 |{{ 'actions'|trans }} | 13 |
---|---|---|
{{ pageType.id }} | 19 |{{ pageType.name }} | 20 |21 | {{ 'delete'|trans }} 22 | | 23 |
27 | | 28 | {{ form_widget(form.name) }} 29 | {{ form_errors(form) }} 30 | | 31 |32 | 35 | | 36 |
# | 11 |{{ 'scope.locale'|trans }} | 12 |{{ 'actions'|trans }} | 13 |
---|---|---|
{{ scope.id }} | 19 |{{ scope.locale }} | 20 |21 | {{ 'delete'|trans }} 22 | | 23 |
27 | | 28 | {{ form_widget(form.locale) }} 29 | {{ form_errors(form) }} 30 | | 31 |32 | 35 | | 36 |
{{ 'version.list.id'|trans }} | 15 |{{ 'version.list.date'|trans }} | 16 |{{ 'version.list.user'|trans }} | 17 |{{ 'version.list.actions.title'|trans }} | 18 |
---|---|---|---|
{{ 'version.list.display_all'|trans }} | 33 |