Sylius - Entity variable value doesn't load in a form - symfony

I decided to write a new feature to Sylius. Now, products has availableOn parameter, but in some situations (like selling tickets for concert,which takes place on particual day) also availableTo would be very usefull.
So I added variable to database
<field name="availableTo" column="available_to" type="datetime" nullable="true">
<gedmo:versioned />
</field>
Added parameter to Product and Variant model as well,added to constructor
$this->availableTo = new \DateTime();
added method definitions to ProductInterace and VariantInterface.
Add label and widget to layout
{{ form_label(form.masterVariant.availableTo) }}
{{ form_widget(form.masterVariant.availableTo, {'label': false})}}
Add it to VariantType builder also:
->add('availableTo', 'datetime', array(
'date_format' => 'y-M-d',
'date_widget' => 'choice',
'time_widget' => 'text',
'label' => 'sylius.form.product_variant.available_to'
))
And everything works fine except when I'm in editing mode the loaded value isn't from database (saving works ok, so I can type date, save and this is stored in database and displaying correctly in other views). There is a value 2010-01-01 without hours. What can I do to fix it?

The solution of this problem was I didn't add this field in mapped-superclass in Variant.orm.xml file
<mapped-superclass name="Sylius\Component\Product\Model\Variant" table="sylius_product_variant">
<field name="availableOn" column="available_on" type="datetime" nullable="true" />
<field name="availableTo" column="available_to" type="datetime" nullable="true" />
</mapped-superclass>

Related

Unable to delete Entity with Many to Many related objects using SF2 Form

I have a activity planning system and i'm facing an issue. My main item is called AircrewAvailability and is linked to a Period item through a Many To Many relation (the Period must stay agnostic so it can be used by other entities without storing their ids).
This availability is displayed on a FullCalendar system : Each period of each availability is an event on the FullCalendar. When clicking on the FullCalendar, we access to the CRUD form.
Create and Edit work both fine, but Delete is troublesome. When i try to remove an Availability, the ORM tries to delete the Period but does not touch to the relation table (aircrew_availability_period), so I get an Integrity constraint violation (which makes perfect sense).
Here are my mappings :
Availability entity :
<entity name="Mouke\Component\Availability\Model\AircrewAvailability" table="TBL_aircrew_availability">
<id name="id" length="40">
<generator strategy="CUSTOM"/>
<custom-id-generator class="Mouke\Component\Resource\Doctrine\ORM\Id\Sha1IdGenerator"/>
</id>
<many-to-many target-entity="Mouke\Component\Application\Model\PeriodInterface" field="periods" orphan-removal="true" fetch="EAGER">
<cascade>
<cascade-all/>
</cascade>
<join-table name="aircrew_availability_period">
<join-columns>
<join-column name="aircrew_availability_id"/>
</join-columns>
<inverse-join-columns>
<join-column name="period_id"/>
</inverse-join-columns>
</join-table>
<gedmo:versioned/>
</many-to-many>
</entity>
</doctrine-mapping>
Period entity :
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping">
<entity name="Mouke\Component\Application\Model\Period" table="TBL_period">
<id name="id" column="id" type="string" length="40">
<generator strategy="CUSTOM"/>
<custom-id-generator class="Mouke\Component\Resource\Doctrine\ORM\Id\Sha1IdGenerator"/>
</id>
<field name="startedAt" column="started_at" type="datetime"/>
<field name="endedAt" column="ended_at" type="datetime"/>
</entity>
</doctrine-mapping>
About my Forms, here the concerned part :
Availability form :
$builder->add('periods', CollectionType::class, [
'entry_type' => PeriodType::class,
'label' => 'Periods',
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'attr' => [
'class' => 'ajax-collection section-no-padding',
],
]);
Period form :
$builder
->add('startedAt', DateTimePickerType::class, [
'label' => 'model.started_at',
'model_timezone' => $options['model_timezone'],
])
->add('endedAt', DateTimePickerType::class, [
'label' => 'model.ended_at',
'model_timezone' => $options['model_timezone'],
]);
The tricky part : I can delete a period from an availability, no problem. But if an availability has no period, it is not displayed in my calendar so you can't edit it anymore. Not only "ghost entity" may have side effects that I don't want to deal with, but also it isn't user friendly to "delete periods" to delete the whole availability, especially when you have a huge "Delete" button in the bottom of the form.
Any idea on the issue ?
Missed the on-delete="CASCADE" notation :
<join-table name="aircrew_availability_period">
<join-columns>
<join-column name="aircrew_availability_id" on-delete="CASCADE"/>
</join-columns>
<inverse-join-columns>
<join-column name="period_id" on-delete="CASCADE"/>
</inverse-join-columns>
</join-table>

Sonata + Fos_user - How to display only entities related to the user?

I have users who are venue managers. I want them to be able to manage their places and events that are happening in these places.
I created fos_user_user and there I built relations to places:
<entity name="Application\Sonata\UserBundle\Entity\User" table="fos_user_user">
<id name="id" column="id" type="integer">
<generator strategy="AUTO" />
</id>
<many-to-many field="places" target-entity="EchoBundle\Entity\Place">
<join-table name="users_places">
<join-columns>
<join-column name="user_id" referenced-column-name="id" />
</join-columns>
<inverse-join-columns>
<join-column name="place_id" referenced-column-name="id" />
</inverse-join-columns>
</join-table>
</many-to-many>
</entity>
So now, I can manage users and add places that they manage. It works fine.
Questions:
How can I filter so once they log in they only see their own places?
How can I allow them to only add events to their own places? Currently when you add an event you have a full list of places to select from.
How can I filter all events so that they only see events related to places they manage?
I looked at "CUSTOMIZING THE QUERY USED TO GENERATE THE LIST" in the Sonata documentation but don't know how to use it. I tried to add security queries found in answers on StackOverflow from 4 years ago but it didn't work.
In your Admin class you can override createQuery (you should check and fix example below to meet your app model) ;)
This solution will cover question 1 and 3.
public function createQuery($context = 'list')
{
$query = parent::createQuery($context);
$aliases = $query->getRootAliases();
$query
->leftJoin($aliases[0] . '.users_places', 'users_places')
->andWhere($query->expr()->eq('users_places.user_id', ':user') )
->setParameter('user', $this->getConfigurationPool()->getContainer()->get('security.token_storage')->getToken()->getUser());
return $query;
}
Question 2:
If you are using sonata formMapper and configureFormFields method, you can pass Custom Query Builder in field definition.
$formMapper
->add('events', 'sonata_type_model', [
'label' => 'Events',
'placeholder' => 'Select ...',
'required' => true,
'query' => $blQueryBuilder,
]);

Symfony2 Forms: How do I create a collection of 'entity' forms

I have a one to many unidirectional relationship in my model. A User has one of many Status.
Using doctrine these are mapped as a unidirectional many-to-many with a unique constraint on one of the join columns.
I'd like to use a symfony form to select a status from the status table, submit the form and have symfony persist the relationship.
I've tried two approaches:
Using the Entity form type, however this produces an error (due to the many-to-many relationship doctrine expects to receive an instance of ArrayCollection rather than a single status object.
Using a collection entity objects. When using this approach an empty div with the id status is rendered in the form. Where as I expected a select box to appear containing status options.
Here is the code. Where am I wrong?
Entity code:
/**
* #ORM\ManyToMany(targetEntity="Status")
*/
protected $status;
Form type code:
$builder->add('status', 'collection', array(
'type' => 'entity',
'allow_add' => true,
'options' => array(
'class' => 'SunflyCoreBundle:Status',
'property' => 'name',
))
);
Form template code:
<form action="{{ path('_product_create_process') }}" method="post" {{ form_enctype(form) }}>
{{ form_widget(form) }}
<input type="submit" />
</form>
HTML Rendered on the page:
<div id="product_status" data-prototype="STUFF THAT WONT RENDER ON SO"></div>

symfony2 comparing hidden field with its hash with form validation

I would like to know how to compare fields in symfony2 form with custom validation.
In particular I want to compare a simple hidden field with its hash.
<input type="hidden" name="smoke" value="1" />
<input type="hidden" name="smoke_hash" value="kahsjkdasjkdh3iuy84932798" />
Something like "repeated Field" but validated with my own logic.
But more something like this:
use Symfony\Component\Validator\Constraints\HashMatchString;
$builder
->add('smoke', 'hidden', array(
'data' => 1,
)
)
->add('smoke_hash', 'hidden', array(
'constraints' => array(
new HashMatchString('smoke')
),
)
)
;
Form Goodness in Symfony 2.1
I’ve already see the solution of Steven Brown (http://www.yewchube.com/2011/08/symfony-2-field-comparison-validator/) but is one year ago with multiple touches on core files...
SOLVED
I’ve created a gist: Gist
Just add validation method to your entity http://symfony.com/doc/current/book/validation.html#getters

Drupal Custom Module / Form Question: Adding an array of fields

I'm creating a custom module where I'd like to have the "add another item" functionality for a particular field, but I can't seem to figure out what I need to do in order to accomplish this... I've been going through Drupal forums and their Forms API Reference, but I must not be getting something.... I'm using Drupal 6.20, and in my module, I tried:
$form['options'] = array(
'#title' => t('Options'),
'#type' => 'fieldset',
);
$form['options']['address'] = array(
'#type'=>'textfield',
'#title'=>t('Address'),
'#tree' => 1,
);
Thinking I would get an text input that looked like this:
<input type="text" class="form-text text" value="" size="60" id="edit-address-0-value" name="address[0][value]">
But, I just get an input that looks like this:
<input type="text" class="form-text" value="" size="60" id="edit-address" name="address" maxlength="128">
You need to set #tree on the element above the one you want to duplicate. FAPI will store values in a tree structure from that element on downwards.
To get a name like address[0][value] you will need something like
$form['options']['address'] = array(
'#tree' => TRUE,
);
$form['options']['address'][0] = array(
'#tree' => TRUE,
);
$form['options']['address'][0]['value'] = array(
'#type'=>'textfield',
'#title'=>t('Address'),
);
But you don't need the [value] part unless you are actually trying to achieve multi-valued grouped fields or if your field has a complex (custom) data type implemented with multiple PHP values (ie. latitude/longitude, start/stop dates, etc.).
You will also probably need to store the number of values in something like $form['options']['#nb_values'] or in an hidden field (if you plan to add the additional fields to the form using JavaScript).

Resources