Forked from
project / hierarchy_manager
57 commits behind the upstream repository.
-
Mingsong Hu authoredMingsong Hu authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
PluginTypeManager.php 6.28 KiB
<?php
namespace Drupal\hierarchy_manager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\hierarchy_manager\Plugin\HmDisplayPluginManager;
use Drupal\hierarchy_manager\Plugin\HmSetupPluginManager;
class PluginTypeManager {
/**
* Display plugin manager.
*
* @var \Drupal\hierarchy_manager\Plugin\HmDisplayPluginManager
*/
protected $displayManager;
/**
* Setup plugin manager.
*
* @var \Drupal\hierarchy_manager\Plugin\HmSetupPluginManager
*/
protected $setupManager;
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* {@inheritdoc}
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, HmDisplayPluginManager $display_manager, HmSetupPluginManager $setup_manager) {
$this->entityTypeManager = $entity_type_manager;
$this->displayManager = $display_manager;
$this->setupManager = $setup_manager;
}
/**
* Construct an item inside the hierarchy.
*
* @param string|int $id
* Item id.
* @param string $label
* Item text.
* @param string $parent
* Parent id of the item.
* @param string $edit_url
* The URL where to edit this item.
* @return array
* The hierarchy item array.
*/
public function buildHierarchyItem($id, $label, $parent, $edit_url) {
return
[
'id' => $id,
'text' => $label,
'parent' => $parent,
'edit_url' => $edit_url,
];
}
/**
* Get a display plugin instance according to a setup plugin.
*
* @param string $setup_plugin_id
* setup plugin ID.
* @return NULL|object
* The display plugin instance.
*/
public function getDisplayPluginInstance(string $setup_plugin_id) {
// The setup plugin instance.
$setup_plugin = $this->setupManager->createInstance($setup_plugin_id);
// Display profile.
$display_profile = $this->entityTypeManager->getStorage('hm_display_profile')->load($setup_plugin->getDispalyProfileId());
if (empty($display_profile)) {
return NULL;
}
// Display plugin ID.
$display_plugin_id = $display_profile->get("plugin");
return $this->displayManager->createInstance($display_plugin_id);
}
/**
* Update the items for a hierarchy
*
* @param int $target_position
* Which position the new items will be insert.
* @param array $all_siblings
* All siblings of the new items in an array[$item_id => (int)$weight]
* @param array $updated_items
* IDs of new items inserted.
* @param int|bool $after
* Indicator if new items are inserted after target position.
*
* @return array
* All siblings needed to move and their new weights.
*/
public function updateHierarchy(int $target_position, array $all_siblings, array $updated_items, $after) {
$filtered_moving_siblings = [];
$first_half = TRUE;
$total = count($all_siblings);
if ($target_position === 0) {
// The insert postion is the first position.
// we don't need to move any siblings.
$weight = (int) reset($all_siblings) - 1;
}
elseif ($target_position >= $total - 1) {
// The insert postion is the end,
// we don't need to move any siblings.
$last_item= array_slice($all_siblings, -1, 1, TRUE);
$weight = (int) reset($last_item) + 1;
}
else {
$target_item = array_slice($all_siblings, $target_position, 1, TRUE);
$weight = (int) reset($target_item);
// If the target position is in the second half,
// we will move all siblings
// after the target position forward.
// Otherwise, we will move siblings
// before the target position backwards.
if ($target_position >= $total / 2) {
$first_half = FALSE;
if ($after) {
// Insert after the target position.
// The target stay where it is.
$weight += 1;
$moving_siblings = array_slice($all_siblings, $target_position + 1, NULL, TRUE);
}
else {
// Insert before the target position.
// The target need to move forwards.
$moving_siblings = array_slice($all_siblings, $target_position, NULL, TRUE);
}
$step = $weight + count($updated_items);
}
else {
if ($after) {
// Insert after the target position.
// The target need to move backwards.
$moving_siblings = array_slice($all_siblings, 0, $target_position + 1, TRUE);
}
else {
// Insert before the target position.
// The target stay where it is.
$weight -= 1;
$moving_siblings = array_slice($all_siblings, 0, $target_position, TRUE);
}
$weight = $step = $weight - count($updated_items);
// Reverse the siblings_moved array
// as we will decrease the weight
// starting from the first element
// and the new weight should be in
// an opposite order.
$moving_siblings = array_reverse($moving_siblings, TRUE);
}
// Move all siblings that need to move.
foreach($moving_siblings as $item_id => $item_weight) {
// Skip all links in the updated array. They will be moved later.
if (in_array($item_id, $updated_items)) {
continue;
}
if ($first_half) {
// While moving the first half of the siblings,
// all moving siblings' weight are decreased,
// if they are greater than the step.
if ((int)$item_weight < --$step) {
// There is planty room, no need to move anymore.
break;
}
else {
// Update the weight.
$filtered_moving_siblings[$item_id] = $step;
}
}
else {
// While moving the second half of the siblings,
// all moving siblings' weight are increased,
// if they are less than the step.
if ((int)$item_weight < ++$step) {
// Update the weight.
$filtered_moving_siblings[$item_id] = $step;
}
else {
// There is planty room, no need to move anymore.
break;
}
}
}
}
return ['start_weight' => $weight, 'moving_siblings' => $filtered_moving_siblings];
}
}