Skip to content
Snippets Groups Projects
Commit 9b00422a authored by vbouchet's avatar vbouchet
Browse files

First working version for D8 - removed confirm_form and drush integration

parent 9e40e9bf
Branches
Tags 8.x-1.0
No related merge requests found
<?php
/**
* @file
* Drush integration for the flat_taxonomy module.
*/
/**
* Implements hook_drush_command().
*/
function flat_taxonomy_drush_command() {
$items['flat-taxonomy'] = array(
'callback' => 'drush_flat_taxonomy',
'description' => dt('Flatten a taxonomy.'),
'arguments' => array(
'machine_name' => dt('Vocabulary machine name which need to be flatten.'),
),
'aliases' => array('ft'),
);
return $items;
}
/**
* Command callback. Flatten a vocabulary.
*/
function drush_flat_taxonomy($vname = NULL) {
// Try to convert machine name to a vocab ID
if (!$vocabulary = taxonomy_vocabulary_machine_name_load($vname)) {
return drush_set_error('FLAT_TAXONOMY_INVALID_INPUT', dt('Invalid vocabulary machine name: !vname', array('!vname' => $vname)));
}
_flat_taxonomy_flatten_vocabulary($vocabulary->vid);
drush_log(dt('!name vocabulary is now flat', array('!name' => $vocabulary->name)), 'success');
}
<?php
/**
* @file
* Install, update and uninstall functions for the flat_taxonomy module.
*/
/**
* Implements hook_uninstall().
*/
function flat_taxonomy_uninstall() {
foreach (taxonomy_get_vocabularies() as $vocabulary) {
variable_del('flat_' . $vocabulary->machine_name);
}
}
\ No newline at end of file
......@@ -5,6 +5,11 @@
* Provides UI and implements hook to force taxonomies to be flat.
*/
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Config\Entity\ThirdPartySettingsInterface;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Taxonomy is not flat.
*/
......@@ -18,170 +23,64 @@ define('FLAT_TAXONOMY_FLAT', 1);
/**
* Implements hook_form_FORM_ID_alter().
*/
function flat_taxonomy_form_taxonomy_vocabulary_form_alter(&$form, $form_state) {
// Check if we need to display the confirmation form.
if (array_key_exists('confirm_update', $form_state)) {
$form = flat_taxonomy_form_taxonomy_vocabulary_form_confirm_edit($form, $form_state);
// We need to alter the access to these fields as we are only altering an
// existing form. If some other modules alter the same form and add more
// fields, these fields may remain on the confirmation step.
$form['name']['#access'] = FALSE;
$form['machine_name']['#access'] = FALSE;
$form['flat'] = array('#type' => 'value', '#value' => 1);
$form['#submit'][] = 'flat_taxonomy_form_taxonomy_vocabulary_form_submit';
function flat_taxonomy_form_taxonomy_vocabulary_form_alter(&$form, FormStateInterface $form_state) {
$vocabulary = $form_state->getFormObject()->getEntity();
return $form;
}
$form['flat'] = array(
'#type' => 'checkbox',
'#title' => t('Flat taxonomy'),
'#description' => t("If checked, the taxonomy will be flat, terms can be ordered but can't be nested"),
'#default_value' => $vocabulary->getThirdPartySetting('flat_taxonomy', 'flat'),
);
// We don't alter the form if we are displaying the confirm delete step.
if (!array_key_exists('confirm_delete', $form_state)) {
$form['flat'] = array(
'#type' => 'checkbox',
'#title' => t('Flat taxonomy'),
'#description' => t("If checked, the taxonomy will be flat, terms can be ordered but can't be nested"),
'#default_value' => (!empty($form['#vocabulary']->machine_name)) ? \Drupal::config('flat_taxonomy.settings')->get('flat_' . $form['#vocabulary']->machine_name, FLAT_TAXONOMY_NORMAL) : FLAT_TAXONOMY_NORMAL,
);
$form['#validate'][] = 'flat_taxonomy_form_taxonomy_vocabulary_form_validate';
$form['#submit'][] = 'flat_taxonomy_form_taxonomy_vocabulary_form_submit';
}
}
$form['#entity_builders'][] = 'flat_taxonomy_form_taxonomy_vocabulary_form_builder';
/**
* Custom validate handler for the taxonomy add/edit form.
*/
function flat_taxonomy_form_taxonomy_vocabulary_form_validate($form, &$form_state) {
// If the user has not seen the confirmation step and if the vocabulary is
// marked as to be flatten but has nested terms, we need to warn the user
// that terms will be updated.
if ($form_state['triggering_element']['#value'] == t('Save') && !isset($form_state['values']['edit'])
&& isset($form['#vocabulary']->vid) && $form_state['values']['flat'] == FLAT_TAXONOMY_FLAT) {
// Try to find a term which is not on the first level.
$query = db_select('taxonomy_term_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid');
$query->fields('t');
$query->condition('t.vid', $form['#vocabulary']->vid);
$query->condition('h.parent', 0, '<>');
$query->range(0, 1);
$result = $query->execute();
// If the vocabulary is not flatten yet, add the confirmation step.
if ($result->rowCount()) {
$form_state['rebuild'] = TRUE;
$form_state['confirm_update'] = TRUE;
return;
}
}
// @TODO: Add a confirm step if the vocabulary is updated to be flatten and
// already has terms (see 7.x version of the module).
}
/**
* Form builder for the vocabulary edit confirmation form.
* Entity form builder to add the flat information to the vocabulary.
*
* This confirmation form is displayed only if the vocabulary is edited
* to be flatten but contains nested terms.
* @param $entity_type
* @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary
* @param $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*/
function flat_taxonomy_form_taxonomy_vocabulary_form_confirm_edit($form, &$form_state) {
// This value is used to check if we already passed the confirmation step.
$form['edit'] = array('#type' => 'value', '#value' => TRUE);
return confirm_form($form,
t('Are you sure you want to flatten the @name vocabulary?', array('@name' => $form_state['vocabulary']->name)),
'admin/structure/taxonomy/' . $form_state['vocabulary']->machine_name . '/edit',
t('This vocabulary has nested terms. Flatten the taxonomy will remove all terms relation. This action cannot be undone.'),
t('Save'),
t('Cancel'));
}
/**
* Custom submit handler for the taxonomy add/edit form.
*
* To avoid updating the variable table too often, we update only if the
* setting has changed.
*/
function flat_taxonomy_form_taxonomy_vocabulary_form_submit($form, &$form_state) {
// If the taxonomy machine name has changed, we delete the previous setting.
if ($form_state['values']['machine_name'] != $form_state['values']['old_machine_name']) {
\Drupal::config('flat_taxonomy.settings')->delete('flat_' . $form_state['values']['old_machine_name']);
}
// We update the variable only if the setting has changed.
if ($form_state['values']['flat'] == FLAT_TAXONOMY_FLAT && \Drupal::config('flat_taxonomy.settings')->get('flat_' . $form_state['values']['machine_name'], FLAT_TAXONOMY_NORMAL) == FLAT_TAXONOMY_NORMAL) {
variable_set('flat_' . $form_state['values']['machine_name'], FLAT_TAXONOMY_FLAT);
}
elseif ($form_state['values']['flat'] == FLAT_TAXONOMY_NORMAL && \Drupal::config('flat_taxonomy.settings')->get('flat_' . $form_state['values']['machine_name'], FLAT_TAXONOMY_NORMAL) == FLAT_TAXONOMY_FLAT) {
variable_del('flat_' . $form_state['values']['machine_name']);
function flat_taxonomy_form_taxonomy_vocabulary_form_builder($entity_type, Drupal\taxonomy\Entity\Vocabulary $vocabulary, &$form, FormStateInterface $form_state) {
if ($form_state->getValue('flat')) {
$vocabulary->setThirdPartySetting('flat_taxonomy', 'flat', $form_state->getValue('flat'));
\Drupal::service('flat_taxonomy.taxonomy_flattener')->flatten($vocabulary);
return;
}
// If for any reason the confirm step has been displayed, that mean we
// need to flatten the taxonomy.
if (!empty($form_state['confirm_update'])) {
_flat_taxonomy_flatten_vocabulary($form_state['vid']);
}
}
/**
* Flatten an entire vocabulary.
*
* @param $vid
* The vid of the vocabulary to flatten.
*/
function _flat_taxonomy_flatten_vocabulary($vid) {
$weight = 0;
foreach (taxonomy_get_tree($vid, 0, 1) as $term) {
_flat_taxonomy_flatten_subtree($term, $weight);
}
}
/**
* Recursive function to flatten a term and its children.
*
* @param $term
* The root term to flatten.
* @param int $weight
* The new weight of the given root term.
*/
function _flat_taxonomy_flatten_subtree($term, &$weight = 0) {
$term->weight = $weight++;
$term->parent = 0;
taxonomy_term_save($term);
foreach (taxonomy_get_tree($term->vid, $term->tid, 1) as $term) {
_flat_taxonomy_flatten_subtree($term, $weight);
}
$vocabulary->unsetThirdPartySetting('flat_taxonomy', 'flat');
}
/**
* Implements hook_taxonomy_term_presave().
*/
function flat_taxonomy_taxonomy_term_presave($term) {
function flat_taxonomy_taxonomy_term_presave(Term $term) {
// If the term is nested but is part of a flat taxonomy, we update the
// parent and log the change. This is not supposed to occur via the normal
// edit form as the parent field is hidden but it may occur via a
// programmatical save (migration, services, ...).
if (\Drupal::config('flat_taxonomy.settings')->get('flat_' . $term->vocabulary_machine_name, FLAT_TAXONOMY_NORMAL) == FLAT_TAXONOMY_FLAT && !empty($term->parent)) {
watchdog('flat_taxonomy', 'Illegal parent %parent_tid for the term %name as vocabulary is flat. Parent has been updated.', array('%parent_tid' => $term->parent, '%name' => $term->name), WATCHDOG_WARNING);
drupal_set_message(t('Illegal parent %parent_tid for the term %name as vocabulary is flat. Parent has been updated.', array('%parent_tid' => $term->parent, '%name' => $term->name)), 'warning');
$vocabulary = Vocabulary::load($term->getVocabularyId());
if ($vocabulary->getThirdPartySetting('flat_taxonomy', 'flat') == FLAT_TAXONOMY_FLAT && !empty($term->parent)) {
\Drupal::logger('flat_taxonomy')->warning('Illegal parent %parent_tid for the term %name as vocabulary is flat. Parent has been updated.', array('%parent_tid' => $term->parent, '%name' => $term->name));
drupal_set_message($this->t('Illegal parent %parent_tid for the term %name as vocabulary is flat. Parent has been updated.', array('%parent_tid' => $term->parent, '%name' => $term->name)), 'warning');
// @TODO: Update the term weight so it is ordered after the parent.
$term->parent = 0;
}
}
/**
* Implements hook_taxonomy_vocabulary_delete().
*/
function flat_taxonomy_taxonomy_vocabulary_delete($vocabulary) {
variable_del('flat_' . $vocabulary->machine_name);
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function flat_taxonomy_form_taxonomy_form_term_alter(&$form, $form_state) {
if (\Drupal::config('flat_taxonomy.settings')->get('flat_' . $form['#vocabulary']->machine_name, FLAT_TAXONOMY_NORMAL) == FLAT_TAXONOMY_FLAT) {
function flat_taxonomy_form_taxonomy_term_form_alter(&$form, FormStateInterface $form_state) {
if ($form_state->getStorage()['taxonomy']['vocabulary']->getThirdPartySetting('flat_taxonomy', 'flat') == FLAT_TAXONOMY_FLAT) {
$form['relations']['parent']['#access'] = FALSE;
$form['#validate'][] = 'flat_taxonomy_form_taxonomy_form_term_validate';
......@@ -191,37 +90,20 @@ function flat_taxonomy_form_taxonomy_form_term_alter(&$form, $form_state) {
/**
* Custom validate handler for the taxonomy term add/edit form.
*/
function flat_taxonomy_form_taxonomy_form_term_validate($form, &$form_state) {
if ($form_state['values']['parent'][0]) {
form_set_error('parent', t("This term can't have any parent has it is part of a flat taxonomy."));
function flat_taxonomy_form_taxonomy_form_term_validate($form, FormStateInterface &$form_state) {
if ($form_state->getValue('parent')[0]) {
$form_state->setErrorByName('parent', $this->t("This term can't have any parent has it is part of a flat taxonomy."));
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function flat_taxonomy_form_taxonomy_overview_terms_alter(&$form, $form_state) {
if (array_key_exists('#vocabulary', $form)) {
$settings['flat_taxonomy'] = \Drupal::config('flat_taxonomy.settings')->get('flat_' . $form['#vocabulary']->machine_name, FLAT_TAXONOMY_NORMAL);
drupal_add_js($settings, 'setting');
}
}
/**
* Implements hook_js_alter().
*/
function flat_taxonomy_js_alter(&$js) {
$flat = FALSE;
foreach ($js['settings']['data'] as $data) {
if (isset($data['flat_taxonomy']) && $data['flat_taxonomy']) {
$flat = TRUE;
}
}
if ($flat) {
foreach ($js['settings']['data'] as $index => $data) {
if (isset($data['tableDrag']['taxonomy']['term-depth']) || isset($data['tableDrag']['taxonomy']['term-parent'])) {
unset($js['settings']['data'][$index]);
function flat_taxonomy_form_taxonomy_overview_terms_alter(&$form, FormStateInterface $form_state) {
if ($form_state->getStorage()['taxonomy']['vocabulary']->getThirdPartySetting('flat_taxonomy', 'flat') == FLAT_TAXONOMY_FLAT) {
foreach ($form['terms']['#tabledrag'] as $index => $data) {
if (isset($data['group']) && ($data['group'] == 'term-depth' || $data['group'] == 'term-parent')) {
unset($form['terms']['#tabledrag'][$index]);
}
}
}
......
taxonomy.vocabulary.*.third_party.flat_taxonomy:
type: mapping
label: 'Flat'
mapping:
flat:
type: text
label: 'Flat'
\ No newline at end of file
services:
flat_taxonomy.taxonomy_flattener:
class: Drupal\flat_taxonomy\Flattener
arguments: ['@entity_type.manager']
\ No newline at end of file
<?php
/**
* @file
* Service to flatten a vocabulary.
*/
namespace Drupal\flat_taxonomy;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
/**
* Provides method to flatten a vocabulary's terms.
*
* @package Drupal\flat_taxonomy
*/
class Flattener {
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityTypeManager
*/
protected $entityManager;
/**
* @var \Drupal\taxonomy\TermStorage
*/
protected $taxonomyTermStorage;
/**
* @param \Drupal\Core\Entity\EntityTypeManager $entity_manager
*/
public function __construct(EntityTypeManager $entity_manager) {
$this->entityManager = $entity_manager;
$this->taxonomyTermStorage = $this->entityManager->getStorage('taxonomy_term');
}
/**
* Flatten an entire vocabulary.
*
* @param \Drupal\taxonomy\Entity\Vocabulary $vocabulary
*/
public function flatten(Vocabulary $vocabulary) {
$weight = 0;
$tree = $this->taxonomyTermStorage->loadTree($vocabulary->id(), 0, 1, TRUE);
foreach ($tree as $term) {
$this->flatten_subtree($term, $weight);
}
}
/**
* Flatten a vocabulary subtree from the given term.
*
* @param \Drupal\taxonomy\Entity\Term $term
* @param $weight
*/
function flatten_subtree(Term $term, $weight) {
// Update the given term.
$term->weight = $weight++;
$term->parent = 0;
$term->save();
// Get the subtree from the given term.
$tree = $this->taxonomyTermStorage->loadTree($term->getVocabularyId(), $term->id(), 1, TRUE);
// Recursively flatten each children subtree.
foreach ($tree as $term) {
$this->flatten_subtree($term, $weight);
}
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment