From 9377b219a24c3d413faee241f760a359e0600e3d Mon Sep 17 00:00:00 2001 From: Oskar Dydo Date: Fri, 10 Jul 2020 13:45:55 +0200 Subject: [PATCH 1/4] Initial commit --- .../Form/GenerateNameViewHelper.php | 55 ++++ .../Form/MultiUploadViewHelper.php | 65 ++++ .../Form/RegisterFieldViewHelper.php | 71 +++++ .../Form/SelectFieldViewHelper.php | 130 ++++++++ Classes/ViewHelpers/Form/SelectViewHelper.php | 115 +++++++ Classes/ViewHelpers/FormViewHelper.php | 284 ++++++++++++++++++ Configuration/TCA/Overrides/sys_template.php | 13 + Configuration/TypoScript/constants.typoscript | 5 + Configuration/TypoScript/setup.typoscript | 22 ++ LICENSE => LICENSE.md | 0 README.md | 20 +- Resources/Private/Layout/Default.html | 3 + .../Private/Partials/Form/Field/Check.html | 44 +++ .../Private/Partials/Form/Field/Content.html | 18 ++ .../Private/Partials/Form/Field/Date.html | 23 ++ .../Private/Partials/Form/Field/File.html | 21 ++ .../Private/Partials/Form/Field/Hidden.html | 14 + .../Private/Partials/Form/Field/Html.html | 19 ++ .../Private/Partials/Form/Field/Input.html | 23 ++ .../Private/Partials/Form/Field/Radio.html | 45 +++ .../Private/Partials/Form/Field/Select.html | 35 +++ .../Private/Partials/Form/Field/Submit.html | 16 + .../Private/Partials/Form/Field/Text.html | 17 ++ .../Private/Partials/Form/Field/Textarea.html | 23 ++ .../Private/Partials/Form/FieldLabel.html | 14 + Resources/Private/Partials/Form/Fields.html | 10 + Resources/Private/Partials/Form/Page.html | 10 + Resources/Private/Partials/Form/Pages.html | 9 + Resources/Private/Template/Form/Form.html | 24 ++ composer.json | 41 +++ ext_emconf.php | 20 ++ ext_icon.png | Bin 0 -> 658 bytes ext_localconf.php | 13 + 33 files changed, 1220 insertions(+), 2 deletions(-) create mode 100644 Classes/ViewHelpers/Form/GenerateNameViewHelper.php create mode 100644 Classes/ViewHelpers/Form/MultiUploadViewHelper.php create mode 100644 Classes/ViewHelpers/Form/RegisterFieldViewHelper.php create mode 100644 Classes/ViewHelpers/Form/SelectFieldViewHelper.php create mode 100644 Classes/ViewHelpers/Form/SelectViewHelper.php create mode 100644 Classes/ViewHelpers/FormViewHelper.php create mode 100644 Configuration/TCA/Overrides/sys_template.php create mode 100644 Configuration/TypoScript/constants.typoscript create mode 100644 Configuration/TypoScript/setup.typoscript rename LICENSE => LICENSE.md (100%) create mode 100644 Resources/Private/Layout/Default.html create mode 100644 Resources/Private/Partials/Form/Field/Check.html create mode 100644 Resources/Private/Partials/Form/Field/Content.html create mode 100644 Resources/Private/Partials/Form/Field/Date.html create mode 100644 Resources/Private/Partials/Form/Field/File.html create mode 100644 Resources/Private/Partials/Form/Field/Hidden.html create mode 100644 Resources/Private/Partials/Form/Field/Html.html create mode 100644 Resources/Private/Partials/Form/Field/Input.html create mode 100644 Resources/Private/Partials/Form/Field/Radio.html create mode 100644 Resources/Private/Partials/Form/Field/Select.html create mode 100644 Resources/Private/Partials/Form/Field/Submit.html create mode 100644 Resources/Private/Partials/Form/Field/Text.html create mode 100644 Resources/Private/Partials/Form/Field/Textarea.html create mode 100644 Resources/Private/Partials/Form/FieldLabel.html create mode 100644 Resources/Private/Partials/Form/Fields.html create mode 100644 Resources/Private/Partials/Form/Page.html create mode 100644 Resources/Private/Partials/Form/Pages.html create mode 100644 Resources/Private/Template/Form/Form.html create mode 100644 composer.json create mode 100644 ext_emconf.php create mode 100644 ext_icon.png create mode 100644 ext_localconf.php diff --git a/Classes/ViewHelpers/Form/GenerateNameViewHelper.php b/Classes/ViewHelpers/Form/GenerateNameViewHelper.php new file mode 100644 index 0000000..a5e4ff9 --- /dev/null +++ b/Classes/ViewHelpers/Form/GenerateNameViewHelper.php @@ -0,0 +1,55 @@ +`. + * + * Examples + * ======== + * + * Example:: + * + * + * + * Output:: + * + * + */ +class GenerateNameViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\Form\AbstractFormFieldViewHelper +{ + /** + * Initialize the arguments. + * + * @throws \TYPO3Fluid\Fluid\Core\ViewHelper\Exception + */ + public function initializeArguments() + { + $this->registerArgument( + 'property', + 'string', + 'Name of Object Property. If used in conjunction with , "name" and "value" properties will be ignored.' + ); + $this->registerArgument('name', 'string', 'Name of input tag'); + } + + /** + * @return string|void + */ + public function render() + { + return $this->getName(); + } +} diff --git a/Classes/ViewHelpers/Form/MultiUploadViewHelper.php b/Classes/ViewHelpers/Form/MultiUploadViewHelper.php new file mode 100644 index 0000000..7a6b2d9 --- /dev/null +++ b/Classes/ViewHelpers/Form/MultiUploadViewHelper.php @@ -0,0 +1,65 @@ +getName(); + $allowedFields = ['name', 'type', 'tmp_name', 'error', 'size']; + foreach ($allowedFields as $fieldName) { + $this->registerFieldNameForFormTokenGeneration($name . '[' . $fieldName . '][]'); + } + $this->tag->addAttribute('type', 'file'); + $name .= '[]'; + $this->tag->addAttribute('name', $name); + $this->setErrorClassAttribute(); + return $this->renderInput(); + } + + /** + * Renders and returns the tag + * + * @return string + * @api + */ + public function renderInput() + { + $data = []; + if (empty($this->tagName)) { + return ''; + } + foreach ($this->tag->getAttributes() as $attributeName => $attributeValue) { + $data[$attributeName] = $attributeValue; + } + $data['name'] = $this->tag->getTagName(); + if ($this->tag->hasContent()) { + $data['content'] = $this->tag->getContent(); + } + return json_encode($data); + } +} diff --git a/Classes/ViewHelpers/Form/RegisterFieldViewHelper.php b/Classes/ViewHelpers/Form/RegisterFieldViewHelper.php new file mode 100644 index 0000000..0731d35 --- /dev/null +++ b/Classes/ViewHelpers/Form/RegisterFieldViewHelper.php @@ -0,0 +1,71 @@ +registerArgument('name', 'string', 'Name of input tag'); + $this->registerArgument('value', 'mixed', 'Value of input tag'); + $this->registerArgument( + 'property', + 'string', + 'Name of Object Property. If used in conjunction with , "name" and "value" properties will be ignored.' + ); + $this->registerArgument('additionalAttributes', 'array', 'Additional tag attributes. They will be added directly to the resulting HTML tag.', false); + $this->registerArgument('checked', 'bool', 'Specifies that the input element should be preselected'); + $this->registerArgument('multiple', 'bool', 'Specifies whether this checkbox belongs to a multivalue (is part of a checkbox group)', false, false); + } + + /** + * @return string|void + */ + public function render() + { + $nameAttribute = $this->getName(); + + $checked = $this->arguments['checked']; + $multiple = $this->arguments['multiple']; + + $propertyValue = null; + if ($this->hasMappingErrorOccurred()) { + $propertyValue = $this->getLastSubmittedFormData(); + } + if ($checked === null && $propertyValue === null) { + $propertyValue = $this->getPropertyValue(); + } + + if ($propertyValue instanceof \Traversable) { + $propertyValue = iterator_to_array($propertyValue); + } + if (is_array($propertyValue)) { + $nameAttribute .= '[]'; + } elseif ($multiple === true) { + $nameAttribute .= '[]'; + } + + $this->registerFieldNameForFormTokenGeneration($nameAttribute); + } +} diff --git a/Classes/ViewHelpers/Form/SelectFieldViewHelper.php b/Classes/ViewHelpers/Form/SelectFieldViewHelper.php new file mode 100644 index 0000000..0ad9f57 --- /dev/null +++ b/Classes/ViewHelpers/Form/SelectFieldViewHelper.php @@ -0,0 +1,130 @@ +originalOptions = $this->arguments['options']; + $this->setOptions(); + return json_encode(parent::render()); + } + + /** + * Set options with key and value from $field->getModifiedOptions() + * convert: + * array( + * array( + * 'label' => 'Red shoes', + * 'value' => 'red', + * 'selected' => 0 + * ) + * ) + * + * to: + * array( + * 'red' => 'Red shoes' + * ) + */ + protected function setOptions(): void + { + $optionArray = []; + foreach ($this->arguments['options'] as $option) { + $optionArray[$option['value']] = $option['label']; + } + $this->arguments['options'] = $optionArray; + } + + /** + * Render one option tag + * + * @param string $value value attribute of the option tag (will be escaped) + * @param string $label content of the option tag (will be escaped) + * @param bool $isSelected specifies wether or not to add selected attribute + * @return string the rendered option tag + */ + protected function renderOptionTag($value, $label, $isSelected = false) + { + unset($isSelected); + return parent::renderOptionTag( + $value, + $label, + $this->isSelectedAlternative($this->getOptionFromOriginalOptionsByValue((string)$value)) + ); + } + + /** + * @param string $value + * @return array + */ + protected function getOptionFromOriginalOptionsByValue(string $value): array + { + foreach ($this->originalOptions as $option) { + if ((string)$value === $option['value'] || (string)$value === $option['label']) { + return $option; + } + } + return []; + } + + /** + * Check if option is selected + * + * @param array $option Current option + * @return bool TRUE if the value marked a s selected; FALSE otherwise + */ + protected function isSelectedAlternative(array $option): bool + { + if (is_array($this->getValueAttribute())) { + return $this->isSelectedAlternativeForArray($option); + } + return $this->isSelectedAlternativeForString($option); + } + + /** + * @param array $option + * @return bool + */ + protected function isSelectedAlternativeForString(array $option): bool + { + if (($option['selected'] && !$this->getValueAttribute()) || + ($this->getValueAttribute() && + ($option['value'] === $this->getValueAttribute() || $option['label'] === $this->getValueAttribute())) + ) { + return true; + } + return false; + } + + /** + * @param array $option + * @return bool + */ + protected function isSelectedAlternativeForArray(array $option): bool + { + foreach ($this->getValueAttribute() as $singleValue) { + if (!empty($singleValue) && ($option['value'] === $singleValue || $option['label'] === $singleValue)) { + return true; + } + } + return false; + } +} diff --git a/Classes/ViewHelpers/Form/SelectViewHelper.php b/Classes/ViewHelpers/Form/SelectViewHelper.php new file mode 100644 index 0000000..6c29a63 --- /dev/null +++ b/Classes/ViewHelpers/Form/SelectViewHelper.php @@ -0,0 +1,115 @@ +arguments['required']) && $this->arguments['required']) { + $this->tag->addAttribute('required', 'required'); + } + $name = $this->getName(); + if (isset($this->arguments['multiple']) && $this->arguments['multiple']) { + $this->tag->addAttribute('multiple', 'multiple'); + $name .= '[]'; + } + $this->tag->addAttribute('name', $name); + $options = $this->getOptions(); + + $this->addAdditionalIdentityPropertiesIfNeeded(); + $this->setErrorClassAttribute(); + $content = ''; + // register field name for token generation. + // in case it is a multi-select, we need to register the field name + // as often as there are elements in the box + if (isset($this->arguments['multiple']) && $this->arguments['multiple']) { + $content .= $this->renderHiddenFieldForEmptyValue(); + $optionsCount = count($options); + for ($i = 0; $i < $optionsCount; $i++) { + $this->registerFieldNameForFormTokenGeneration($name); + } + // save the parent field name so that any child f:form.select.option + // tag will know to call registerFieldNameForFormTokenGeneration + // this is the reason why "self::class" is used instead of static::class (no LSB) + $this->viewHelperVariableContainer->addOrUpdate( + self::class, + 'registerFieldNameForFormTokenGeneration', + $name + ); + } else { + $this->registerFieldNameForFormTokenGeneration($name); + } + + $this->viewHelperVariableContainer->addOrUpdate(self::class, 'selectedValue', $this->getSelectedValue()); + $this->renderPrependOptionTag(); + $this->renderOptionTags($options); + + //TODO check if we need it in 'production mode' + $childContent = $this->renderChildren(); + $this->viewHelperVariableContainer->remove(self::class, 'selectedValue'); + $this->viewHelperVariableContainer->remove(self::class, 'registerFieldNameForFormTokenGeneration'); + + return $this->data; + } + + /** + * Render the option tags. + * + * @param array $options the options for the form. + */ + protected function renderOptionTags($options) + { + foreach ($options as $value => $label) { + $isSelected = $this->isSelected($value); + $this->renderOptionTag($value, $label, $isSelected) . LF; + } + } + + /** + * Render one option tag + * + * @param string $value value attribute of the option tag (will be escaped) + * @param string $label content of the option tag (will be escaped) + * @param bool $isSelected specifies whether or not to add selected attribute + * @return string the rendered option tag + */ + protected function renderOptionTag($value, $label, $isSelected) + { + $this->data[$this->elementCounter]['value'] = $value; + $this->data[$this->elementCounter]['label'] = $label; + $this->data[$this->elementCounter]['isSelected'] = $isSelected; + + $this->elementCounter++; + } +} diff --git a/Classes/ViewHelpers/FormViewHelper.php b/Classes/ViewHelpers/FormViewHelper.php new file mode 100644 index 0000000..fbd5490 --- /dev/null +++ b/Classes/ViewHelpers/FormViewHelper.php @@ -0,0 +1,284 @@ +` Tag. + * + * Basic usage + * =========== + * + * Use :html:`` to output an HTML :html:`
` tag which is targeted + * at the specified action, in the current controller and package. + * It will submit the form data via a POST request. If you want to change this, + * use :html:`method="get"` as an argument. + * + * Examples + * ======== + * + * A complex form with a specified encoding type + * --------------------------------------------- + * + * Form with enctype set:: + * + * ... + * + * A Form which should render a domain object + * ------------------------------------------ + * + * Binding a domain object to a form:: + * + * + * + * + * + * + * This automatically inserts the value of ``{customer.name}`` inside the + * textbox and adjusts the name of the textbox accordingly. + */ +class FormViewHelper extends \TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper +{ + /** + * @var array + */ + protected $data = []; + + /** + * @var int + */ + protected $i = 0; + + /** + * Initialize arguments. + */ + public function initializeArguments() + { + parent::initializeArguments(); + $this->registerArgument('formUid', 'int', 'Form uid', true); + } + + /** + * @return false|string + * @throws \TYPO3\CMS\EXTBASE\Security\Exception\InvalidArgumentForHashGenerationException + */ + public function render() + { + $this->setFormActionUri(); + if (isset($this->arguments['method']) && strtolower($this->arguments['method']) === 'get') { + $this->tag->addAttribute('method', 'get'); + } else { + $this->tag->addAttribute('method', 'post'); + } + + if (isset($this->arguments['novalidate']) && $this->arguments['novalidate'] === true) { + $this->tag->addAttribute('novalidate', 'novalidate'); + } + + $this->addFormObjectNameToViewHelperVariableContainer(); + $this->addFormObjectToViewHelperVariableContainer(); + $this->addFieldNamePrefixToViewHelperVariableContainer(); + $this->addFormFieldNamesToViewHelperVariableContainer(); + $this->data['pages'] = $this->renderChildren(); + + $this->renderHiddenIdentityField($this->arguments['object'] ?? null, $this->getFormObjectName()); + $this->renderAdditionalIdentityFields(); + $this->renderHiddenReferrerFields(); + + // Render the trusted list of all properties after everything else has been rendered + $this->renderTrustedPropertiesField(); + $this->renderFormUidField(); + + $this->removeFieldNamePrefixFromViewHelperVariableContainer(); + $this->removeFormObjectFromViewHelperVariableContainer(); + $this->removeFormObjectNameFromViewHelperVariableContainer(); + $this->removeFormFieldNamesFromViewHelperVariableContainer(); + $this->removeCheckboxFieldNamesFromViewHelperVariableContainer(); + + return json_encode($this->data); + } + + /** + * Sets the "action" attribute of the form tag + */ + protected function setFormActionUri() + { + if ($this->hasArgument('actionUri')) { + $formActionUri = $this->arguments['actionUri']; + } else { + if (isset($this->arguments['noCacheHash'])) { + trigger_error( + 'Using the argument "noCacheHash" in ViewHelper has no effect anymore. Remove the argument in your fluid template, as it will result in a fatal error.', + E_USER_DEPRECATED + ); + } + + /** @var UriBuilder $uriBuilder */ + $uriBuilder = $this->renderingContext->getControllerContext()->getUriBuilder(); + $uriBuilder + ->reset() + ->setTargetPageType($this->arguments['pageType'] ?? 0) + ->setNoCache($this->arguments['noCache'] ?? false) + ->setSection($this->arguments['section'] ?? '') + ->setCreateAbsoluteUri($this->arguments['absolute'] ?? false) + ->setArguments(isset($this->arguments['additionalParams']) ? (array)$this->arguments['additionalParams'] : []) + ->setAddQueryString($this->arguments['addQueryString'] ?? false) + ->setArgumentsToBeExcludedFromQueryString(isset($this->arguments['argumentsToBeExcludedFromQueryString']) ? (array)$this->arguments['argumentsToBeExcludedFromQueryString'] : []) + ->setFormat($this->arguments['format'] ?? ''); + + $addQueryStringMethod = $this->arguments['addQueryStringMethod'] ?? null; + if (is_string($addQueryStringMethod)) { + $uriBuilder->setAddQueryStringMethod($addQueryStringMethod); + } + + $pageUid = (int)($this->arguments['pageUid'] ?? 0); + if ($pageUid > 0) { + $uriBuilder->setTargetPageUid($pageUid); + } + + $formActionUri = $uriBuilder->uriFor( + $this->arguments['action'] ?? null, + $this->arguments['arguments'] ?? [], + $this->arguments['controller'] ?? null, + $this->arguments['extensionName'] ?? null, + $this->arguments['pluginName'] ?? null + ); + $this->formActionUriArguments = $uriBuilder->getArguments(); + } + $this->data['action'] = $formActionUri; + } + + /** + * Render additional identity fields which were registered by form elements. + * This happens if a form field is defined like property="bla.blubb" - then we might need an identity property for the sub-object "bla". + * + * @return string HTML-string for the additional identity properties + */ + protected function renderAdditionalIdentityFields() + { + if ($this->viewHelperVariableContainer->exists(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'additionalIdentityProperties')) { + $additionalIdentityProperties = $this->viewHelperVariableContainer->get(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'additionalIdentityProperties'); + + foreach ($additionalIdentityProperties as $identity) { + $this->addHiddenField('identity', $identity); + } + } + + return ''; + } + + /** + * Renders hidden form fields for referrer information about + * the current controller and action. + * + * @return string Hidden fields with referrer information + * @todo filter out referrer information that is equal to the target (e.g. same packageKey) + */ + protected function renderHiddenReferrerFields() + { + $request = $this->renderingContext->getControllerContext()->getRequest(); + $extensionName = $request->getControllerExtensionName(); + $controllerName = $request->getControllerName(); + $actionName = $request->getControllerActionName(); + $actionRequest = [ + '@extension' => $extensionName, + '@controller' => $controllerName, + '@action' => $actionName, + ]; + $this->addHiddenField($this->prefixFieldName('__referrer[@extension]'), $extensionName); + $this->addHiddenField($this->prefixFieldName('__referrer[@controller]'), $controllerName); + $this->addHiddenField($this->prefixFieldName('__referrer[@action]'), $actionName); + $this->addHiddenField($this->prefixFieldName('__referrer[@request]'), $this->hashService->appendHmac(json_encode($actionRequest))); + } + + /** + * Adds the field name prefix to the ViewHelperVariableContainer + */ + protected function addFieldNamePrefixToViewHelperVariableContainer() + { + $fieldNamePrefix = $this->getFieldNamePrefix(); + $this->viewHelperVariableContainer->add(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'fieldNamePrefix', $fieldNamePrefix); + } + + /** + * Renders a hidden form field containing the technical identity of the given object. + * + * @param object $object Object to create the identity field for + * @param string $name Name + * + * @return string A hidden field containing the Identity (UID in TYPO3 Flow, uid in Extbase) of the given object or NULL if the object is unknown to the persistence framework + * @see \TYPO3\CMS\Extbase\Mvc\Controller\Argument::setValue() + */ + protected function renderHiddenIdentityField($object, $name) + { + if ($object instanceof LazyLoadingProxy) { + $object = $object->_loadRealInstance(); + } + if (!is_object($object) + || !($object instanceof AbstractDomainObject) + || ($object->_isNew() && !$object->_isClone())) { + return ''; + } + // Intentionally NOT using PersistenceManager::getIdentifierByObject here!! + // Using that one breaks re-submission of data in forms in case of an error. + $identifier = $object->getUid(); + if ($identifier === null) { + return ''; + } + $name = $this->prefixFieldName($name) . '[__identity]'; + $this->registerFieldNameForFormTokenGeneration($name); + + $this->addHiddenField($name, $identifier); + } + + /** + * Render the request hash field + * + * @return string|void + * @throws \TYPO3\CMS\EXTBASE\Security\Exception\InvalidArgumentForHashGenerationException + */ + protected function renderTrustedPropertiesField() + { + $formFieldNames = $this->viewHelperVariableContainer->get(\TYPO3\CMS\Fluid\ViewHelpers\FormViewHelper::class, 'formFieldNames'); + $requestHash = $this->mvcPropertyMappingConfigurationService->generateTrustedPropertiesToken($formFieldNames, $this->getFieldNamePrefix()); + $this->addHiddenField($this->prefixFieldName('__trustedProperties'), $requestHash); + } + + /** + * Render the request form uid field + * + * @return string|void + * @throws \TYPO3\CMS\EXTBASE\Security\Exception\InvalidArgumentForHashGenerationException + */ + protected function renderFormUidField() + { + $this->addHiddenField($this->prefixFieldName('mail[form]'), $this->arguments['formUid']); + } + + /** + * @param $name + * @param $value + */ + protected function addHiddenField($name, $value) + { + $this->data['hiddenFields'][$this->i]['name'] = $name; + $this->data['hiddenFields'][$this->i]['value'] = $value; + $this->i++; + } +} diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php new file mode 100644 index 0000000..0396076 --- /dev/null +++ b/Configuration/TCA/Overrides/sys_template.php @@ -0,0 +1,13 @@ +run + vendorName = In2code + extensionName = Powermail + pluginName = Pi1 + controller = Form + } + } + } + } + } +} diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md diff --git a/README.md b/README.md index e0c76fd..dbee57f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,18 @@ -# headless_powermail -Connects together EXT:headless and EXT:powermail +# TYPO3 Extension "headless_powermail" - Connects together EXT:headless and EXT:powermail + +Headless Powermail allows you to render Powermail forms in JSON. + +## Features + +- JSON API for Powermail extension +- Powermail standard fields are in JSON +- Some of extra fields are converted to JSON such as: Hidden, Date, File, Content, show HTML, show some text + +## Installation +Install extension using composer\ +``composer require friendsoftypo3/headless_powermail`` + +Then, you should include extension typoscript template, and use provided constants. + +## Development +Development for this extension is happening as part of the TYPO3 PWA initiative, see https://typo3.org/community/teams/typo3-development/initiatives/pwa/ diff --git a/Resources/Private/Layout/Default.html b/Resources/Private/Layout/Default.html new file mode 100644 index 0000000..34e2859 --- /dev/null +++ b/Resources/Private/Layout/Default.html @@ -0,0 +1,3 @@ + + + diff --git a/Resources/Private/Partials/Form/Field/Check.html b/Resources/Private/Partials/Form/Field/Check.html new file mode 100644 index 0000000..be31129 --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Check.html @@ -0,0 +1,44 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + + + + + [ + + + + {f:if(condition:iteration.isLast,else:',')} + + ] + + + diff --git a/Resources/Private/Partials/Form/Field/Content.html b/Resources/Private/Partials/Form/Field/Content.html new file mode 100644 index 0000000..e948acf --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Content.html @@ -0,0 +1,18 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + diff --git a/Resources/Private/Partials/Form/Field/Date.html b/Resources/Private/Partials/Form/Field/Date.html new file mode 100644 index 0000000..f4e9d50 --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Date.html @@ -0,0 +1,23 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + diff --git a/Resources/Private/Partials/Form/Field/File.html b/Resources/Private/Partials/Form/Field/File.html new file mode 100644 index 0000000..e754fcf --- /dev/null +++ b/Resources/Private/Partials/Form/Field/File.html @@ -0,0 +1,21 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + diff --git a/Resources/Private/Partials/Form/Field/Hidden.html b/Resources/Private/Partials/Form/Field/Hidden.html new file mode 100644 index 0000000..05c858d --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Hidden.html @@ -0,0 +1,14 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + diff --git a/Resources/Private/Partials/Form/Field/Html.html b/Resources/Private/Partials/Form/Field/Html.html new file mode 100644 index 0000000..4837d37 --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Html.html @@ -0,0 +1,19 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + diff --git a/Resources/Private/Partials/Form/Field/Input.html b/Resources/Private/Partials/Form/Field/Input.html new file mode 100644 index 0000000..0e9167b --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Input.html @@ -0,0 +1,23 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + diff --git a/Resources/Private/Partials/Form/Field/Radio.html b/Resources/Private/Partials/Form/Field/Radio.html new file mode 100644 index 0000000..c657af4 --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Radio.html @@ -0,0 +1,45 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + + + + + [ + + + + {f:if(condition:iteration.isLast,else:',')} + + ] + + + diff --git a/Resources/Private/Partials/Form/Field/Select.html b/Resources/Private/Partials/Form/Field/Select.html new file mode 100644 index 0000000..78171ea --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Select.html @@ -0,0 +1,35 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + + + + diff --git a/Resources/Private/Partials/Form/Field/Submit.html b/Resources/Private/Partials/Form/Field/Submit.html new file mode 100644 index 0000000..c08a26c --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Submit.html @@ -0,0 +1,16 @@ + + + + + diff --git a/Resources/Private/Partials/Form/Field/Text.html b/Resources/Private/Partials/Form/Field/Text.html new file mode 100644 index 0000000..44534c3 --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Text.html @@ -0,0 +1,17 @@ + + + + + + diff --git a/Resources/Private/Partials/Form/Field/Textarea.html b/Resources/Private/Partials/Form/Field/Textarea.html new file mode 100644 index 0000000..4349706 --- /dev/null +++ b/Resources/Private/Partials/Form/Field/Textarea.html @@ -0,0 +1,23 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + diff --git a/Resources/Private/Partials/Form/FieldLabel.html b/Resources/Private/Partials/Form/FieldLabel.html new file mode 100644 index 0000000..044692c --- /dev/null +++ b/Resources/Private/Partials/Form/FieldLabel.html @@ -0,0 +1,14 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + diff --git a/Resources/Private/Partials/Form/Fields.html b/Resources/Private/Partials/Form/Fields.html new file mode 100644 index 0000000..11830eb --- /dev/null +++ b/Resources/Private/Partials/Form/Fields.html @@ -0,0 +1,10 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + [ + + {f:if(condition:iteration.isLast,else:',')} + + ] + + diff --git a/Resources/Private/Partials/Form/Page.html b/Resources/Private/Partials/Form/Page.html new file mode 100644 index 0000000..5d337a8 --- /dev/null +++ b/Resources/Private/Partials/Form/Page.html @@ -0,0 +1,10 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + diff --git a/Resources/Private/Partials/Form/Pages.html b/Resources/Private/Partials/Form/Pages.html new file mode 100644 index 0000000..fd56e7a --- /dev/null +++ b/Resources/Private/Partials/Form/Pages.html @@ -0,0 +1,9 @@ + + + [ + + {f:if(condition:iteration.isLast,else:',')} + + ] + + diff --git a/Resources/Private/Template/Form/Form.html b/Resources/Private/Template/Form/Form.html new file mode 100644 index 0000000..da29108 --- /dev/null +++ b/Resources/Private/Template/Form/Form.html @@ -0,0 +1,24 @@ +{namespace vh=In2code\Powermail\ViewHelpers} + + + + + + + + + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..5698fa0 --- /dev/null +++ b/composer.json @@ -0,0 +1,41 @@ +{ + "name": "friendsoftypo3/headless_powermail", + "type": "typo3-cms-extension", + "description": "This extension provides integration with powermail to output content from TYPO3 in JSON format.", + "keywords": [ + "TYPO3", + "headless", + "pwa", + "json", + "powermail" + ], + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "Tymoteusz Motylewski", + "role": "Head" + }, + { + "name": "Oskar Dydo", + "role": "Developer" + }, + { + "name": "TYPO3 PWA Initiative", + "role": "Developer", + "email": "extensions@macopedia.com" + } + ], + "require": { + "typo3/cms-core": "^9.5 || ^10.0" + }, + "suggest": { + "friendsoftypo3/headless": "^1.0" + } + "autoload": { + "psr-4": { + "FriendsOfTYPO3\\HeadlessPowermail\\": "Classes" + } + } +} diff --git a/ext_emconf.php b/ext_emconf.php new file mode 100644 index 0000000..d1e0761 --- /dev/null +++ b/ext_emconf.php @@ -0,0 +1,20 @@ + 'Headless Powermail', + 'description' => 'This extension provides way to output content from TYPO3 in JSON format.', + 'state' => 'stable', + 'author' => 'Oskar Dydo', + 'author_email' => 'extensions@macopedia.pl', + 'category' => 'fe', + 'internal' => '', + 'version' => '2.1.0', + 'constraints' => [ + 'depends' => [ + 'typo3' => '9.5.0-10.4.99', + 'frontend' => '9.5.0-10.4.99' + ], + 'conflicts' => [], + 'suggests' => [], + ], +]; diff --git a/ext_icon.png b/ext_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9a0c72b8e6459c2d5a75dcf60629cbd394343194 GIT binary patch literal 658 zcmV;D0&V??P)=t_C3tB^wPe4Zs;jL)M8s04=e;7eJx`p#nT>BAo}P ztOY=S!PofM0f2FmD*!zRBNL{j02Xo`M}X=CM=jf91Zc7}a6vc$fd(|UVUh0wlPHZ1 z2QV%;0ec?WuyIj-?NJP%i34(p3apc>pXgL@Z9%ad0a+DvSJJpJ?n~ zv<-%p2*Hg3q6!(dl(s>eC#rBy$~#~goVRY&XnGlthMlSs&xeUtH%MM|69D83OVe~o z&G!Bz0%WhuCA67s_ZcIso1PcQWPtc!;LuOblLLpJ3;+vo7XqlKGgD6x^k-+Lmf-QN sscjwP&v@)Z4L?N$|M%!SCtm^#0IK}(onZ=9i~s-t07*qoM6N<$f*;i=ng9R* literal 0 HcmV?d00001 diff --git a/ext_localconf.php b/ext_localconf.php new file mode 100644 index 0000000..4bd0d9b --- /dev/null +++ b/ext_localconf.php @@ -0,0 +1,13 @@ + Date: Fri, 10 Jul 2020 13:47:53 +0200 Subject: [PATCH 2/4] Fix composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 5698fa0..c3345cb 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,7 @@ }, "suggest": { "friendsoftypo3/headless": "^1.0" - } + }, "autoload": { "psr-4": { "FriendsOfTYPO3\\HeadlessPowermail\\": "Classes" From 6063221678009385a235c27aa95f9aab36f10e22 Mon Sep 17 00:00:00 2001 From: Oskar Dydo Date: Fri, 10 Jul 2020 14:05:10 +0200 Subject: [PATCH 3/4] Change fluid namespace of Viewhelpers --- Resources/Private/Partials/Form/Field/Check.html | 4 ++-- Resources/Private/Partials/Form/Field/Content.html | 4 ++-- Resources/Private/Partials/Form/Field/Date.html | 4 ++-- Resources/Private/Partials/Form/Field/File.html | 4 ++-- Resources/Private/Partials/Form/Field/Hidden.html | 2 +- Resources/Private/Partials/Form/Field/Html.html | 4 ++-- Resources/Private/Partials/Form/Field/Input.html | 4 ++-- Resources/Private/Partials/Form/Field/Radio.html | 4 ++-- Resources/Private/Partials/Form/Field/Select.html | 6 +++--- Resources/Private/Partials/Form/Field/Text.html | 4 ++-- Resources/Private/Partials/Form/Field/Textarea.html | 4 ++-- Resources/Private/Template/Form/Form.html | 2 +- composer.json | 1 + ext_localconf.php | 2 +- 14 files changed, 25 insertions(+), 24 deletions(-) diff --git a/Resources/Private/Partials/Form/Field/Check.html b/Resources/Private/Partials/Form/Field/Check.html index be31129..0b2be29 100644 --- a/Resources/Private/Partials/Form/Field/Check.html +++ b/Resources/Private/Partials/Form/Field/Check.html @@ -1,6 +1,6 @@ {namespace vh=In2code\Powermail\ViewHelpers} - @@ -8,7 +8,7 @@ field: { label: '{f:render(partial: \'Form/FieldLabel\', arguments: \'{_all}\') -> headless:format.json.decode()}', marker: field.marker, - name: '{hlpowermail:form.generateName(property:\'{field.marker}.\')}', + name: '{headlesspowermail:form.generateName(property:\'{field.marker}.\')}', css: field.css, fieldWrappingClasses: settings.styles.framework.fieldWrappingClasses, fieldAndLabelWrappingClasses: settings.styles.framework.fieldAndLabelWrappingClasses, diff --git a/Resources/Private/Partials/Form/Field/Content.html b/Resources/Private/Partials/Form/Field/Content.html index e948acf..da3d8dc 100644 --- a/Resources/Private/Partials/Form/Field/Content.html +++ b/Resources/Private/Partials/Form/Field/Content.html @@ -1,6 +1,6 @@ {namespace vh=In2code\Powermail\ViewHelpers} - + diff --git a/Resources/Private/Partials/Form/Field/Date.html b/Resources/Private/Partials/Form/Field/Date.html index f4e9d50..10e579e 100644 --- a/Resources/Private/Partials/Form/Field/Date.html +++ b/Resources/Private/Partials/Form/Field/Date.html @@ -1,12 +1,12 @@ {namespace vh=In2code\Powermail\ViewHelpers} - + diff --git a/Resources/Private/Partials/Form/Field/Hidden.html b/Resources/Private/Partials/Form/Field/Hidden.html index 05c858d..b34ed88 100644 --- a/Resources/Private/Partials/Form/Field/Hidden.html +++ b/Resources/Private/Partials/Form/Field/Hidden.html @@ -1,6 +1,6 @@ {namespace vh=In2code\Powermail\ViewHelpers} - + + diff --git a/Resources/Private/Partials/Form/Field/Input.html b/Resources/Private/Partials/Form/Field/Input.html index 0e9167b..6a7caa8 100644 --- a/Resources/Private/Partials/Form/Field/Input.html +++ b/Resources/Private/Partials/Form/Field/Input.html @@ -1,12 +1,12 @@ {namespace vh=In2code\Powermail\ViewHelpers} - + @@ -8,7 +8,7 @@ field: { label: '{f:render(partial: \'Form/FieldLabel\', arguments: \'{_all}\') -> headless:format.json.decode()}', marker: field.marker, - name: '{hlpowermail:form.generateName(property:\'{field.marker}.\')}', + name: '{headlesspowermail:form.generateName(property:\'{field.marker}.\')}', css: field.css, fieldWrappingClasses: settings.styles.framework.fieldWrappingClasses, fieldAndLabelWrappingClasses: settings.styles.framework.fieldAndLabelWrappingClasses, diff --git a/Resources/Private/Partials/Form/Field/Select.html b/Resources/Private/Partials/Form/Field/Select.html index 78171ea..64643df 100644 --- a/Resources/Private/Partials/Form/Field/Select.html +++ b/Resources/Private/Partials/Form/Field/Select.html @@ -1,6 +1,6 @@ {namespace vh=In2code\Powermail\ViewHelpers} - @@ -8,7 +8,7 @@ field: { label: '{f:render(partial: \'Form/FieldLabel\', arguments: \'{_all}\') -> headless:format.json.decode()}', marker: field.marker, - name: '{hlpowermail:form.generateName(property:\'{field.marker}\')}', + name: '{headlesspowermail:form.generateName(property:\'{field.marker}\')}', css: field.css, fieldWrappingClasses: settings.styles.framework.fieldWrappingClasses, fieldAndLabelWrappingClasses: settings.styles.framework.fieldAndLabelWrappingClasses, @@ -24,7 +24,7 @@ - - + diff --git a/Resources/Private/Partials/Form/Field/Textarea.html b/Resources/Private/Partials/Form/Field/Textarea.html index 4349706..532e39e 100644 --- a/Resources/Private/Partials/Form/Field/Textarea.html +++ b/Resources/Private/Partials/Form/Field/Textarea.html @@ -1,12 +1,12 @@ {namespace vh=In2code\Powermail\ViewHelpers} - + diff --git a/composer.json b/composer.json index c3345cb..78f4e95 100644 --- a/composer.json +++ b/composer.json @@ -30,6 +30,7 @@ "require": { "typo3/cms-core": "^9.5 || ^10.0" }, + "version": "2.0.0", "suggest": { "friendsoftypo3/headless": "^1.0" }, diff --git a/ext_localconf.php b/ext_localconf.php index 4bd0d9b..dee5651 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -3,7 +3,7 @@ call_user_func( function ($extensionKey) { - $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['hlpowermail'] = [ + $GLOBALS['TYPO3_CONF_VARS']['SYS']['fluid']['namespaces']['headlesspowermail'] = [ 'FriendsOfTYPO3\HeadlessPowermail\ViewHelpers' ]; From 9613df154a4d1ad7b48c8b6a46dcbaea9853b175 Mon Sep 17 00:00:00 2001 From: Oskar Dydo Date: Fri, 10 Jul 2020 14:27:21 +0200 Subject: [PATCH 4/4] Add constraint for powermail --- ext_emconf.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext_emconf.php b/ext_emconf.php index d1e0761..9a72e48 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -12,7 +12,8 @@ 'constraints' => [ 'depends' => [ 'typo3' => '9.5.0-10.4.99', - 'frontend' => '9.5.0-10.4.99' + 'frontend' => '9.5.0-10.4.99', + 'powermail' => '^7.4', ], 'conflicts' => [], 'suggests' => [],