t('DraggableViews Weight'), 'group' => t('Draggableviews'), 'help' => t('Display the weight value.'), 'field' => [ 'id' => 'numeric', ], 'sort' => [ 'id' => 'standard', ], 'filter' => [ 'help' => t('Filter by the draggableviews weight value (Native handler only).'), 'id' => 'numeric', ], 'argument' => [ 'id' => 'numeric', ], ]; $data['draggableviews_structure']['parent'] = [ 'title' => t('Parent'), 'help' => t('The parent entity id.'), 'group' => t('Draggableviews'), 'field' => [ 'id' => 'numeric', ], 'filter' => [ 'help' => t("Filter by the draggableviews parent's entity id (Native handler only)."), 'id' => 'numeric', ], 'argument' => [ 'id' => 'numeric', ], ]; foreach (\Drupal::entityTypeManager()->getDefinitions() as $entity_type) { $base_table = $entity_type->getDataTable() ?: $entity_type->getBaseTable(); $entity_keys = $entity_type->getKeys(); if ($base_table && isset($data[$base_table]['table'])) { $data[$base_table]['draggableviews'] = [ 'title' => $data[$base_table]['table']['group'], 'group' => t('Draggableviews'), 'help' => t('Provide a draggable functionality.'), 'entity field' => $entity_keys['id'], 'field' => [ 'id' => 'draggable_views_field', 'click sortable' => FALSE, ], ]; // Explain to every entity how to join with draggableviews_structure // table. $data['draggableviews_structure']['table']['join'][$base_table] = [ 'handler' => 'draggableviews_join_handler', // Because this is a direct link it could be left out. 'left_table' => $base_table, 'left_field' => $entity_keys['id'], 'field' => 'entity_id', ]; } } } /** * Implements hook_preprocess_views_view_table(). */ function draggableviews_preprocess_views_view_table(&$variables) { $view = $variables['view']; // If this view is not the sort view, then stop here. if (!isset($view->field['draggableviews'])) { return; } $draggableviews = new DraggableViews($variables['view']); // Add hierarchy. foreach ($variables['rows'] as $key => $row) { $columns = array_keys($row['columns']); // Find the first column that is not the draggableviews field. do { $first_column = current($columns); if ($first_column !== 'draggableviews') { break; } // Set the first column. $first_column = each($columns); } while ($first_column); // Indent the first column that is not the draggableviews field. $columns_title = $row['columns'][$first_column]['content'][0]['field_output']['#markup']; $indent = [ '#theme' => 'indentation', '#size' => $draggableviews->getDepth($key), ]; $variables['rows'][$key]['columns'][$first_column]['content'][0]['field_output']['#markup'] = (string) (render($indent) . $columns_title); } // Add table attributes. $variables['attributes']['id'] = $draggableviews->getHtmlId(); // Add rows attributes. foreach ($variables['rows'] as &$row) { $row['attributes']->addClass('draggable'); } unset($row); } /** * Implements hook_form_alter(). */ function draggableviews_form_alter(&$form, FormStateInterface $form_state, $form_id) { // Filter the right form. if (strpos($form_id, 'views_form_') === FALSE) { return; } // Check whether the view is draggable. $view = $form_state->getBuildInfo()['args'][0]; if (!isset($view->field['draggableviews'])) { return; } // Remove default submit button. $form['actions']['submit']['#access'] = FALSE; if (\Drupal::currentUser()->hasPermission('access draggableviews')) { // Create draggableviews save order button. $form['actions']['save_order'] = [ '#value' => t('Save order'), '#type' => 'submit', ]; } // If there is no results remove the save-order button. if (!isset($form['draggableviews'][0])) { $form['actions']['save_order']['#access'] = FALSE; return; } $form['actions']['save_order']['#submit'][] = 'draggableviews_views_submit'; } /** * Submit handler. */ function draggableviews_views_submit(&$form, FormStateInterface $form_state) { $input = $form_state->getUserInput(); /** @var \Drupal\views\ViewExecutable $view */ $view = $form_state->getBuildInfo()['args'][0]; $view_name = $view->id(); $view_display = $view->current_display; $weight = 0; $connection = Database::getConnection(); $transaction = $connection->startTransaction(); try { foreach ($input['draggableviews'] as $item) { // Remove old data. $connection->delete('draggableviews_structure') ->condition('view_name', $view_name) ->condition('view_display', $view_display) ->condition('entity_id', $item['id']) ->execute(); // Add new data. $record = [ 'view_name' => $view_name, 'view_display' => $view_display, 'args' => '[]', 'entity_id' => $item['id'], 'weight' => $weight, ]; // Save parent if exists. if (isset($item['parent'])) { $record['parent'] = $item['parent']; } $connection->insert('draggableviews_structure')->fields($record)->execute(); $weight++; } // We invalidate the entity list cache, so other views are also aware of the // cache. $views_entity_table_info = $view->query->getEntityTableInfo(); // Find the entity type used by the view. $result = array_keys(array_filter($views_entity_table_info, function ($info) { return $info['relationship_id'] == 'none'; })); $entity_type_id = reset($result); $list_cache_tags = \Drupal::entityTypeManager()->getDefinition($entity_type_id)->getListCacheTags(); Cache::invalidateTags($list_cache_tags); } catch (\Exception $e) { $transaction->rollback(); \Drupal::logger('draggableviews')->error('Failed with @message', ['@message' => $e->getMessage()]); drupal_set_message(t('There was an error while saving the data. Please, try gain.'), 'warning'); } }