Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
| Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 9 |
CRAP | |
0.00% |
0 / 77 |
| QuickEditFieldForm | |
0.00% |
0 / 1 |
|
0.00% |
0 / 9 |
552 | |
0.00% |
0 / 77 |
| __construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 5 |
|||
| create | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 7 |
|||
| getFormId | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 2 |
|||
| buildForm | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 19 |
|||
| init | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 15 |
|||
| validateForm | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 3 |
|||
| submitForm | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 4 |
|||
| buildEntity | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 8 |
|||
| simplify | |
0.00% |
0 / 1 |
56 | |
0.00% |
0 / 14 |
|||
| <?php | |
| /** | |
| * @file | |
| * Contains \Drupal\quickedit\Form\QuickEditFieldForm. | |
| */ | |
| namespace Drupal\quickedit\Form; | |
| use Drupal\Core\Entity\EntityInterface; | |
| use Drupal\Core\Entity\EntityStorageInterface; | |
| use Drupal\Core\Entity\EntityChangedInterface; | |
| use Drupal\Core\Extension\ModuleHandlerInterface; | |
| use Drupal\Core\Form\FormBase; | |
| use Drupal\Core\Form\FormStateInterface; | |
| use Drupal\Core\Render\Element; | |
| use Drupal\Core\Entity\Entity\EntityFormDisplay; | |
| use Drupal\user\PrivateTempStoreFactory; | |
| use Symfony\Component\DependencyInjection\ContainerInterface; | |
| use Symfony\Component\Validator\Validator\ValidatorInterface; | |
| /** | |
| * Builds and process a form for editing a single entity field. | |
| */ | |
| class QuickEditFieldForm extends FormBase { | |
| /** | |
| * Stores the tempstore factory. | |
| * | |
| * @var \Drupal\user\PrivateTempStoreFactory | |
| */ | |
| protected $tempStoreFactory; | |
| /** | |
| * The module handler. | |
| * | |
| * @var \Drupal\Core\Extension\ModuleHandlerInterface | |
| */ | |
| protected $moduleHandler; | |
| /** | |
| * The node type storage. | |
| * | |
| * @var \Drupal\Core\Entity\EntityStorageInterface | |
| */ | |
| protected $nodeTypeStorage; | |
| /** | |
| * The typed data validator. | |
| * | |
| * @var \Symfony\Component\Validator\Validator\ValidatorInterface | |
| */ | |
| protected $validator; | |
| /** | |
| * Constructs a new EditFieldForm. | |
| * | |
| * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory | |
| * The tempstore factory. | |
| * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
| * The module handler. | |
| * @param \Drupal\Core\Entity\EntityStorageInterface $node_type_storage | |
| * The node type storage. | |
| * @param \Symfony\Component\Validator\Validator\ValidatorInterface $validator | |
| * The typed data validator service. | |
| */ | |
| public function __construct(PrivateTempStoreFactory $temp_store_factory, ModuleHandlerInterface $module_handler, EntityStorageInterface $node_type_storage, ValidatorInterface $validator) { | |
| $this->moduleHandler = $module_handler; | |
| $this->nodeTypeStorage = $node_type_storage; | |
| $this->tempStoreFactory = $temp_store_factory; | |
| $this->validator = $validator; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public static function create(ContainerInterface $container) { | |
| return new static( | |
| $container->get('user.private_tempstore'), | |
| $container->get('module_handler'), | |
| $container->get('entity.manager')->getStorage('node_type'), | |
| $container->get('typed_data_manager')->getValidator() | |
| ); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function getFormId() { | |
| return 'quickedit_field_form'; | |
| } | |
| /** | |
| * {@inheritdoc} | |
| * | |
| * Builds a form for a single entity field. | |
| */ | |
| public function buildForm(array $form, FormStateInterface $form_state, EntityInterface $entity = NULL, $field_name = NULL) { | |
| if (!$form_state->has('entity')) { | |
| $this->init($form_state, $entity, $field_name); | |
| } | |
| // Add the field form. | |
| $form_state->get('form_display')->buildForm($entity, $form, $form_state); | |
| // Add a dummy changed timestamp field to attach form errors to. | |
| if ($entity instanceof EntityChangedInterface) { | |
| $form['changed_field'] = array( | |
| '#type' => 'hidden', | |
| '#value' => $entity->getChangedTime(), | |
| ); | |
| } | |
| // Add a submit button. Give it a class for easy JavaScript targeting. | |
| $form['actions'] = array('#type' => 'actions'); | |
| $form['actions']['submit'] = array( | |
| '#type' => 'submit', | |
| '#value' => t('Save'), | |
| '#attributes' => array('class' => array('quickedit-form-submit')), | |
| ); | |
| // Simplify it for optimal in-place use. | |
| $this->simplify($form, $form_state); | |
| return $form; | |
| } | |
| /** | |
| * Initialize the form state and the entity before the first form build. | |
| */ | |
| protected function init(FormStateInterface $form_state, EntityInterface $entity, $field_name) { | |
| // @todo Rather than special-casing $node->revision, invoke prepareEdit() | |
| // once https://www.drupal.org/node/1863258 lands. | |
| if ($entity->getEntityTypeId() == 'node') { | |
| $node_type = $this->nodeTypeStorage->load($entity->bundle()); | |
| $entity->setNewRevision($node_type->isNewRevision()); | |
| $entity->revision_log = NULL; | |
| } | |
| $form_state->set('entity', $entity); | |
| $form_state->set('field_name', $field_name); | |
| // Fetch the display used by the form. It is the display for the 'default' | |
| // form mode, with only the current field visible. | |
| $display = EntityFormDisplay::collectRenderDisplay($entity, 'default'); | |
| foreach ($display->getComponents() as $name => $options) { | |
| if ($name != $field_name) { | |
| $display->removeComponent($name); | |
| } | |
| } | |
| $form_state->set('form_display', $display); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| */ | |
| public function validateForm(array &$form, FormStateInterface $form_state) { | |
| $entity = $this->buildEntity($form, $form_state); | |
| $form_state->get('form_display')->validateFormValues($entity, $form, $form_state); | |
| } | |
| /** | |
| * {@inheritdoc} | |
| * | |
| * Saves the entity with updated values for the edited field. | |
| */ | |
| public function submitForm(array &$form, FormStateInterface $form_state) { | |
| $entity = $this->buildEntity($form, $form_state); | |
| $form_state->set('entity', $entity); | |
| // Store entity in tempstore with its UUID as tempstore key. | |
| $this->tempStoreFactory->get('quickedit')->set($entity->uuid(), $entity); | |
| } | |
| /** | |
| * Returns a cloned entity containing updated field values. | |
| * | |
| * Calling code may then validate the returned entity, and if valid, transfer | |
| * it back to the form state and save it. | |
| */ | |
| protected function buildEntity(array $form, FormStateInterface $form_state) { | |
| /** @var $entity \Drupal\Core\Entity\EntityInterface */ | |
| $entity = clone $form_state->get('entity'); | |
| $field_name = $form_state->get('field_name'); | |
| $form_state->get('form_display')->extractFormValues($entity, $form, $form_state); | |
| // @todo Refine automated log messages and abstract them to all entity | |
| // types: https://www.drupal.org/node/1678002. | |
| if ($entity->getEntityTypeId() == 'node' && $entity->isNewRevision() && $entity->revision_log->isEmpty()) { | |
| $entity->revision_log = t('Updated the %field-name field through in-place editing.', array('%field-name' => $entity->get($field_name)->getFieldDefinition()->getLabel())); | |
| } | |
| return $entity; | |
| } | |
| /** | |
| * Simplifies the field edit form for in-place editing. | |
| * | |
| * This function: | |
| * - Hides the field label inside the form, because JavaScript displays it | |
| * outside the form. | |
| * - Adjusts textarea elements to fit their content. | |
| * | |
| * @param array &$form | |
| * A reference to an associative array containing the structure of the form. | |
| * @param \Drupal\Core\Form\FormStateInterface $form_state | |
| * The current state of the form. | |
| */ | |
| protected function simplify(array &$form, FormStateInterface $form_state) { | |
| $field_name = $form_state->get('field_name'); | |
| $widget_element =& $form[$field_name]['widget']; | |
| // Hide the field label from displaying within the form, because JavaScript | |
| // displays the equivalent label that was provided within an HTML data | |
| // attribute of the field's display element outside of the form. Do this for | |
| // widgets without child elements (like Option widgets) as well as for ones | |
| // with per-delta elements. Skip single checkboxes, because their title is | |
| // key to their UI. Also skip widgets with multiple subelements, because in | |
| // that case, per-element labeling is informative. | |
| $num_children = count(Element::children($widget_element)); | |
| if ($num_children == 0 && $widget_element['#type'] != 'checkbox') { | |
| $widget_element['#title_display'] = 'invisible'; | |
| } | |
| if ($num_children == 1 && isset($widget_element[0]['value'])) { | |
| // @todo While most widgets name their primary element 'value', not all | |
| // do, so generalize this. | |
| $widget_element[0]['value']['#title_display'] = 'invisible'; | |
| } | |
| // Adjust textarea elements to fit their content. | |
| if (isset($widget_element[0]['value']['#type']) && $widget_element[0]['value']['#type'] == 'textarea') { | |
| $lines = count(explode("\n", $widget_element[0]['value']['#default_value'])); | |
| $widget_element[0]['value']['#rows'] = $lines + 1; | |
| } | |
| } | |
| } |