Sonata admin export fields with collection fields - symfony

I'm trying to make custom columns for export, but I can't access children. Is there any possibility to do that ?
My code at this moment looks like this:
public function getExportFields()
{
return [
'ID' => 'id',
'Transaction number' => 'transactionNumber',
'Loan account' => 'loan',
'Loan name' => 'loan.name',
'Amount' => 'amount',
//'Amount ($)' => '',
'Transaction type' => 'transactionCategory',
'Reference' => 'transactionAssociation.cashTransaction.transactionNumber',
'Date' => 'date'
];
}
I can't find out a solution. I was thinking to use PropertyAccess, but I don't know how to integrate it here.
I'm using Symfony 3.X with Sonata.

To get the collection records in export you cannot directly do this by specifying the property with association, A workaround for to achieve this you can define a new unmapped property in your entity with a getter function which will get all the collection details like in your main entity define new property as
protected $cashTransactionNumber;
public function getCashTransactionNumber()
{
$cashTransactionNumber = array();
$i = 1;
foreach ($this->getTransactionAssociation() as $key => $transactionAssociation) {
$cashTransactionNumber [] = $i .
') No.:' . $transactionAssociation->somemethod()->__toString()() .
/** Other properties */;
$i++;
}
return $this->cashTransactionNumber = join(' , ', $cashTransactionNumber );
}
then in your getExportFields() method call this property
public function getExportFields(){
return array(
'Reference'=>'cashTransactionNumber ',
....// Other properties
);
}
Reference: Exporting one to many relationship on sonata admin

Related

How do you modify entity references on a form in a custom ajax action in Drupal 8?

I have added a custom button to a form:
$form['actions']['autotag_content'] = [
'#type' => 'button',
'#value' => 'Autotag Content',
'#ajax' => [
'callback' => ['\Drupal\taxonomy_migrate\taggerService', 'tagContent'],
'wrapper' => ['block-adminimal-theme-content'],
'progress' => [
'type' => 'throbber',
'message' => 'Tagging content',
],
],
];
Then in the callback I want to add or remove entities from an entity reference field on the form. This would then get sent back to the browser and rerendered. I don't want the changes to be save, I just want them populated in the form and then the user can accept the changes.
For the sake of this example, I have simplified this to just demonstrate the point. I would like to add two entity references to field_tax_subjects and have the frontend form rerender. Currently, the frontend form rerenders, but doesn't reflect the changes
public static function tagContent(array &$form, FormStateInterface &$form_state) {
$node = $form_state->getFormObject()->getEntity();
$node->field_tax_subjects[] = 12345;
$node->field_tax_subjects[] = 23456;
$form = \Drupal::service('entity.form_builder')->getForm($node);
$form_state->setRebuild();
return $form;
}
my answer is just for in case your ajax is working
because in your question you have'nt full code of form
also its not clear its node form or something else
any way
If your ajax is working you only have to correct how to set value for entity reference field and term reference filed
for entity reference and term reference
public static function tagContent(array &$form, FormStateInterface &$form_state) {
$node = $form_state->getFormObject()->getEntity();
// for entity refrence
$node->field_tax_subjects[]['target_id'] = 12345;
$node->field_tax_subjects[]['target_id'] = 23456;
// for term reference
//$node->field_tax_subjects[]['tid'] = 12345;
//$node->field_tax_subjects[]['tid'] = 23456;
$form = \Drupal::service('entity.form_builder')->getForm($node);
$form_state->setRebuild();
return $form;
}
HOPE THIS HELP YOU
THANKS

Adding elements to a field widget in Drupal 8

What I need to accomplish is adding a link to a node to field widgets (the node contains the formatted instructions to properly compile the field).
So far I've been able to add the node reference field in the field config form, using Third Party Settings:
function mymodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form_id === 'field_config_edit_form' && $form_state->getFormObject()->getEntity()->get('entity_type') == 'myentity') {
$field = $form_state->getFormObject()->getEntity();
$help_page_id = $field->getThirdPartySetting('mymodule', 'help_page_id');
$form['help_page_id'] = array(
'#type' => 'entity_autocomplete',
'#title' => t('Help page'),
'#target_type' => 'node',
'#selection_handler' => 'default',
'#selection_settings' => array(
'target_bundles' => array('help_page'),
),
'#default_value' => $help_page_id ? Node::load($help_page_id) : NULL,
'#weight' => 100,
);
$form['#entity_builders'][] = 'mymodule_form_field_config_edit_form_builder';
}
}
Now I'm having troubles retrieving this information when showing the form, and altering the field widget in order to display the link.
Using hook_field_widget_form_alter, I cannot get the custom configuration value from the arguments I have:
function mymodule_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
}
I guess I have to load the field configuration entity, but I don't know how.
I didn't test it, but something like this should work:
function mymodule_field_widget_form_alter(&$element, \Drupal\Core\Form\FormStateInterface $form_state, $context) {
// Add a suffix to widget form elements for all fields of type entity_reference.
$field_definition = $context['items']->getFieldDefinition();
if ($field_definition->getType() == 'entity_reference') {
// TODO: Render the node link to $link
$element['#suffix'] = $link;
}
}

How to wrap field in custom markup?

Situation
I have a custom module that is using hook_field_formatter_info() to add an "fancy" option to the image field in the manage display of a content type. When this option is chosen I want to be able to surround the ENTIRE field in custom divs and markup. I want the solution to be a hook in my custom module and not a template override.
Process
A user wants the display of an image field to be the "fancy" option. They check it in the drop down and click save from the content types Manage Display admin page. Now on that content type node there should be custom markup surrounding the entire field even if there are multiple images, the new markup should surround ALL the images and not each individual image.
hook_field_formatter_view
hook_field_formatter_view seems to demand it's output be an array and I can't seem to be able to wrap the output in a div.
Template overrides
I can't just make a field.tpl.php for the specific field because like I initially mentioned I need to be able to switch themes and the module still work like normal. Unless there is a way to get my module to override any field where said field has hook_field_formatter_info() set specifically.
/**
* Implements hook_field_formatter_view().
*/
function bootstrap_modal_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
foreach ($items as $delta => $item) {
if ($index === NULL || $index === $delta) {
$element[$delta] = array(
'#theme' => 'bootstrap_modal_image_formatter',
'#item' => $item,
'#entity_type' => $entity_type,
'#entity' => $entity,
'#node' => $entity, // Left for legacy support.
'#field' => $field,
'#display_settings' => $display['settings'],
'#delta' => $delta,
);
}
}
// $element = '<div id="CUSTOMDIVSTUFF">' . $element . '</div>';
return $element;
}
And here is the #theme function:
function theme_bootstrap_modal_image_formatter($variables) {
$item = $variables['item'];
$entity_type = $variables['entity_type'];
$entity = $variables['entity'];
$field = $variables['field'];
$settings = $variables['display_settings'];
$image = array(
'path' => $item['uri'],
'alt' => isset($item['alt']) ? $item['alt'] : '',
'title' => isset($item['title']) ? $item['title'] : '',
'style_name' => $settings['bootstrap_modal_node_style'],
);
if (isset($item['width']) && isset($item['height'])) {
$image['width'] = $item['width'];
$image['height'] = $item['height'];
}
if (isset($item['attributes'])) {
$image['attributes'] = $item['attributes'];
}
// Allow image attributes to be overridden.
if (isset($variables['item']['override']['attributes'])) {
foreach (array('width', 'height', 'alt', 'title') as $key) {
if (isset($variables['item']['override']['attributes'][$key])) {
$image[$key] = $variables['item']['override']['attributes'][$key];
unset($variables['item']['override']['attributes'][$key]);
}
}
if (isset($image['attributes'])) {
$image['attributes'] = $variables['item']['override']['attributes'] + $image['attributes'];
}
else {
$image['attributes'] = $variables['item']['override']['attributes'];
}
}
$entity_title = entity_label($entity_type, $entity);
if ($style_name = $settings['bootstrap_modal_image_style']) {
$path = image_style_url($style_name, $image['path']);
}
else {
$path = file_create_url($image['path']);
}
$caption = 'some value';
$gallery_id = 'some value';
return theme('bootstrap_modal_imagefield', array('image' => $image, 'path' => $path, 'title' => $caption, 'gid' => $gallery_id));
}
Been working on this for days, I'm drowning here.
This is possible via HOOK_process_field(). Use this hook to define a new template file for your field by adding it to theme_hook_suggestions array (place the template file in your module directory, because you wanted to change the theme -as you mentioned-). More info about field template suggestions.
Then, you will need to add the module path to drupal theme registry, so it picks up the template file. Demo.
I found out it was:
function bootstrap_modal_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array(
'#prefix' => '<div class="wrapper">',
'#suffix' => '</div>',
);

Getting random path hierarchy for CCK fields inside form array

I have created a custom entity and i'm using CCK fields. Each bundle has it's own fields. For example:
function MYMODULE_install() {
// Check if our field is not already created.
if (!field_info_field('field_myField')) {
$field = array(
'field_name' => 'date_field',
'type' => 'list_text',
);
field_create_field($field);
}
//Enable is executed only once.
function bundle_callback_enable() {
// Create the instance on the bundle.
$instance = array(
'field_name' => 'date_field',
'entity_type' => 'payment_method',
'label' => 'Expiration Date',
'bundle' => 'card',
'required' => TRUE,
'settings' => array();
field_create_instance($instance);
}
My bundles are created from individual modules, so in each install file i am creating the respective fields.
Yesterday i tried to add validation callback functions in those fields and i saw something weird inside form array. Fields with type="text" had the path:
$form[field_name]['und'][0][value] //<! expectable
but fields with type='list_text' had only the path:
$form[field_name]['und'] //<! unexpectable
I couldn't find any solution and i've solved it with this:
function &get_cck_path_value( $field_name, &$form_path) {
$field = null
if ( isset( $form_path[$field_name][LANGUAGE_NONE] ) ) {
$field = &$form_path[$field_name][LANGUAGE_NONE]
}elseif(isset($form_path[$field_name][LANGUAGE_NONE][0])) {
$field = &$form_path[$field_name][LANGUAGE_NONE][0]['value'];
}
return $field;
}
I don't like this approach. Is too hucky. Can you tell me if that is a cck feature or bug?
I can't understand when it decides where to put the values( All the process is fulfilled through the "field_attach_form( ... )" )?
Have you faced any problem like this?
Thanks in advance.
Thandem.
I believe that you are seeing the abbreviated form field in validation because the field had no value entered into it and no default value was defined for it. There is no value, so no array is present to store the value.

Map array to entity in Symfony2/Doctrine2

I'm using the DoctrineFixtures bundle to create example entities during development. In my ORM fixtures load() method, I define the data as associative arrays and create the entity object in a loop.
<?php
// ...
public function load($manager) {
$roleDefs = array(
'role-1' => array(
'role' => 'administrator'
),
'role-2' => array(
'role' => 'user'
),
);
foreach($roleDefs as $key => $roleDef) {
$role = new Role();
$role->setRole($roleDef['role']);
$manager->persist($role);
$this->addReference($key, $role);
}
$manager->flush();
}
I always use the same array schema. Every array element uses the property name (in underscore notation) of the entity as index. If the entity structure becomes more complex, there are a lot of $entity->setMyProperty($def['my_property']); lines.
I think the problem of mapping propertynames to setter methods is a very common problem in Symfony and Doctrine as this type of mapping is found in many situations (e.g. mapping forms to entities).
Now I'm wondering if there is a built-in method that can be used for mapping. It would be nice to have a solution like
foreach($defs as $key => $def) {
$entity = $magicMapper->getEntity('MyBundle:MyEntity', $def);
// ...
}
Has someone an idea how this can be achieved?
Thanks a lot,
Hacksteak
I sometimes use loops when creating fixtures. I'm not sure if this solution fits your requirements, but I find that the most flexible way to build fixtures and quickly add new properties over time if you need is to do the following... Assuming the creation of a bunch of blog posts:
// an array of blog post fixture values
$posts = array(
array(
'title' => 'Foo',
'text' => 'lorem'
'date' => new \DateTime('2011-12-01'),
),
array(
'title' => 'Bar',
'text' => 'lorem'
'date' => new \DateTime('2011-12-02'),
),
// more data...
);
// loop over the posts
foreach ($posts as $post) {
// new entity
$post = new Post();
// now loop over the properties of each post array...
foreach ($post as $property => $value) {
// create a setter
$method = sprintf('set%s', ucwords($property)); // or you can cheat and omit ucwords() because PHP method calls are case insensitive
// use the method as a variable variable to set your value
$post->$method($value);
}
// persist the entity
$em->persist($post);
}
This way you can add more properties by just adding the new values to your array.

Resources