diff --git a/.ddev/config.yaml b/.ddev/config.yaml index b67d033..b8dc26c 100644 --- a/.ddev/config.yaml +++ b/.ddev/config.yaml @@ -1,4 +1,4 @@ -APIVersion: v1.12.1 +APIVersion: v1.12.2 name: sitepackagebuilder type: php docroot: public @@ -17,8 +17,8 @@ use_dns_when_possible: true timezone: Europe/Berlin -# This config.yaml was created with ddev version v1.12.1 -# webimage: drud/ddev-webserver:v1.12.1 +# This config.yaml was created with ddev version v1.12.2 +# webimage: drud/ddev-webserver:v1.12.2 # dbimage: drud/ddev-dbserver-mariadb-10.2:v1.12.0 # dbaimage: drud/phpmyadmin:v1.12.0 # bgsyncimage: drud/ddev-bgsync:v1.12.0 diff --git a/src/Controller/Api/SitepackageController.php b/src/Controller/Api/SitepackageController.php index cbb1dec..7970695 100644 --- a/src/Controller/Api/SitepackageController.php +++ b/src/Controller/Api/SitepackageController.php @@ -70,13 +70,6 @@ public function createSitepackage(Request $request): Response $content = $request->getContent(); $sitepackage = $this->serializer->deserialize($content, Package::class, 'json'); $this->validateObject($sitepackage); - - $sitepackage->setVendorName(StringUtility::stringToUpperCamelCase($sitepackage->getAuthor()->getCompany())); - $sitepackage->setVendorNameAlternative(StringUtility::camelCaseToLowerCaseDashed($sitepackage->getVendorName())); - $sitepackage->setPackageName(StringUtility::stringToUpperCamelCase($sitepackage->getTitle())); - $sitepackage->setPackageNameAlternative(StringUtility::camelCaseToLowerCaseDashed($sitepackage->getPackageName())); - $sitepackage->setExtensionKey(StringUtility::camelCaseToLowerCaseUnderscored($sitepackage->getPackageName())); - $this->sitepackageGenerator->create($sitepackage); $filename = $this->sitepackageGenerator->getFilename(); BinaryFileResponse::trustXSendfileTypeHeader(); diff --git a/src/Controller/Web/DefaultController.php b/src/Controller/Web/DefaultController.php index 4802d49..7861c82 100644 --- a/src/Controller/Web/DefaultController.php +++ b/src/Controller/Web/DefaultController.php @@ -53,19 +53,23 @@ public function new(Request $request) { $session = $request->getSession(); $session->set('sitepackage', null); + $sitepackage = new Package(); $form = $this->createNewSitePackageForm($sitepackage); $form->handleRequest($request); - if ($form->isSubmitted() && $form->isValid()) { - $sitepackage->setVendorName(StringUtility::stringToUpperCamelCase($sitepackage->getAuthor()->getCompany())); - $sitepackage->setVendorNameAlternative(StringUtility::camelCaseToLowerCaseDashed($sitepackage->getVendorName())); - $sitepackage->setPackageName(StringUtility::stringToUpperCamelCase($sitepackage->getTitle())); - $sitepackage->setPackageNameAlternative(StringUtility::camelCaseToLowerCaseDashed($sitepackage->getPackageName())); - $sitepackage->setExtensionKey(StringUtility::camelCaseToLowerCaseUnderscored($sitepackage->getPackageName())); - $session = $request->getSession(); - $session->set('sitepackage', $sitepackage); - return $this->redirectToRoute('default_success'); + if ($form->isSubmitted()) { + if ($form->get('extended')->isClicked()) { + $sitepackage->setExtended(true); + } + + if ($sitepackage->getExtended()) { + $session->set('sitepackage', $sitepackage); + return $this->redirectToRoute('default_edit'); + } elseif ($form->isValid()) { + $session->set('sitepackage', $sitepackage); + return $this->redirectToRoute('default_success'); + } } return $this->render( @@ -83,6 +87,7 @@ public function edit(Request $request) { $session = $request->getSession(); $sitepackage = $session->get('sitepackage'); + if ($sitepackage === null) { $this->addFlash( 'danger', @@ -90,16 +95,11 @@ public function edit(Request $request) ); return $this->redirectToRoute('default_new'); } + $form = $this->createEditSitePackageForm($sitepackage); $form->handleRequest($request); + if ($form->isSubmitted() && $form->isValid()) { - $sitepackage->setVendorName(StringUtility::stringToUpperCamelCase($sitepackage->getAuthor()->getCompany())); - $sitepackage->setVendorNameAlternative(StringUtility::camelCaseToLowerCaseDashed($sitepackage->getVendorName())); - $sitepackage->setPackageName(StringUtility::stringToUpperCamelCase($sitepackage->getTitle())); - $sitepackage->setPackageNameAlternative(StringUtility::camelCaseToLowerCaseDashed($sitepackage->getPackageName())); - $sitepackage->setExtensionKey(StringUtility::camelCaseToLowerCaseUnderscored($sitepackage->getPackageName())); - $session = $request->getSession(); - $session->set('sitepackage', $sitepackage); return $this->redirectToRoute('default_success'); } diff --git a/src/Entity/Package.php b/src/Entity/Package.php index afdc7be..3401ea0 100644 --- a/src/Entity/Package.php +++ b/src/Entity/Package.php @@ -10,6 +10,7 @@ namespace App\Entity; use App\Entity\Package\Author; +use App\Utility\StringUtility; use JMS\Serializer\Annotation as Serializer; use Swagger\Annotations as SWG; use Symfony\Component\Validator\Constraints as Assert; @@ -19,6 +20,11 @@ */ class Package implements \JsonSerializable { + /** + * @var bool + */ + private $extended = false; + /** * @Assert\NotBlank() * @Assert\Choice({ @@ -47,14 +53,34 @@ class Package implements \JsonSerializable private $basePackage = 'bootstrap_package'; /** + * @Assert\Length( + * allowEmptyString = true, + * min = 3 + * ) + * @Assert\Regex( + * pattern = "/^[A-Z][A-Za-z0-9]+$/", + * message = "Only letters, numbers and spaces are allowed" + * ) + * @SWG\Property(type="string", example="BK2K", default="generated from author->company if empty") + * @Serializer\Type("string") * @var string */ - private $vendorName; + private $vendorName = ''; /** + * @Assert\Length( + * allowEmptyString = true, + * min = 3 + * ) + * @Assert\Regex( + * pattern = "/^[a-z][a-z0-9-]+$/", + * message = "Only letters, numbers and hyphens are allowed" + * ) + * @SWG\Property(type="string", example="bk2k", default="generated from vendor name if empty") + * @Serializer\Type("string") * @var string */ - private $vendorNameAlternative; + private $vendorNameAlternative = ''; /** * @Assert\NotBlank( @@ -87,19 +113,49 @@ class Package implements \JsonSerializable private $description; /** + * @Assert\Length( + * allowEmptyString = true, + * min = 3 + * ) + * @Assert\Regex( + * pattern = "/^[A-Z][A-Za-z0-9]+$/", + * message = "Only letters and numbers are allowed" + * ) + * @SWG\Property(type="string", example="MySitepackage", default="generated from title if empty") + * @Serializer\Type("string") * @var string */ - private $packageName; + private $packageName = ''; /** + * @Assert\Length( + * allowEmptyString = true, + * min = 3 + * ) + * @Assert\Regex( + * pattern = "/^[a-z][a-z0-9-]+$/", + * message = "Only lower case letters, numbers and hyphens are allowed" + * ) + * @SWG\Property(type="string", example="my-sitepackage", default="generated from package name if empty") + * @Serializer\Type("string") * @var string */ - private $packageNameAlternative; + private $packageNameAlternative = ''; /** + * @Assert\Length( + * allowEmptyString = true, + * min = 3 + * ) + * @Assert\Regex( + * pattern = "/^[a-z][a-z0-9_]+$/", + * message = "Only lower case letters, numbers and undscores are allowed" + * ) + * @SWG\Property(type="string", example="my_sitepackage", default="generated from package name if empty") + * @Serializer\Type("string") * @var string */ - private $extensionKey; + private $extensionKey = ''; /** * @Assert\Url() @@ -112,12 +168,29 @@ class Package implements \JsonSerializable /** * @Assert\Valid - * * @Serializer\Type(Author::class) * @var Author */ private $author; + /** + * @return bool + */ + public function getExtended() + { + return $this->extended; + } + + /** + * @param bool $extended + * @return Package + */ + public function setExtended($extended) + { + $this->extended = $extended; + return $this; + } + /** * @return int */ @@ -159,6 +232,10 @@ public function setBasePackage($basePackage) */ public function getVendorName() { + if (empty($this->vendorName)) { + return StringUtility::stringToUpperCamelCase($this->getAuthor()->getCompany()); + } + return $this->vendorName; } @@ -168,7 +245,10 @@ public function getVendorName() */ public function setVendorName($vendorName) { - $this->vendorName = $vendorName; + if ($this->getVendorName() !== $vendorName) { + $this->vendorName = StringUtility::stringToUpperCamelCase($vendorName); + } + return $this; } @@ -177,6 +257,10 @@ public function setVendorName($vendorName) */ public function getVendorNameAlternative() { + if (empty($this->vendorNameAlternative)) { + return StringUtility::camelCaseToLowerCaseDashed($this->getVendorName()); + } + return $this->vendorNameAlternative; } @@ -186,7 +270,9 @@ public function getVendorNameAlternative() */ public function setVendorNameAlternative($vendorNameAlternative) { - $this->vendorNameAlternative = $vendorNameAlternative; + if ($this->getVendorNameAlternative() !== $vendorNameAlternative) { + $this->vendorNameAlternative = StringUtility::camelCaseToLowerCaseDashed($vendorNameAlternative); + } return $this; } @@ -231,6 +317,10 @@ public function setDescription($description) */ public function getPackageName() { + if (empty($this->packageName)) { + return StringUtility::stringToUpperCamelCase($this->getTitle()); + } + return $this->packageName; } @@ -240,7 +330,10 @@ public function getPackageName() */ public function setPackageName($packageName) { - $this->packageName = $packageName; + if ($this->getPackageName() !== $packageName) { + $this->packageName = StringUtility::stringToUpperCamelCase($packageName); + } + return $this; } @@ -249,6 +342,10 @@ public function setPackageName($packageName) */ public function getPackageNameAlternative() { + if (empty($this->packageNameAlternative)) { + return StringUtility::camelCaseToLowerCaseDashed($this->getPackageName()); + } + return $this->packageNameAlternative; } @@ -258,7 +355,10 @@ public function getPackageNameAlternative() */ public function setPackageNameAlternative($packageNameAlternative) { - $this->packageNameAlternative = $packageNameAlternative; + if ($this->getPackageNameAlternative() !== $packageNameAlternative) { + $this->packageNameAlternative = StringUtility::camelCaseToLowerCaseDashed($packageNameAlternative); + } + return $this; } @@ -267,6 +367,10 @@ public function setPackageNameAlternative($packageNameAlternative) */ public function getExtensionKey() { + if (empty($this->extensionKey)) { + return StringUtility::camelCaseToLowerCaseUnderscored($this->getPackageName()); + } + return $this->extensionKey; } @@ -276,7 +380,10 @@ public function getExtensionKey() */ public function setExtensionKey($extensionKey) { - $this->extensionKey = $extensionKey; + if ($this->getExtensionKey() !== $extensionKey) { + $this->extensionKey = StringUtility::camelCaseToLowerCaseUnderscored($extensionKey); + } + return $this; } diff --git a/src/Form/AuthorType.php b/src/Form/AuthorType.php index 652dc00..f3945fc 100644 --- a/src/Form/AuthorType.php +++ b/src/Form/AuthorType.php @@ -23,25 +23,25 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder ->add('name', TextType::class, [ 'attr' => [ - 'autocomplete' => 'off', + 'autocomplete' => 'on', 'placeholder' => 'John Doe', ], ]) ->add('email', EmailType::class, [ 'attr' => [ - 'autocomplete' => 'off', + 'autocomplete' => 'on', 'placeholder' => 'john.doe@example.com', ], ]) ->add('company', TextType::class, [ 'attr' => [ - 'autocomplete' => 'off', + 'autocomplete' => 'on', 'placeholder' => 'Company Inc.', ], ]) ->add('homepage', TextType::class, [ 'attr' => [ - 'autocomplete' => 'off', + 'autocomplete' => 'on', 'placeholder' => 'https://www.example.com', ], ]); diff --git a/src/Form/PackageType.php b/src/Form/PackageType.php index da46885..f753090 100644 --- a/src/Form/PackageType.php +++ b/src/Form/PackageType.php @@ -12,6 +12,7 @@ use App\Entity\Package; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; @@ -28,6 +29,8 @@ class PackageType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { + $extended = $options['data']->getExtended(); + $builder ->setAction($options['action']) ->add('typo3Version', ChoiceType::class, [ @@ -67,8 +70,66 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'autocomplete' => 'off', 'placeholder' => 'https://github.com/username/my_sitepackage' ] - ]) - ->add('author', AuthorType::class); + ]); + + if ($extended) { + $builder + ->add('vendorName', TextType::class, [ + 'label' => 'PHP Vendor Name', + 'required' => false, + 'attr' => [ + 'autocomplete' => 'on', + 'placeholder' => 'BK2K', + ], + ]) + ->add('packageName', TextType::class, [ + 'label' => 'PHP Package Name', + 'required' => false, + 'attr' => [ + 'autocomplete' => 'off', + 'placeholder' => 'my_sitepackage', + ], + ]) + ->add('vendorNameAlternative', TextType::class, [ + 'label' => 'Composer Vendor Name', + 'required' => false, + 'attr' => [ + 'autocomplete' => 'on', + 'placeholder' => 'BK2K', + ], + ]) + ->add('packageNameAlternative', TextType::class, [ + 'label' => 'Composer Package Name', + 'required' => false, + 'attr' => [ + 'autocomplete' => 'off', + 'placeholder' => 'my_sitepackage', + ], + ]) + ->add('extensionKey', TextType::class, [ + 'label' => 'Extension Key', + 'required' => false, + 'attr' => [ + 'autocomplete' => 'off', + 'placeholder' => 'my_sitepackage', + ], + ]); + } + + if (!$extended) { + $builder->add( + 'extended', + SubmitType::class, + [ + 'label' => 'Extended Configuration', + 'icon' => 'pencil', + 'attr' => ['class' => 'btn-secondary'], + 'validate' => false + ] + ); + } + + $builder->add('author', AuthorType::class); } /** diff --git a/src/Resources/skeletons/BaseExtension/bootstrap_package/composer.json.twig b/src/Resources/skeletons/BaseExtension/bootstrap_package/composer.json.twig index 618a348..218b704 100644 --- a/src/Resources/skeletons/BaseExtension/bootstrap_package/composer.json.twig +++ b/src/Resources/skeletons/BaseExtension/bootstrap_package/composer.json.twig @@ -1,10 +1,13 @@ { "name": "{{ package.vendorNameAlternative }}/{{ package.packageNameAlternative }}", - "type": "typo3-cms-extension", "description": "{{ package.description}}", + "type": "typo3-cms-extension", + "keywords": ["TYPO3 CMS", "extension", "sitepackage", "{{ package.title }}"], "homepage": "{{ package.author.homepage }}", - "license": ["GPL-2.0-or-later"], - "keywords": ["TYPO3 CMS"], + "license": "proprietary", + "support": { + "source": "{{ package.repositoryUrl }}" + }, "require": { "bk2k/bootstrap-package": "{% if package.typo3version < 9000000 %}^10.0{% elseif package.typo3version < 10000000 %}^10.0 || ^11.0{% else %}^11.0{% endif %}" }, @@ -12,5 +15,10 @@ "psr-4": { "{{ package.vendorName }}\\{{ package.packageName }}\\": "Classes/" } + }, + extra: { + "typo3/cms": { + "extension-key": "{{ package.extensionKey }}" + } } } diff --git a/src/Resources/skeletons/BaseExtension/fluid_styled_content/composer.json.twig b/src/Resources/skeletons/BaseExtension/fluid_styled_content/composer.json.twig index 9e09a26..a313058 100644 --- a/src/Resources/skeletons/BaseExtension/fluid_styled_content/composer.json.twig +++ b/src/Resources/skeletons/BaseExtension/fluid_styled_content/composer.json.twig @@ -1,10 +1,13 @@ { "name": "{{ package.vendorNameAlternative }}/{{ package.packageNameAlternative }}", - "type": "typo3-cms-extension", "description": "{{ package.description}}", + "type": "typo3-cms-extension", + "keywords": ["TYPO3 CMS", "extension", "sitepackage", "{{ package.title }}"], "homepage": "{{ package.author.homepage }}", - "license": ["GPL-2.0-or-later"], - "keywords": ["TYPO3 CMS"], + "license": "proprietary", + "support": { + "source": "{{ package.repositoryUrl }}" + }, "require": { "typo3/cms-core": "{% if package.typo3version < 9000000 %}^8.7{% elseif package.typo3version < 10000000 %}^9.5{% else %}^10.2{% endif %}", "typo3/cms-rte-ckeditor": "{% if package.typo3version < 9000000 %}^8.7{% elseif package.typo3version < 10000000 %}^9.5{% else %}^10.2{% endif %}", @@ -14,5 +17,10 @@ "psr-4": { "{{ package.vendorName }}\\{{ package.packageName }}\\": "Classes/" } + }, + extra: { + "typo3/cms": { + "extension-key": "{{ package.extensionKey }}" + } } } diff --git a/src/Utility/StringUtility.php b/src/Utility/StringUtility.php index 0f211c2..fab819b 100644 --- a/src/Utility/StringUtility.php +++ b/src/Utility/StringUtility.php @@ -62,6 +62,7 @@ public static function stringToUpperCamelCase($string) { $string = self::clean($string); $string = preg_replace('/[^a-z0-9]+/i', ' ', $string); + $string = preg_replace('/[A-Z]+/', ' $0', $string); $string = trim($string); $string = strtolower($string); $string = ucwords($string); diff --git a/templates/default/edit.html.twig b/templates/default/edit.html.twig index f383f4f..261abc2 100644 --- a/templates/default/edit.html.twig +++ b/templates/default/edit.html.twig @@ -17,14 +17,6 @@ -
-
-

- We respect your Privacy.
- We are not storing, sharing or doing any other crazy stuff with the data you provide to generate your very own sitepackage. Simple as that. - -

-
-
+{% include 'default/partials/privacy-footer.html.twig' %} {% endblock %} diff --git a/templates/default/new.html.twig b/templates/default/new.html.twig index 6352974..2131da0 100644 --- a/templates/default/new.html.twig +++ b/templates/default/new.html.twig @@ -21,13 +21,6 @@ -
-
-

- We respect your Privacy.
- We are not storing, sharing or doing any other crazy stuff with the data you provide to generate your very own sitepackage. Simple as that. -

-
-
+{% include 'default/partials/privacy-footer.html.twig' %} {% endblock %} diff --git a/templates/default/partials/privacy-footer.html.twig b/templates/default/partials/privacy-footer.html.twig new file mode 100644 index 0000000..1e9a0f1 --- /dev/null +++ b/templates/default/partials/privacy-footer.html.twig @@ -0,0 +1,8 @@ +
+
+

+ We respect your Privacy.
+ We are not storing, sharing or doing any other crazy stuff with the data you provide to generate your very own sitepackage. Simple as that. +

+
+