Skip to content

Commit

Permalink
Merge pull request #20 from Brille24/files
Browse files Browse the repository at this point in the history
Files
  • Loading branch information
JakobTolkemit authored Mar 11, 2019
2 parents 8a1b6b1 + 0143856 commit 34389e6
Show file tree
Hide file tree
Showing 31 changed files with 149 additions and 43 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,5 @@ You can also assign a group and override value prices in the product fixture.
When you finished defining all your fixtures, run `bin/console sylius:fixtures:load` to load your fixtures.

## Things to consider
* This plugin does not take the [tier price plugin](https://packagist.org/packages/brille24/tierprice-plugin) into account. The tier prices will override the pricing model that is implemented here (if you use the default implementation that comes with the plugin)
* Just like the tier price plugin, this plugin overrides the update cart functionality if you want to implement an event bases solution, you need to comment out the `Brille24\SyliusCustomerOptionsPlugin\Services\OrderPricesRecalculator` in the `services.xml` in the plugin's resource folder.
* Saving files as customer defined values as the values are currently stored as a string in the database
1 change: 0 additions & 1 deletion features/bootstrap/FeatureContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ class FeatureContext implements Context
public function __construct()
{
}

}
5 changes: 4 additions & 1 deletion features/shop/viewing_product.feature
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ Feature: Viewing products with customer options
And I have a customer option named "Text Option" with type "text"
And I have a customer option named "Date Option" with type "date"
And I have a customer option named "Number Option" with type "number"
And I have a customer option named "File Option" with type "file"

And I have a customer option group named "Some Group"
And customer option group "Some Group" has option "Select Option"
And customer option group "Some Group" has option "Text Option"
And customer option group "Some Group" has option "Date Option"
And customer option group "Some Group" has option "Number Option"
And customer option group "Some Group" has option "File Option"

And the store has a product "Cool Product"
And product "Cool Product" has the customer option group "Some Group"
Expand All @@ -32,4 +34,5 @@ Feature: Viewing products with customer options
And I should see customization for "Text Option"
Then I should see customization for "Select Option"
And I should see customization for "Date Option"
And I should see customization for "Number Option"
And I should see customization for "Number Option"
And I should see customization for "File Option"
6 changes: 5 additions & 1 deletion features/shop/viewing_product_in_cart.feature
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ Feature: Viewing product with customer options in cart
And I have a customer option named "Text Option" with type "text"
And I have a customer option named "Date Option" with type "date"
And I have a customer option named "Number Option" with type "number"
And I have a customer option named "File Option" with type "file"

And I have a customer option group named "Some Group"
And customer option group "Some Group" has option "Select Option"
And customer option group "Some Group" has option "Text Option"
And customer option group "Some Group" has option "Date Option"
And customer option group "Some Group" has option "Number Option"
And customer option group "Some Group" has option "File Option"

And the store has a product "Cool Product"
And product "Cool Product" has the customer option group "Some Group"
Expand All @@ -32,6 +34,7 @@ Feature: Viewing product with customer options in cart
And I entered value "Custom text" for option "Text Option" for this order
And I entered value "2018-06-18" for option "Date Option" for this order
And I entered value "42" for option "Number Option" for this order
And I entered value "/hello" for option "File Option" for this order
When I see the summary of my cart
Then I should see "Customer Options"
And I should see "Select Option: Value 1"
Expand All @@ -40,10 +43,11 @@ Feature: Viewing product with customer options in cart
And I should see "Date Option: 06"
And I should see "Date Option: 2018"
And I should see "Number Option: 42"
And I should see "File Option: File content"

@ui
Scenario: Having a product without options in the cart
Given the store has a product "Boring Product"
And I have 1 products "Boring Product" in the cart
When I see the summary of my cart
Then I should not see "Customer Options"
Then I should not see "Customer Options"
2 changes: 1 addition & 1 deletion src/Entity/CustomerOptions/CustomerOption.php
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ public function setConfiguration(array $configuration): void
{
// Setting the new values
foreach ($configuration as $key => $value) {
$optionKey = str_replace('_', '.', $key);
$optionKey = str_replace(':', '.', $key);
$this->configuration[$optionKey]['value'] = $value;
}

Expand Down
10 changes: 7 additions & 3 deletions src/Entity/CustomerOptions/CustomerOptionValue.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,21 @@ public function getPriceForChannel(
$prices = $this->getPricesForChannel($channel);

if (!$ignoreActive) {
$prices = $prices->filter(function (COValuePriceInterface $price) { return $price->isActive(); });
$prices = $prices->filter(function (COValuePriceInterface $price) {
return $price->isActive();
});
}

if (count($prices) > 1) {
// Get the prices with product references (aka. overrides) first
$prices = $prices->toArray();

return array_reduce(
$prices, function ($accumulator, COValuePriceInterface $price): COValuePriceInterface {
$prices,
function ($accumulator, COValuePriceInterface $price): COValuePriceInterface {
return $price->getProduct() !== null ? $price : $accumulator;
}, reset($prices)
},
reset($prices)
);
} elseif (count($prices) === 1) {
return $prices->first();
Expand Down
4 changes: 3 additions & 1 deletion src/Enumerations/CustomerOptionTypeEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,10 @@ public static function getConfigurationArray(): array
'brille24.form.config.default_value' => ['type' => 'boolean', 'value' => true],
],
self::FILE => [
'brille24.form.config.max.file_size' => ['type' => 'text', 'value' => '10MB'],
'brille24.form.config.max.file_size' => ['type' => 'text', 'value' => '10M'],
'brille24.form.config.min.file_size' => ['type' => 'text', 'value' => '0B'],
'brille24.form.config.multiple' => ['type' => 'boolean', 'value' => false],
'brille24.form.config.allowed_types' => ['type' => 'text', 'value' => ''],
],
];
}
Expand Down
8 changes: 6 additions & 2 deletions src/Factory/CustomerOptionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,12 @@ public function generateRandomConfiguration(int $amount): array

/** @var CustomerOptionGroupInterface[] $groups */
$groups = $this->customerOptionGroupRepository->findAll();
$groupCodes = array_map(function (CustomerOptionGroupInterface $group) { return $group->getCode(); },
$groups);
$groupCodes = array_map(
function (CustomerOptionGroupInterface $group) {
return $group->getCode();
},
$groups
);

$options['groups'] = [];
if (count($groupCodes) > 0) {
Expand Down
4 changes: 3 additions & 1 deletion src/Factory/CustomerOptionGroupFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ public function __construct(

public function generateRandom(int $amount): array
{
$productCodeGetter = function (CodeAwareInterface $codeAware) { return $codeAware->getCode(); };
$productCodeGetter = function (CodeAwareInterface $codeAware) {
return $codeAware->getCode();
};

$customerOptionsCodes = array_map($productCodeGetter, $this->customerOptionRepository->findAll());
$productCodes = array_map($productCodeGetter, $this->productRepository->findAll());
Expand Down
4 changes: 3 additions & 1 deletion src/Factory/CustomerOptionValuePriceFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ public function generateRandomConfiguration(int $amount): array
{
$prices = [];
$allChannelCodes = array_map(
function (ChannelInterface $channel) { return $channel->getCode(); },
function (ChannelInterface $channel) {
return $channel->getCode();
},
$this->channelRepository->findAll()
);

Expand Down
3 changes: 2 additions & 1 deletion src/Factory/ProductFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ public function create(array $options = []): ProductInterface
[
'customer_option_group' => null,
'customer_option_value_prices' => [],
], $options
],
$options
);

$customerOptionGroupConfig = $options['customer_option_group'];
Expand Down
3 changes: 2 additions & 1 deletion src/Form/CustomerOptionConfigurationType.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public function buildForm(FormBuilderInterface $builder, array $options): void

// Adding form field for configuration option based on type
$form->add(
str_replace('.', '_', $key), $formTypeClass,
str_replace('.', ':', $key),
$formTypeClass,
array_merge(['data' => $data, 'label' => $key], $formTypeConfig)
);
}
Expand Down
4 changes: 3 additions & 1 deletion src/Form/CustomerOptionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ function ($a) {

return $a;
},
function ($a) { return $a; }
function ($a) {
return $a;
}
));
}

Expand Down
8 changes: 6 additions & 2 deletions src/Form/Extensions/ProductTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ public function buildForm(FormBuilderInterface $builder, array $options): void

$builder
->add(
'customer_option_group', EntityType::class, [
'customer_option_group',
EntityType::class,
[
'class' => CustomerOptionGroup::class,
'placeholder' => 'Please choose',
'empty_data' => null,
Expand All @@ -55,7 +57,9 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
);

$builder->add(
'customer_option_value_prices', CollectionType::class, [
'customer_option_value_prices',
CollectionType::class,
[
'entry_type' => CustomerOptionValuePriceType::class,
'entry_options' => [
'product' => $product,
Expand Down
17 changes: 15 additions & 2 deletions src/Form/Product/ShopCustomerOptionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
}

$builder->addEventListener(
FormEvents::POST_SET_DATA, function (FormEvent $event) {
FormEvents::POST_SET_DATA,
function (FormEvent $event) {
$data = $event->getData();
$form = $event->getForm();
if (!is_array($data)) {
Expand Down Expand Up @@ -158,6 +159,16 @@ private function getFormConfiguration(
}
}

if ($customerOptionType === CustomerOptionTypeEnum::FILE) {
/*
* Here we give the Customer Option File Type a special block name to override it in a form theme.
*
* The reason for this is when submitting the form on the "add to cart" button files are not transmitted.
* Therefore we added a hidden field and transmit the base64 encoding of the file.
*/
$configuration['block_name'] = 'file_type';
}

return array_merge($formOptions, $defaultOptions, $configuration);
}

Expand Down Expand Up @@ -202,7 +213,9 @@ private function buildValueString(CustomerOptionValueInterface $value, ProductIn
}

$valueString = $price->getValueString(
$this->currencyContext->getCurrencyCode(), $this->localeContext->getLocaleCode(), $this->moneyFormatter
$this->currencyContext->getCurrencyCode(),
$this->localeContext->getLocaleCode(),
$this->moneyFormatter
);
$name = $value->getName();

Expand Down
2 changes: 1 addition & 1 deletion src/Resources/config/doctrine/OrderItemOption.orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<field name="customerOptionValueCode" nullable="true"/>
<field name="customerOptionValueName" nullable="true"/>
<field name="optionValue" nullable="true"/>
<field name="optionValue" nullable="true" type="text"/>

<many-to-one target-entity="Brille24\SyliusCustomerOptionsPlugin\Entity\CustomerOptions\CustomerOptionValueInterface"
field="customerOptionValue" optional="true"
Expand Down
2 changes: 2 additions & 0 deletions src/Resources/translations/messages.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ brille24:
customer_option_groups: Kundenoptionengruppen
required: Erforderlich
product_customization: Produktanpassung
file_content: Dateiinhalt
pricing:
fixed_amount: Feste Menge
percent: Prozent
Expand Down Expand Up @@ -57,6 +58,7 @@ brille24:
date: Maximum Datum
number: Maximum Zahl
default_value: Standard-Wert
allowed_types: Erlaubte Dateitypen
validators:
condition:
greater: ">"
Expand Down
2 changes: 2 additions & 0 deletions src/Resources/translations/messages.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ brille24:
customer_option_group: Customer Option Group
required: Required
product_customization: Product customization
file_content: File content
pricing:
fixed_amount: Fixed amount
percent: Percent
Expand Down Expand Up @@ -56,6 +57,7 @@ brille24:
date: Maximum date
number: Maximum number
default_value: Default value
allowed_types: Allowed file types
validators:
condition:
greater: ">"
Expand Down
29 changes: 29 additions & 0 deletions src/Resources/views/Form/product_theme.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{# We are overriding the customer option file type. For more information see: ShopCustomerOptionType.php #}
{% block _sylius_add_to_cart_customer_options_file_type_widget %}
<input type="{{type}}" name="{{full_name}}" id="{{id}}" onChange="uploadPicture(event)" />
<input type="hidden" name="{{full_name ~ '[data]' }}" id="{{ id ~ '_data'}}" />

<script>
fr = new FileReader();
function uploadPicture(evt) {
const dataTag = document.getElementById(`${evt.target.id}_data`);
fr.onload = (e) => {
const content = e.target.result;
const base64Encoding = content.indexOf('base64,');
if(base64Encoding === -1) {
throw Error('Source did not decode to base64');
}
if(dataTag.value.length > 0) {
dataTag.value += '|';
}
dataTag.value += content;
};
dataTag.value = '';
Array.from(evt.target.files).forEach(file => fr.readAsDataURL(file));
}
</script>
{% endblock %}
8 changes: 3 additions & 5 deletions src/Resources/views/Product/Shop/_customerOptions.html.twig
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
{% form_theme form.customer_options with 'Brille24SyliusCustomerOptionsPlugin:Form:product_theme.html.twig' %}

{% if product.customerOptionGroup != null %}
{% include 'Brille24SyliusCustomerOptionsPlugin:all:_date.html.twig' only %}

<div class="ui segment">
<h4>{{ 'brille24.ui.product_customization'|trans }}</h4>
{% for customerOption in form.customer_options %}
{{ form_row(customerOption) }}
{% endfor %}
{{ form_widget(form.customer_options) }}
</div>
{% endif %}
{% endif %}
10 changes: 9 additions & 1 deletion src/Resources/views/Product/_customerOptions.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,15 @@
{% for orderItemOption in configuration %}
<div class="item" data-sylius-option-name="{{ orderItemOption.customerOptionCode }}">
{{ orderItemOption.customerOptionName }}:
{{ orderItemOption.customerOptionValueName }}
{% if(orderItemOption.customerOption.type == 'file') %}
{% if 'image' in orderItemOption.customerOptionValueName %}
<img src="{{ orderItemOption.customerOptionValueName }}" style="max-width: 200px" />
{% else %}
{{ 'brille24.ui.file_content'|trans }}
{% endif %}
{% else %}
{{ orderItemOption.customerOptionValueName }}
{% endif %}
{{ renderPrice(orderItemOption) }}
</div>
{% endfor %}
Expand Down
9 changes: 7 additions & 2 deletions src/Services/ConstraintCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ConstraintCreator
*/
public static function getValueFromConfiguration(array $configuration, string $key)
{
if (!isset($configuration[$key]['value'])) {
if (!array_key_exists($key, $configuration)) {
return null;
}

Expand Down Expand Up @@ -54,7 +54,12 @@ public static function createFromConfiguration(string $type, array $configuratio

return new Length($lengthRange);
case CustomerOptionTypeEnum::FILE:
return new File(['maxSize' => $getFromConfiguration('brille24.form.config.max.file_size')]);
$allowedFileTypes = explode(',', (string) $getFromConfiguration('brille24.form.config.allowed_types'));

return new File([
'maxSize' => $getFromConfiguration('brille24.form.config.max.file_size'),
'mimeTypes' => array_map('trim', $allowedFileTypes),
]);
case CustomerOptionTypeEnum::DATE:
case CustomerOptionTypeEnum::DATETIME:
$dateRange = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ public function validate($value, Constraint $constraint): void
*
* So in this line we look for the array key that contains min and max
*/
$minKeys = array_filter(array_keys($value), function (string $key) { return is_int(strpos($key, 'min')); });
$maxKeys = array_filter(array_keys($value), function (string $key) { return is_int(strpos($key, 'max')); });
$minKeys = array_filter(array_keys($value), function (string $key) {
return is_int(strpos($key, 'min'));
});
$maxKeys = array_filter(array_keys($value), function (string $key) {
return is_int(strpos($key, 'max'));
});

if (count($minKeys) === 0 || count($maxKeys) === 0) {
return;
Expand Down
Loading

0 comments on commit 34389e6

Please sign in to comment.