Merge pull request #787 from bolt/feature/collections-support-all-fields

Feature/collections support all fields
This commit is contained in:
Bob den Otter
2019-12-12 13:23:45 +01:00
committed by GitHub
7 changed files with 116 additions and 59 deletions
+17 -10
View File
@@ -4,16 +4,23 @@
<div :is="element"></div>
</div>
<editor-select
ref="templateSelect"
:value="initialSelectValue"
:name="templateSelectName"
:options="templateSelectOptions"
:allowempty="false"
></editor-select>
<button class="btn btn-secondary" type="button" @click="addCollectionItem">
{{ labels.add_collection_item }}
</button>
<div class="d-flex">
<editor-select
ref="templateSelect"
class="flex-grow-1 mr-2"
:value="initialSelectValue"
:name="templateSelectName"
:options="templateSelectOptions"
:allowempty="false"
></editor-select>
<button
class="btn btn-secondary"
type="button"
@click="addCollectionItem"
>
{{ labels.add_collection_item }}
</button>
</div>
</div>
</template>
@@ -298,16 +298,35 @@ class ContentEditController extends TwigAwareController implements BackendZone
if (isset($formData['collections'])) {
foreach ($formData['collections'] as $collection => $collectionItems) {
$setsInCollection = [];
$fieldsInCollection = [];
$orderArray = array_flip($collectionItems['order']);
//update all fields of the collection and collect their field_name and field_reference
foreach ($collectionItems as $collectionItemName => $collectionItemValue) {
$setDefinition = $content->getDefinition()->get('fields')->get($collection)->get('fields')->get($collectionItemName);
foreach ($collectionItemValue as $hash => $set) {
$this->updateSet($content, $setDefinition, $hash, $set, $locale);
$setsInCollection[] = [
if ($collectionItemName === 'order') {
continue;
}
$collectionItemDefinition = $content->getDefinition()->get('fields')->get($collection)->get('fields')->get($collectionItemName);
if ($collectionItemDefinition['type'] === 'set') {
// if this is a set field, create fields for each field within the set
foreach ($collectionItemValue as $hash => $fieldValue) {
$this->updateSet($content, $collectionItemDefinition, $hash, $fieldValue, $locale);
}
} else {
// if this is any other field
$field = $this->getFieldToUpdate($content, $collectionItemName, $collectionItemDefinition);
$this->updateField($field, $collectionItemValue, $locale);
}
//iterate over all submitted fields within the collection, get the correct index/order, to persist references
//in the collection value
foreach ($collectionItemValue as $hash => $fieldValue) {
$index = $orderArray[$hash];
$fieldsInCollection[$index] = [
'field_name' => $collectionItemName,
'field_reference' => $hash,
'field_type' => $collectionItemDefinition['type'],
];
}
}
@@ -319,9 +338,11 @@ class ContentEditController extends TwigAwareController implements BackendZone
$collectionField = Field::factory($content->getDefinition()->get('fields')->get($collection));
}
//fill in the collection field value with the collected field_name and field_reference
//sort the array keys (1,3,2) ascending (1,2,3)
ksort($fieldsInCollection);
$collectionField->setName($collection);
$collectionField->setValue($setsInCollection);
$collectionField->setValue($fieldsInCollection);
if (! $content->hasField($collectionField->getName())) {
$content->addField($collectionField);
@@ -363,11 +384,13 @@ class ContentEditController extends TwigAwareController implements BackendZone
}
}
private function getFieldToUpdate(Content $content, string $fieldName): Field
private function getFieldToUpdate(Content $content, string $fieldName, $fieldDefinition = ''): Field
{
/** @var Field $field */
$field = null;
$definition = empty($fieldDefinition) ? $content->getDefinition()->get('fields')->get($fieldName) : $fieldDefinition;
if ($content->hasField($fieldName)) {
$field = $content->getField($fieldName);
}
@@ -382,8 +405,7 @@ class ContentEditController extends TwigAwareController implements BackendZone
// Perhaps create a new Field..
if (! $field) {
$fields = $content->getDefinition()->get('fields');
$field = Field::factory($fields->get($fieldName), $fieldName);
$field = Field::factory($definition, $fieldName);
$field->setName($fieldName);
$content->addField($field);
+16 -5
View File
@@ -32,11 +32,21 @@ class CollectionField extends Field implements FieldInterface
$i = 0;
foreach ($thisFieldValues as $thisFieldValue) {
$field = new SetField();
$field->setContent($this->getContent());
$field->setValue($thisFieldValue['field_reference']);
$field->setDefinition('fields', $this->getDefinition()->get('fields')[$thisFieldValue['field_name']]);
$field->setName($thisFieldValue['field_name']);
if ($thisFieldValue['field_type'] === 'set') {
$field = new SetField();
$field->setContent($this->getContent());
$field->setValue($thisFieldValue['field_reference']);
$field->setDefinition($thisFieldValue['field_name'], $this->getDefinition()->get('fields')[$thisFieldValue['field_name']]);
$field->setName($thisFieldValue['field_name']);
} else {
$field = $this->getContent()->getField($thisFieldValue['field_name']);
// The field value persists ALL the values for the same type collection items (e.g. all 'ages') in an array
// To display the value for the current item, we set the value for the specific key only
// As $this->getValue() is called multiple times, clone the object to ensure $field->setValue() is called once per instance
$field = clone $field;
$field->setValue($field->getValue()[$thisFieldValue['field_reference']]);
$field->setDefinition($thisFieldValue['field_name'], $this->getDefinition()->get('fields')[$thisFieldValue['field_name']]);
}
$result['fields'][$i] = $field;
$i++;
@@ -44,6 +54,7 @@ class CollectionField extends Field implements FieldInterface
foreach ($fieldDefinitions as $fieldName => $fieldDefinition) {
$templateField = parent::factory($fieldDefinition, '', $fieldName);
$templateField->setDefinition($fieldName, $this->getDefinition()->get('fields')[$fieldName]);
$templateField->setName($fieldName);
$result['templates'][$fieldName] = $templateField;
}
+23
View File
@@ -36,3 +36,26 @@
</a>
{% endapply %}{% endmacro %}
{% macro generate_collection_fields(collectionField, fields) %}{% apply spaceless %}
{% set fieldsHtml = [] %}
{% for item_field in fields %}
{% set collectionItemName = 'collections[' ~ collectionField.name ~ '][' ~ item_field.definition.name ~ ']' %}
{% if item_field.definition.type == 'set' %}
{% set hash = item_field.hash %}
{% else %}
{# non-set fields do not have hashes, so we create a 'dummy' hash from the current loop index. #}
{% set hash = loop.index0 %}
{% set collectionItemName = collectionItemName ~ '[' ~ hash ~ ']' %}
{% endif %}
{% set new_field %}
{% include '@bolt/_partials/fields/' ~ item_field.type ~ '.html.twig' with
{'field': item_field, 'in_collection': true, 'is_first': loop.index0 == 0, 'is_last': loop.index == fields|length, 'name': collectionItemName, 'collection_name': collectionField.name, 'hash': hash } only %}
{% endset %}
{# set the label manually as set in _base.html.twig, to pass to Collection.vue for templates #}
{% set label = item_field.definition.label|default(item_field.name|default('unnamed')|ucwords) %}
{% set fieldsHtml = fieldsHtml|merge([{'html': new_field, 'hash': hash, 'label': label}]) %}
{% endfor %}
{{ fieldsHtml|json_encode }}
{% endapply %}{% endmacro %}
@@ -96,5 +96,24 @@
{% block field %}
{% endblock %}
{{ postfix|raw }}
{% if in_collection is defined %}
<input type="hidden" name="collections[{{ collection_name }}][order][]" value="{{ hash }}">
<button class='action-move-up-collection-item btn btn-secondary' {% if is_first is defined and is_first %} disabled {% endif %}>
<i class="fas fa-fw fa-chevron-up"></i>
{{ 'collection.move_item_up'|trans }}
</button>
<button class='action-move-down-collection-item btn btn-secondary' {% if is_last is defined and is_last %} disabled {% endif %}>
<i class="fas fa-fw fa-chevron-down"></i>
{{ 'collection.move_item_down'|trans }}
</button>
<button class='action-remove-collection-item btn btn-hidden-danger'>
<i class="fas fa-fw fa-times"></i>
{{ 'collection.remove_item'|trans }}
</button>
{% endif %}
</div>
@@ -1,4 +1,5 @@
{% extends '@bolt/_partials/fields/_base.html.twig' %}
{% import '@bolt/_macro/_macro.html.twig' as macro %}
{% block field %}
{% set labels = {
@@ -6,31 +7,20 @@
} %}
{# get the html for all collection field already in the database #}
{% set existing_fields = [] %}
{% set existing_fields = "" %}
{% if field.value.fields is defined %}
{% for item_field in field.value.fields %}
{% set collectionItemName = 'collections[' ~ field.name ~ '][' ~ item_field.name ~ ']' %}
{% set existing_field %}
{% include '@bolt/_partials/fields/' ~ item_field.type ~ '.html.twig' with
{'field': item_field, 'in_collection': true, 'is_first': loop.index0 == 0, 'is_last': loop.index == field.value.fields|length, 'name': collectionItemName } only %}
{% endset %}
{% set existing_fields = existing_fields|merge([{'html': existing_field, 'hash': item_field.hash}]) %}
{% endfor %}
{% set existing_fields %}{{ macro.generate_collection_fields(field, field.value.fields) }}{% endset %}
{% endif %}
{# get the html template for the collection fields defined in the field definition #}
{% set templated_fields = [] %}
{% for item_field in field.value.templates %}
{% set collectionItemName = 'collections[' ~ field.name ~ '][' ~ item_field.name ~ ']' %}
{% set templated_field %}
{% include '@bolt/_partials/fields/' ~ item_field.type ~ '.html.twig' with {'field': item_field, 'in_collection': true, 'name': collectionItemName} only %}
{% endset %}
{% set templated_fields = templated_fields|merge([{'label': item_field.definition.label, 'html': templated_field, 'hash': item_field.hash}]) %}
{% endfor %}
{% set templated_fields = "" %}
{% if field.value.templates is defined %}
{% set templated_fields %}{{ macro.generate_collection_fields(field, field.value.templates) }}{% endset %}
{% endif %}
<editor-collection
:existing-fields='{{ existing_fields | json_encode }}'
:templates='{{ templated_fields | json_encode }}'
:existing-fields='{{ existing_fields }}'
:templates='{{ templated_fields }}'
:labels='{{ labels | json_encode }}'
></editor-collection>
-15
View File
@@ -11,19 +11,4 @@
{% set setItemName = setName ~ '[' ~ field.value.hash ~ ']' ~ '[' ~ fieldItem.name ~ ']' %}
{% include '@bolt/_partials/fields/' ~ fieldItem.type ~ '.html.twig' with {'field' : fieldItem, 'name' : setItemName} only %}
{% endfor %}
{% if in_collection is defined %}
<button class='action-move-up-collection-item btn btn-secondary' {% if is_first is defined and is_first %} disabled {% endif %}>
<i class="fas fa-fw fa-chevron-up"></i>
{{ 'collection.move_item_up'|trans }}
</button>
<button class='action-move-down-collection-item btn btn-secondary' {% if is_last is defined and is_last %} disabled {% endif %}>
<i class="fas fa-fw fa-chevron-down"></i>
{{ 'collection.move_item_down'|trans }}
</button>
<button class='action-remove-collection-item btn btn-hidden-danger'>
<i class="fas fa-fw fa-times"></i>
{{ 'collection.remove_item'|trans }}
</button>
{% endif %}
{% endblock %}