t('DraggableViews Weight'), 'group' => t('Global'), 'help' => t('Display the weight value.'), 'field' => array( 'id' => 'numeric', ), 'sort' => array( 'id' => 'standard', ), 'filter' => array( 'help' => t('Filter by the draggableviews weight value (Native handler only).'), 'id' => 'numeric', ), ); $data['draggableviews_structure']['parent'] = array( 'title' => t('Parent'), 'help' => t('The parent entity id.'), 'group' => t('Draggableviews'), 'field' => array( 'id' => 'numeric', ), 'filter' => array( 'help' => t('Filter by the draggableviews parent\'s entity id (Native handler only).'), 'id' => 'numeric', ), ); foreach (\Drupal::entityManager()->getDefinitions() as $entity_type_id => $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'] = array( 'title' => $data[$base_table]['table']['group'], 'group' => t('Draggableviews'), 'help' => t('Provide a draggable functionality.'), 'entity field' => $entity_keys['id'], 'field' => array( '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] = array( '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', 'extra' => array( array('field' => 'view_name', 'value' => '***VIEW_ID***'), array('field' => 'view_display', 'value' => '***VIEW_DISPLAY***'), ), ); } } } /** * Implements hook_views_query_substitutions(). * * Allow replacement of current userid so we can cache these queries. */ function draggableviews_views_query_substitutions(\Drupal\views\ViewExecutable $view) { return array('***VIEW_ID***' => $view->id(), '***VIEW_DISPLAY***' => $view->current_display); } /** * Implements hook_preprocess_views_view_table(). */ function draggableviews_preprocess_views_view_table(&$variables) { $view = $variables['view']; if (!isset($view->field['draggableviews'])) { return; } $draggableviews = new \Drupal\draggableviews\DraggableViews($variables['view']); // Add hierarchy. foreach ($variables['rows'] as $key => $row) { $title = $row['columns']['title']['content'][0]['field_output']['#markup']; $indent = [ '#theme' => 'indentation', '#size' => $draggableviews->getDepth($key), ]; $variables['rows'][$key]['columns']['title']['content'][0]['field_output']['#markup'] = render($indent) . $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, \Drupal\Core\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'] = array( '#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, \Drupal\Core\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 = \Drupal\Core\Database\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(); \Drupal\Core\Cache\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'); } }