Last active
August 29, 2015 14:07
-
-
Save webdevilopers/42c3cdc6013fb09f1c58 to your computer and use it in GitHub Desktop.
Batch resp. mass editing symfony form type using Doctrine Entity using data transformation and events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <form action="#" method="post" > | |
| <input type="hidden" id="contract_timekeeping_entry_batch__token" name="contract_timekeeping_entry_batch[_token]" value="U8W2Zy-AfwOC_UX7mOUqI7PGpn69Vo-X8UnjM07BuNQ" /> | |
| <button type="submit" id="contract_timekeeping_entry_batch_submit" name="contract_timekeeping_entry_batch[submit]">Submit</button> | |
| <div id='timekeepings'> | |
| <table class='default wide' border="1"> | |
| <thead> | |
| <tr> | |
| <th>Personal</th> | |
| <th> </th> | |
| <th class='unimportant' colspan='2'>28.11.2011</th> | |
| <th class='unimportant' colspan='2'>29.11.2011</th> | |
| <th class='unimportant' colspan='2'>30.11.2011</th> | |
| <th class='unimportant' colspan='2'>01.12.2011</th> | |
| <th class='unimportant' colspan='2'>02.12.2011</th> | |
| <th class='unimportant' colspan='2'>03.12.2011</th> | |
| <th class='unimportant' colspan='2'>04.12.2011</th> | |
| <th> </th> | |
| </tr> | |
| </thead> | |
| <tbody class='single-row'> | |
| <tr class='work' row_idx='0'> | |
| <th class='user' rowspan='2' user_id='170'> | |
| <div> | |
| <strong> <label class="required">170</label></strong> | |
| <img alt="Add" class="add clickable" onclick="add_row(170)" src="/images/add.png" title="Weitere Zeile hinzufügen" /> | |
| </div> | |
| </th> | |
| <th class='title_work'>Zeit von/bis</th> | |
| <td class="work_begin"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-28_work_begin" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-28][work_begin]" value="1112" /></td> | |
| <td class="work_end"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-28_work_end" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-28][work_end]" value="1211" /></td> | |
| <td class="work_begin"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-29_work_begin" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-29][work_begin]" /></td> | |
| <td class="work_end"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-29_work_end" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-29][work_end]" /></td> | |
| <td class="work_begin"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-30_work_begin" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-30][work_begin]" value="1100" /></td> | |
| <td class="work_end"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-30_work_end" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-30][work_end]" value="1300" /></td> | |
| <td class="work_begin"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-01_work_begin" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-01][work_begin]" /></td> | |
| <td class="work_end"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-01_work_end" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-01][work_end]" /></td> | |
| <td class="work_begin"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-02_work_begin" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-02][work_begin]" /></td> | |
| <td class="work_end"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-02_work_end" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-02][work_end]" /></td> | |
| <td class="work_begin"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-03_work_begin" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-03][work_begin]" /></td> | |
| <td class="work_end"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-03_work_end" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-03][work_end]" /></td> | |
| <td class="work_begin"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-04_work_begin" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-04][work_begin]" /></td> | |
| <td class="work_end"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-04_work_end" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-04][work_end]" /></td> | |
| <th class='sum' title='Arbeitszeit'> | |
| <span></span> | |
| </th> | |
| </tr> | |
| <tr class='travel' row_idx='0'> | |
| <th class='title_other'>Fahrt/Pause</th> | |
| <td class="duration_travel"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-28_duration_travel" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-28][duration_travel]" size="5" /></td> | |
| <td class="duration_break"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-28_duration_break" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-28][duration_break]" size="5" /></td> | |
| <td class="duration_travel"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-29_duration_travel" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-29][duration_travel]" size="5" /></td> | |
| <td class="duration_break"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-29_duration_break" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-29][duration_break]" size="5" /></td> | |
| <td class="duration_travel"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-30_duration_travel" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-30][duration_travel]" size="5" /></td> | |
| <td class="duration_break"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-11-30_duration_break" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-30][duration_break]" size="5" /></td> | |
| <td class="duration_travel"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-01_duration_travel" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-01][duration_travel]" size="5" /></td> | |
| <td class="duration_break"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-01_duration_break" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-01][duration_break]" size="5" /></td> | |
| <td class="duration_travel"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-02_duration_travel" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-02][duration_travel]" size="5" /></td> | |
| <td class="duration_break"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-02_duration_break" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-02][duration_break]" size="5" /></td> | |
| <td class="duration_travel"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-03_duration_travel" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-03][duration_travel]" size="5" /></td> | |
| <td class="duration_break"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-03_duration_break" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-03][duration_break]" size="5" /></td> | |
| <td class="duration_travel"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-04_duration_travel" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-04][duration_travel]" size="5" /></td> | |
| <td class="duration_break"><input type="text" id="contract_timekeeping_entry_batch_timekeepingEntries_170_days_2011-12-04_duration_break" name="contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-12-04][duration_break]" size="5" /></td> | |
| <th class='sum' title='Fahrtzeit'> | |
| <div> | |
| <span></span> | |
| <img alt="Cross" class="delete clickable" src="/images/cross.png?1396860297" /> | |
| </div> | |
| </th> | |
| </tr> | |
| </tbody> | |
| <tfoot> | |
| <tr class='work'> | |
| <th> </th> | |
| <th class='title_work'>Arbeitszeit</th> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <th class='sum'>0</th> | |
| </tr> | |
| <tr class='travel'> | |
| <th> </th> | |
| <th class='title_other'>Fahrtzeit</th> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <th class='sum'>0</th> | |
| </tr> | |
| </tfoot> | |
| </table> | |
| </div> | |
| </form> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {% extends "PlusquamContractBundle::layout.html.twig" %} | |
| {% block content %} | |
| <form action="#" method="post" {{ form_enctype(form) }}> | |
| {{ form_widget(form._token) }} | |
| {{ form_errors(form) }} | |
| {{ form_widget(form.submit) }} | |
| <div id='timekeepings'> | |
| <table class='default wide' border="1"> | |
| <thead> | |
| <tr> | |
| <th>Personal</th> | |
| <th> </th> | |
| {% for day in days %} | |
| <th class='unimportant' colspan='2'>{{ day|localizeddate('medium', 'none') }}</th> | |
| {% endfor %} | |
| <th> </th> | |
| </tr> | |
| </thead> | |
| {% for user in form.timekeepingEntries %} | |
| <tbody class='single-row'> | |
| <tr class='work' row_idx='0'> | |
| <th class='user' rowspan='2' user_id='{{ user.vars.name }}'> | |
| <div> | |
| <strong>{{ form_label(user) }}</strong> | |
| <img alt="Add" class="add clickable" onclick="add_row({{ user.vars.name }})" src="/images/add.png" title="Weitere Zeile hinzufügen" /> | |
| </div> | |
| </th> | |
| <th class='title_work'>Zeit von/bis</th> | |
| {% for day in user.days %} | |
| <td class="work_begin">{{ form_widget(day.work_begin) }}</td> | |
| <td class="work_end">{{ form_widget(day.work_end) }}</td> | |
| {% endfor %} | |
| <th class='sum' title='Arbeitszeit'> | |
| <span></span> | |
| </th> | |
| </tr> | |
| <tr class='travel' row_idx='0'> | |
| <th class='title_other'>Fahrt/Pause</th> | |
| {% for day in user.days %} | |
| <td class="duration_travel">{{ form_widget(day.duration_travel) }}</td> | |
| <td class="duration_break">{{ form_widget(day.duration_break) }}</td> | |
| {% endfor %} | |
| <th class='sum' title='Fahrtzeit'> | |
| <div> | |
| <span></span> | |
| <img alt="Cross" class="delete clickable" src="/images/cross.png?1396860297" /> | |
| </div> | |
| </th> | |
| </tr> | |
| </tbody> | |
| {% endfor %} | |
| <tfoot> | |
| <tr class='work'> | |
| <th> </th> | |
| <th class='title_work'>Arbeitszeit</th> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <th class='sum'>0</th> | |
| </tr> | |
| <tr class='travel'> | |
| <th> </th> | |
| <th class='title_other'>Fahrtzeit</th> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <td colspan='2'> </td> | |
| <th class='sum'>0</th> | |
| </tr> | |
| </tfoot> | |
| </table> | |
| </div> | |
| </form> | |
| {% include 'PlusquamTimekeepingBundle:Timekeeping:_script.html.twig' %} | |
| {% endblock %} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Plusquam\Bundle\ContractBundle\Entity; | |
| use Doctrine\ORM\Mapping as ORM; | |
| class Contract | |
| { | |
| /** | |
| * @ORM\OneToMany(targetEntity="TimekeepingEntry", mappedBy="contract", cascade={"persist"}) | |
| */ | |
| private $timekeepingEntries; | |
| /** | |
| * Add timekeepingEntries | |
| * | |
| * @param \Plusquam\Bundle\ContractBundle\Entity\TimekeepingEntry $timekeepingEntries | |
| * @return Contract | |
| */ | |
| public function addTimekeepingEntry(\Plusquam\Bundle\ContractBundle\Entity\TimekeepingEntry $timekeepingEntries) | |
| { | |
| $timekeepingEntries->setContract($this); | |
| $this->timekeepingEntries[] = $timekeepingEntries; | |
| return $this; | |
| } | |
| /** | |
| * Remove timekeepingEntries | |
| * | |
| * @param \Plusquam\Bundle\ContractBundle\Entity\TimekeepingEntry $timekeepingEntries | |
| */ | |
| public function removeTimekeepingEntry(\Plusquam\Bundle\ContractBundle\Entity\TimekeepingEntry $timekeepingEntries) | |
| { | |
| $this->timekeepingEntries->removeElement($timekeepingEntries); | |
| } | |
| /** | |
| * Get timekeepingEntries | |
| * | |
| * @return \Doctrine\Common\Collections\Collection | |
| */ | |
| public function getTimekeepingEntries() | |
| { | |
| return $this->timekeepingEntries; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Acme\Bundle\TimekeepingBundle\Controller; | |
| use Symfony\Bundle\FrameworkBundle\Controller\Controller; | |
| use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; | |
| use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; | |
| use Acme\Bundle\ContractBundle\Entity\TimekeepingEntry; | |
| use Acme\Bundle\TimekeepingBundle\Form\TimekeepingEntryType; | |
| class TimekeepingController extends Controller | |
| { | |
| /** | |
| * @Route("/timekeeping/edit/{id}") | |
| * @Template() | |
| */ | |
| public function batchAction(Request $request) | |
| { | |
| $contractId = $request->get('contractId'); | |
| $em = $this->getDoctrine()->getManager(); | |
| $weekStartDate = $this->get('request')->get('date') !== null | |
| ? $this->get('request')->get('date') | |
| : '28.11.2011'; | |
| $monthStartDate = '28.11.2014'; | |
| $weekParam = $this->get('request')->get('week'); | |
| $date = new \DateTime($weekStartDate); | |
| $week = $date->format("W"); | |
| $days = $this->daysInWeek($week, $year); | |
| $contract = $em->getRepository('Plusquam\Bundle\ContractBundle\Entity\TimekeepingEntry') | |
| ->findContractTimekeepingEntriesByDate(array('contractId' => $contractId, 'days' => $days)); | |
| $form = $this->createForm('contract_timekeeping_entry_batch', $contract, array('days' => $days)); | |
| $form->handleRequest($request); | |
| if ($form->isValid()) { | |
| $em = $this->getDoctrine()->getManager(); | |
| $em->persist($contract); | |
| $em->flush(); | |
| } | |
| return array( | |
| 'form' => $form->createView(), | |
| 'days' => $days, | |
| 'week_start_date' => $weekStartDate, | |
| 'month_start_date' => $monthStartDate | |
| ); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Acme\Bundle\ContractBundle\Entity; | |
| use Doctrine\ORM\Mapping as ORM; | |
| /** | |
| * @ORM\Entity(repositoryClass="Acme\Bundle\ContractBundle\Entity\TimekeepingEntryRepository") | |
| * @ORM\Table(name="timekeeping_entries") | |
| */ | |
| class TimekeepingEntry | |
| { | |
| /** | |
| * @ORM\Id | |
| * @ORM\Column(type="integer") | |
| * @ORM\GeneratedValue(strategy="AUTO") | |
| */ | |
| private $id; | |
| /** | |
| * @ORM\ManyToOne(targetEntity="Contract", inversedBy="timekeepingEntries") | |
| * @ORM\JoinColumn(name="contract_id", referencedColumnName="id") | |
| */ | |
| private $contract; | |
| /** | |
| * @ORM\Column(type="date") | |
| */ | |
| private $date; | |
| /** | |
| * @ORM\Column(type="smallint", name="work_begin", options={"unsigned":true}, columnDefinition="SMALLINT(4) UNSIGNED ZEROFILL") | |
| */ | |
| private $workBegin; | |
| /** | |
| * @ORM\Column(type="smallint", name="work_end", options={"unsigned":true}, columnDefinition="SMALLINT(4) UNSIGNED ZEROFILL") // type time? | |
| */ | |
| private $workEnd; | |
| /** | |
| * @ORM\ManyToOne(targetEntity="Application\Sonata\UserBundle\Entity\User", inversedBy="timekeepingEntries") | |
| * @ORM\JoinColumn(name="user_id", referencedColumnName="id") | |
| */ | |
| private $user; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Plusquam\Bundle\ContractBundle\Form; | |
| use Symfony\Component\Form\AbstractType; | |
| use Symfony\Component\Form\FormBuilderInterface; | |
| use Symfony\Component\Form\FormView; | |
| use Symfony\Component\OptionsResolver\OptionsResolverInterface; | |
| use Symfony\Component\Form\FormInterface; | |
| use Symfony\Component\Form\FormEvent; | |
| use Symfony\Component\Form\FormEvents; | |
| use Plusquam\Bundle\ContractBundle\Form\DataTransformer\TimekeepingTransformer; | |
| class TimekeepingEntryBatchType extends AbstractType | |
| { | |
| /** | |
| * @param FormBuilderInterface $builder | |
| * @param array $options | |
| */ | |
| public function buildForm(FormBuilderInterface $builder, array $options) | |
| { | |
| $timekeepingTransformer = new TimekeepingTransformer(); | |
| $builder | |
| ->setAttribute('days', $options['days']) | |
| ->add('submit', 'submit', array()) | |
| ->addModelTransformer($timekeepingTransformer) // On preSetData data send to the event is not processed by modelTransformer. | |
| ; | |
| // desired notation: contract_timekeeping_entry_batch[timekeepingEntries][1][work_end] | |
| // $builder->add('timekeepingEntries', 'collection', array( | |
| // // each item in the array will be an "email" field | |
| //// 'type' => 'TimekeepingEntryType', | |
| // 'type' => new TimekeepingEntryType(), | |
| // // these options are passed to each "email" type | |
| // 'allow_delete' => true, | |
| // 'allow_add' => true, | |
| // 'by_reference' => false, | |
| // 'options' => array( | |
| // 'min_date' => reset($options['days']), | |
| // 'max_date' => end($options['days']), | |
| //// 'required' => false, | |
| //// 'attr' => array('class' => 'email-box') | |
| // ), | |
| // )); | |
| $factory = $builder->getFormFactory(); | |
| $formModifier = function (FormInterface $form, $contract) use ($factory, $options) { | |
| $timekeepingEntries = $contract->getTimekeepingEntries(); | |
| // current notation: contract_timekeeping_entry_batch[timekeepingEntries][170][days][2011-11-28][work_begin] | |
| $usersBuilder = $factory->createNamed('timekeepingEntries', 'form', array(), array( | |
| // $usersBuilder = $factory->createNamed('timekeepingEntries', 'collection', array(), array( | |
| 'auto_initialize' => false | |
| )) | |
| ; | |
| $form->add($usersBuilder); | |
| if (count($timekeepingEntries) == 0) { | |
| return; | |
| } | |
| $data = array( | |
| 'timekeepings' => array( | |
| 'users' => array(), | |
| ), | |
| 'days' => $options['days'] | |
| ); | |
| foreach ($timekeepingEntries as $timekeeping) { | |
| $user = $timekeeping->getUser()->getId(); | |
| $date = $timekeeping->getDate(); | |
| $data['timekeepings']['users'][$user]['days'][$date->format('Y-m-d')]['work_begin'] = $timekeeping->getWorkBegin(); | |
| $data['timekeepings']['users'][$user]['days'][$date->format('Y-m-d')]['work_end'] = $timekeeping->getWorkEnd(); | |
| $data['timekeepings']['users'][$user]['days'][$date->format('Y-m-d')]['duration_travel'] = $timekeeping->getDurationTravel(); | |
| $data['timekeepings']['users'][$user]['days'][$date->format('Y-m-d')]['duration_break'] = $timekeeping->getDurationBreak(); | |
| } | |
| foreach ($data['timekeepings']['users'] as $userId => $user) { | |
| $userBuilder = $factory->createNamed((string) $userId, 'form', $user, array( | |
| // $userBuilder = $factory->createNamed(null, 'form', $user, array( | |
| 'auto_initialize' => false | |
| )); | |
| $daysBuilder = $factory->createNamed('days', 'form', $user['days'], array( | |
| 'auto_initialize' => false | |
| )); | |
| $userBuilder->add($daysBuilder); | |
| foreach ($data['days'] as $weekDay => $date) { | |
| $formData = key_exists($date, $user['days']) ? $user['days'][$date] : null; | |
| $dateBuilder = $factory->createNamed($date, 'form', $formData, array( | |
| 'auto_initialize' => false | |
| )); | |
| $dateBuilder->add('work_begin' , 'text', array( | |
| 'required' => false, | |
| )); | |
| $dateBuilder->add('work_end' , 'text', array( | |
| 'required' => false, | |
| )); | |
| $dateBuilder->add('duration_travel' , 'number', array( | |
| 'precision' => 2, | |
| 'required' => false, | |
| 'label' => 'Travael', | |
| 'attr' => array('size' => 5) | |
| )); // @see http://symfony.com/doc/master/reference/forms/types/number.html#field-options | |
| $dateBuilder->add('duration_break' , 'number', array( | |
| 'precision' => 2, | |
| 'required' => false, | |
| 'label' => 'Break', | |
| 'attr' => array('size' => 5) | |
| )); | |
| $daysBuilder->add($dateBuilder); | |
| } | |
| $usersBuilder->add($userBuilder); | |
| } | |
| }; | |
| $builder->addEventListener(FormEvents::PRE_SET_DATA, | |
| function (FormEvent $event) use ($formModifier) { | |
| $contract = $event->getData(); | |
| $formModifier($event->getForm(), $contract); | |
| } | |
| ); | |
| $builder->addEventListener(FormEvents::POST_SUBMIT, | |
| function (FormEvent $event) use ($formModifier) { | |
| $contract = $event->getData(); | |
| $formModifier($event->getForm(), $contract); | |
| } | |
| ); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| */ | |
| public function buildView(FormView $view, FormInterface $form, array $options) | |
| { | |
| $view->vars['days'] = $options['days']; | |
| } | |
| /** | |
| * | |
| * @param type $weekNum | |
| * @param type $year | |
| * @return type | |
| * @todo Move to helper | |
| */ | |
| function daysInWeek($weekNum, $year) | |
| { | |
| $result = array(); | |
| $datetime = new \DateTime('00:00:00'); | |
| $datetime->setISODate($year, $weekNum, 1); // start with monday | |
| $interval = new \DateInterval('P1D'); | |
| $week = new \DatePeriod($datetime, $interval, 6); // count of days in week | |
| foreach($week as $day){ | |
| $dateIndex = $day->format('w'); | |
| $result[$dateIndex] = $day->format('Y-m-d'); | |
| } | |
| return $result; | |
| } | |
| /** | |
| * @param OptionsResolverInterface $resolver | |
| */ | |
| public function setDefaultOptions(OptionsResolverInterface $resolver) | |
| { | |
| $resolver->setDefaults(array( | |
| 'data_class' => 'Plusquam\Bundle\ContractBundle\Entity\Contract', | |
| 'days' => array() | |
| )); | |
| } | |
| /** | |
| * @return string | |
| */ | |
| public function getName() | |
| { | |
| return 'contract_timekeeping_entry_batch'; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Acme\Bundle\TimekeepingBundle\Form; | |
| use Symfony\Component\Form\AbstractType; | |
| use Symfony\Component\Form\FormBuilderInterface; | |
| use Symfony\Component\OptionsResolver\OptionsResolverInterface; | |
| class TimekeepingEntryType extends AbstractType | |
| { | |
| /** | |
| * @param FormBuilderInterface $builder | |
| * @param array $options | |
| */ | |
| public function buildForm(FormBuilderInterface $builder, array $options) | |
| { | |
| $builder | |
| ->add('date', 'date', array( | |
| 'widget' => 'choice', | |
| 'attr' => array('class' => 'date') | |
| )) // will be hidden | |
| //->add('user') // will be hidden | |
| ->add('work_begin') | |
| ->add('work_end') | |
| ->add('submit', 'submit'); | |
| } | |
| /** | |
| * @param OptionsResolverInterface $resolver | |
| */ | |
| public function setDefaultOptions(OptionsResolverInterface $resolver) | |
| { | |
| $resolver->setDefaults(array( | |
| 'data_class' => 'Acme\Bundle\ContractBundle\Entity\TimekeepingEntry' | |
| )); | |
| } | |
| /** | |
| * @return string | |
| */ | |
| public function getName() | |
| { | |
| return 'timekeeping'; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Acme\AppBundle\ContractBundle\Form\DataTransformer; | |
| use Symfony\Component\Form\DataTransformerInterface; | |
| use Symfony\Component\Form\Exception\TransformationFailedException; | |
| class TimekeepingTransformer implements DataTransformerInterface | |
| { | |
| /** | |
| * @param Contract|null $contract | |
| * @return string | |
| */ | |
| public function transform($contract) | |
| { | |
| // no need for transforming, populating is done dynamically by the PRE_SET_DATA event | |
| return $contract; | |
| } | |
| /** | |
| * Transforms a timekeepings collection array back to TimekeepingEntry Entity type | |
| * | |
| * @return Contract|null | |
| * | |
| * @throws TransformationFailedException if object (issue) is not found. | |
| */ | |
| public function reverseTransform($contract) | |
| { | |
| // What to do here? Never called using PRE_SET_DATA event? | |
| return $contract; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment