paragraphs_gantt-1.0.x-dev/src/Controller/ParagraphsGanttController.php

src/Controller/ParagraphsGanttController.php
<?php

namespace Drupal\paragraphs_gantt\Controller;

use Drupal\Component\Serialization\Json;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\Queue\QueueWorkerManagerInterface;
use Drupal\Core\Url;
use Drupal\paragraphs\Entity\Paragraph;
use Drupal\paragraphs\ParagraphsTypeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class definition for ComponentFormController.
 */
class ParagraphsGanttController extends ControllerBase {

  /**
   * Query POST.
   *
   * @var mixed
   */
  protected $post;

  public function __construct(protected CacheTagsInvalidatorInterface $cacheTags, protected QueueFactory $queueFactory, protected QueueWorkerManagerInterface $queueWorkerManager) {
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('cache_tags.invalidator'),
      $container->get('queue'),
      $container->get('plugin.manager.queue_worker'),
    );
  }

  /**
   * Add new / Edit / Delete Paragraphs.
   */
  public function ajax(Request $request, ParagraphsTypeInterface $paragraph_type, $view_mode, $entity_type, $entity_field, $entity_id) {

    $entity = $this->entityTypeManager()
      ->getStorage($entity_type)
      ->load($entity_id);

    $bundle = $entity->bundle();
    $loadViewDisplay = $this->entityTypeManager()
      ->getStorage('entity_view_display')
      ->load($entity_type . '.' . $bundle . '.' . $view_mode);
    $fieldSetting = $loadViewDisplay->getRenderer($entity_field)->getSettings();
    $action = $request->request->get("!nativeeditor_status") ?? FALSE;
    $output = [];
    if (!$action) {
      return new JsonResponse($output);
    }
    $this->post = $request->request->all();
    $mode = $request->query->get('gantt_mode');

    if ($mode == 'tasks') {
      if (!empty($fieldSetting['action_queue']) && $action == 'updated') {
        $output = $this->actionTaskQueue($action, $entity, $paragraph_type, $entity_field, $fieldSetting);
      }
      else {
        $output = $this->actionTask($action, $entity, $paragraph_type, $entity_field, $fieldSetting);
      }
    }
    if ($mode == 'links') {
      $output = $this->actionLinks($action, $entity, $paragraph_type, $entity_field, $fieldSetting);
    }

    return new JsonResponse($output);
  }

  /**
   * Import file MPP.
   *
   * {@inheritdoc}
   */
  public function import(Request $request, ParagraphsTypeInterface $paragraph_type, $view_mode, $entity_type, $entity_field, $entity_id) {
    $action = 'inserted';
    $entity = $this->entityTypeManager()
      ->getStorage($entity_type)
      ->load($entity_id);
    $mapping_data = [];
    $mapping_link = [];
    $bundle = $entity->bundle();
    $loadViewDisplay = $this->entityTypeManager()
      ->getStorage('entity_view_display')
      ->load($entity_type . '.' . $bundle . '.' . $view_mode);
    $fieldSetting = $loadViewDisplay->getRenderer($entity_field)->getSettings();
    if (!empty($request->get("data"))) {
      $rawData = $request->get("data");
      $rawLinks = $request->get("links");
      $this->post = [];
      foreach ($rawData as $data) {
        $start = new DrupalDateTime(preg_replace('/\s*\(.*\)$/', '', $data['start_date']));
        $end = new DrupalDateTime(preg_replace('/\s*\(.*\)$/', '', $data['end_date']));
        $this->post = [
          'text' => $data['text'],
          'duration' => $data['duration'],
          'progress' => $data['progress'],
          'open' => $data['open'],
          'parent' => $data['parent'],
          'type' => $data['type'] ?? 'task',
          'start_date' => $start->format('Y-m-d H:i'),
          'end_date' => $end->format('Y-m-d H:i'),
        ];
        if (!empty($mapping_data[$data['parent']]['id'])) {
          $this->post['parent'] = $mapping_data[$data['parent']]['id'];
        }
        $output = $this->actionTask($action, $entity, $paragraph_type, $entity_field, $fieldSetting);
        $mapping_data[$data['id']] = ['id' => $output['tid'], 'parent' => $mapping_data[$data['parent']]['id']];
      }

      foreach ($rawLinks as $data) {
        $this->post = [
          'source' => $mapping_data[$data['source']]['id'],
          'target' => $mapping_data[$data['target']]['id'],
          'type' => $data['type'],
          'lag' => $data['lag'],
        ];
        $output = $this->actionLinks($action, $entity, $paragraph_type, $entity_field, $fieldSetting);
        $mapping_link[$data['id']] = [
          'id' => $output['tid'],
          'source' => $mapping_data[$data['source']]['id'],
          'target' => $mapping_data[$data['target']]['id'],
        ];
      }
    }

    return new JsonResponse(['data' => $mapping_data, 'links' => $mapping_link]);
  }

  /**
   * Delete paragraphs.
   *
   * {@inheritDoc}
   */
  protected function deleteParagraph($entity, $entity_field, $paragraph) {
    $getField = $entity->get($entity_field);
    $array_of_referenced_items = $getField->getValue();
    $index_to_remove = array_search($this->post['id'], array_column($array_of_referenced_items, 'target_id'));
    if (is_numeric($index_to_remove) && $index_to_remove >= 0) {
      $getField->removeItem($index_to_remove);
      $entity->save();
      $paragraph->delete();
      $storage = $this->entityTypeManager()
        ->getStorage($entity->getEntityTypeId());
      $storage->resetCache([$entity->id()]);
    }
    return $paragraph->id();
  }

  /**
   * Update paragraphs.
   *
   * {@inheritDoc}
   */
  protected function updateParagraphOrder($field_settings, $paragraph) {
    $managerParagraph = $this->entityTypeManager()->getStorage('paragraph');
    $listOrder = Json::decode($this->post['listOrder']);
    if (!empty($listOrder)) {
      foreach ($listOrder as $item) {
        if ($item['id'] == $paragraph->id()) {
          continue;
        }
        $entity_order = $managerParagraph->load($item['id']);
        if ($entity_order) {
          $entity_order->set($field_settings['order'], $item['order']);
          $entity_order->save();
        }
      }
    }
  }

  /**
   * Update schedule planned.
   *
   * {@inheritDoc}
   */
  protected function updateSchedulePlanned($field_settings, $type_date, $time_timezone, $utc_timezone) {
    $managerParagraph = $this->entityTypeManager()->getStorage('paragraph');
    $listUpdate = Json::decode($this->post['listSchedulePlanned']);
    if (!empty($listUpdate)) {
      foreach ($listUpdate as $item_planned) {
        $entity_update = $managerParagraph->load($item_planned['id']);
        if ($entity_update) {
          $planned_date = $this->processDate('planned_start', 'planned_end', $type_date, $field_settings, $time_timezone, $utc_timezone, $item_planned['planned_start'], $item_planned['planned_end']);

          if ($type_date['start_date_planned']['field_type'] == 'daterange') {
            $entity_update->set($field_settings['planned_date'], $planned_date);
          }
          else {
            if (!empty($field_settings['planned_date'])) {
              $entity_update->set($field_settings['planned_date'], $planned_date['value']);
            }
            if (!empty($field_settings['planned_end_date'])) {
              $entity_update->set($field_settings['planned_end_date'], $planned_date['end_value']);
            }
          }
          $entity_update->save();
        }
      }
    }
  }

  /**
   * Process Dates.
   *
   * {@inheritDoc}
   */
  protected function processDate($start_key, $end_key, $type_date, $field_settings, $time_timezone, $utc_timezone, $start = NULL, $end = NULL) {
    $type_key_start = 'start_date_planned';
    $type_key_end = 'end_date_planned';
    if ($start_key == 'start_date') {
      $type_key_start = 'start_date_actually';
      $type_key_end = 'end_date_actually';
    }
    $dateFormatStart = $dateFormatEnd = 'Y-m-d\TH:i:s';
    if ($type_date[$type_key_start]['field_type'] == 'daterange' && $type_date[$type_key_start]['date_type'] == 'date') {
      $dateFormatStart = $dateFormatEnd = 'Y-m-d';
    }
    elseif ($type_date[$type_key_end]['date_type'] == 'date') {
      $dateFormatEnd = 'Y-m-d';
    }

    if (empty($start)) {
      $start = $this->post[$start_key] ?? NULL;
    }
    if (empty($end)) {
      $end = $this->post[$end_key] ?? NULL;
    }

    if (!empty($start) && $start != 'undefined') {
      $start_date = new DrupalDateTime($start, $time_timezone);
      $end_date = new DrupalDateTime($end, $time_timezone);

      if ($type_date[$type_key_start]['field_type'] == 'daterange' && $type_date[$type_key_start]['date_type'] == 'datetime') {
        $start_date->setTimezone($utc_timezone);
        $end_date->setTimezone($utc_timezone);
      }
      elseif ($type_date[$type_key_start]['date_type'] == 'datetime') {
        $start_date->setTimezone($utc_timezone);
        if (!empty($type_date[$type_key_end]['date_type']) && $type_date[$type_key_end]['date_type'] == 'datetime') {
          $end_date->setTimezone($utc_timezone);
        }
      }

      $type = $type_date[$type_key_start]["field_type"] == 'daterange' ? $type_date[$type_key_start]["date_type"] : $type_date[$type_key_end]["date_type"];
      if ($field_settings['last_of_the_day'] && $type == 'date') {
        $end_date->modify("-1 day");
      }

      return [
        'value' => $start_date->format($dateFormatStart),
        'end_value' => $end_date->format($dateFormatEnd),
      ];
    }
    return [
      'value' => NULL,
      'end_value' => NULL,
    ];
  }

  /**
   * Process Task.
   */
  protected function actionTask($action, $entity, $paragraph_type, $entity_field, $field_settings) {

    $output = ['action' => $action];
    if (!empty($this->post['isImport'])) {
      return $output;
    }
    $paragraph = $action == 'inserted'
      ? Paragraph::create(['type' => $paragraph_type->id()])
      : Paragraph::load($this->post["id"]);

    if (empty($paragraph)) {
      return $output;
    }

    if ($action == 'deleted') {
      $output['tid'] = $this->deleteParagraph($entity, $entity_field, $paragraph);
      return $output;
    }

    $this->setFieldValue($paragraph, $field_settings, $action);

    if ($action == 'inserted') {
      $paragraph->isNew();
    }
    $paragraph->save();
    $output['tid'] = $paragraph->id();

    if ($action == 'inserted') {
      $destination = $this->post['destination'] ?? '';
      $destination = str_replace('destination=', '', $destination);
      $destination = ['destination' => $destination];
      $output["link_detail"] = Url::fromRoute('paragraphs_gantt.edit', ['paragraph' => $paragraph->id()])
        ->setOptions(['query' => $destination])->toString();

      $entity->get($entity_field)->appendItem([
        'target_id' => $paragraph->id(),
        'target_revision_id' => $paragraph->getRevisionId(),
      ]);
      $entity->save();
    }
    else {
      $this->cacheTags->invalidateTags($entity->getCacheTags());
    }

    return $output;
  }

  /**
   * {@inheritDoc}
   */
  protected function actionLinks(string $action, EntityInterface $entity, ParagraphsTypeInterface $paragraph_type, string $entity_field, array $field_settings) {
    $output = ['action' => $action];
    $source = !empty($this->post['source']) ? $this->post['source'] : FALSE;
    $target = !empty($this->post['target']) ? $this->post['target'] : FALSE;
    $type = !empty($this->post['type']) ? $this->post['type'] : '0';
    if ($action == 'deleted') {
      [$source, $target] = str_contains($this->post['id'], '-')
      ? explode('-', $this->post['id'])
      : [$this->post['id'], NULL];
    }
    $paragraph = Paragraph::load($source);
    if (empty($paragraph)) {
      return $output;
    }
    // Schedule planned.
    if (!empty($this->post['listSchedulePlanned'])) {
      $fieldDefinitions = $paragraph->getFieldDefinitions();

      // Timezone current user.
      $user_timezone = $this->currentUser()->getTimeZone() ?? "UTC";
      $time_timezone = new \DateTimeZone($user_timezone);
      $utc_timezone = $user_timezone == 'UTC' ? $time_timezone : new \DateTimeZone('UTC');

      // Type date actually, planned.
      $type_date = $this->getTypeDateField($fieldDefinitions, $field_settings);

      // Set plan date.
      $this->updateSchedulePlanned($field_settings, $type_date, $time_timezone, $utc_timezone);
    }

    $linkValues = [];
    if (!$paragraph?->get($field_settings['links'])?->isEmpty()) {
      $linkValues = $paragraph->get($field_settings['links'])->getValue();
    }
    $lag = !empty($this->post['lag']) ? $this->post['lag'] : NULL;
    if ($action == 'inserted' || !empty($this->post['isImport'])) {
      $output['tid'] = "$source-$target";
      if ($paragraph->getFieldDefinition($field_settings['links']) && $paragraph->getFieldDefinition($field_settings['links'])->getType() == 'triples_field') {
        $linkValues[] = ['first' => $target, 'second' => $type, 'third' => $lag];
      }
      else {
        $linkValues[] = ['first' => $target, 'second' => $type];
      }
    }
    if ($action == 'updated') {
      foreach ($linkValues as $delta => $linkValue) {
        if ($linkValue['first'] == $target) {
          if ($paragraph->getFieldDefinition($field_settings['links']) && $paragraph->getFieldDefinition($field_settings['links'])->getType() == 'triples_field') {
            $linkValues[$delta] = [
              'first' => $target,
              'second' => $type,
              'third' => $lag,
            ];
          }
          else {
            $linkValues[$delta] = [
              'first' => $target,
              'second' => $type,
            ];
          }
        }
      }
    }
    if ($action == 'deleted') {
      foreach ($linkValues as $delta => $linkValue) {
        if ($linkValue['first'] == $target) {
          unset($linkValues[$delta]);
        }
      }
    }
    $paragraph->set($field_settings['links'], $linkValues);

    $paragraph->save();
    $this->cacheTags->invalidateTags($entity->getCacheTags());
    return $output;
  }

  /**
   * {@inheritDoc}
   */
  public function getTypeDateField($fieldDefinitions, $setting) {
    // Get type date field.
    $type_date = [
      'start_date_actually' => ['date_type' => '', 'field_type' => ''],
      'end_date_actually' => ['date_type' => '', 'field_type' => ''],
      'start_date_planned' => ['date_type' => '', 'field_type' => ''],
      'end_date_planned' => ['date_type' => '', 'field_type' => ''],
    ];
    $populateDateType = function ($settingKey, $typeKey) use (&$type_date, $fieldDefinitions, $setting) {
      if (!empty($setting[$settingKey]) && !empty($fieldDefinitions[$setting[$settingKey]])) {
        $dateSettings = $fieldDefinitions[$setting[$settingKey]]->getSettings();
        $type_date[$typeKey]['date_type'] = $dateSettings["datetime_type"];
        $type_date[$typeKey]['field_type'] = $fieldDefinitions[$setting[$settingKey]]->getType();
      }
    };
    $populateDateType('start_date', 'start_date_actually');
    $populateDateType('end_date', 'end_date_actually');
    $populateDateType('planned_date', 'start_date_planned');
    $populateDateType('planned_end_date', 'end_date_planned');

    return $type_date;
  }

  /**
   * {@inheritDoc}
   */
  protected function actionTaskQueue($action, $entity, $paragraph_type, $entity_field, $field_settings) {
    $output = ['action' => $action];
    $queue = $this->queueFactory->get('queue_task_paragraphs_gantt');
    $queue_worker = $this->queueWorkerManager->createInstance('queue_task_paragraphs_gantt');
    $data = [
      'current_user' => $this->currentUser()->id(),
      'data' => $this->post,
      'action' => $action,
      'entity' => $entity,
      'paragraph_type' => $paragraph_type,
      'entity_field' => $entity_field,
      'field_settings' => $field_settings,
    ];
    if ($queue->createItem($data)) {
      $output['tid'] = $this->post['tid'];
    }
    while ($item = $queue->claimItem()) {
      $queue_worker->processItem($item->data);
      $queue->deleteItem($item);
    }
    return $output;
  }

  /**
   * {@inheritDoc}
   */
  protected function setFieldValue(&$paragraph, $field_settings, $action) {
    $fieldDefinitions = $paragraph->getFieldDefinitions();

    // Timezone current user.
    $user_timezone = $this->currentUser()->getTimeZone() ?? "UTC";
    $time_timezone = new \DateTimeZone($user_timezone);
    $utc_timezone = $user_timezone == 'UTC' ? $time_timezone : new \DateTimeZone('UTC');

    // Type date actually, planned.
    $type_date = $this->getTypeDateField($fieldDefinitions, $field_settings);

    // Set start date.
    $actual_date = $this->processDate('start_date', 'end_date', $type_date, $field_settings, $time_timezone, $utc_timezone);
    // Set plan date.
    $planned_date = $this->processDate('planned_start', 'planned_end', $type_date, $field_settings, $time_timezone, $utc_timezone);

    // Set actual date and plan date.
    if (!empty($actual_date)) {
      if ($type_date['start_date_actually']['field_type'] == 'daterange') {
        $paragraph->set($field_settings['start_date'], $actual_date);
      }
      else {
        if (!empty($field_settings['start_date'])) {
          $paragraph->set($field_settings['start_date'], $actual_date['value']);
        }
        if (!empty($field_settings['end_date'])) {
          $paragraph->set($field_settings['end_date'], $actual_date['end_value']);
        }
      }
      if (!empty($field_settings['planned_date'])) {
        if ($type_date['start_date_planned']['field_type'] == 'daterange') {
          $paragraph->set($field_settings['planned_date'], $planned_date);
        }
        else {
          if (!empty($field_settings['planned_date'])) {
            $paragraph->set($field_settings['planned_date'], $planned_date['value']);
          }
          if (!empty($field_settings['planned_end_date'])) {
            $paragraph->set($field_settings['planned_end_date'], $planned_date['end_value']);
          }
        }
      }
    }

    // Set field option.
    $options = [
      'type',
      'duration',
      'progress',
      'priority',
      'planned_duration',
      'custom_field',
    ];
    foreach ($options as $option) {
      $value = $this->post[$option] ?? NULL;
      if (!empty($field_settings[$option]) && !empty($fieldDefinitions[$field_settings[$option]])) {
        $paragraph->set($field_settings[$option], $value);
      }
    }
    // Set text.
    if (!empty($field_settings['text']) && !empty($fieldDefinitions[$field_settings['text']])) {
      $paragraph->set($field_settings['text'], $this->post['text'] ?? 'Undefined');
    }
    // Set parent.
    if (!empty($field_settings['parent']) && !empty($fieldDefinitions[$field_settings['parent']])) {
      $paragraph->set($field_settings['parent'], $this->post['parent'] ?? NULL);
    }
    // Set open.
    if (!empty($field_settings['open']) && !empty($fieldDefinitions[$field_settings['open']])) {
      $paragraph->set($field_settings['open'], $this->post['open'] ?? 0);
    }
    // Set order.
    if (!empty($field_settings['order']) && !empty($fieldDefinitions[$field_settings['order']])) {
      $paragraph->set($field_settings['order'], $this->post['order'] ?? 0);
      if ($action == 'order' && !empty($this->post['listOrder'])) {
        $this->updateParagraphOrder($field_settings, $paragraph);
      }
    }
    // Set resource.
    if (!empty($field_settings["custom_resource"])) {
      foreach ($field_settings["custom_resource"] as $field_resource) {
        if ($field_settings["creator"] == $field_resource || empty($fieldDefinitions[$field_resource])) {
          continue;
        }
        $resource = [];
        $this->post[$field_resource] = !empty($this->post[$field_resource]) ? json_decode($this->post[$field_resource]) : [];
        if (is_array($this->post[$field_resource])) {
          foreach ($this->post[$field_resource] as $resource_id) {
            if (!empty($resource_id)) {
              $resource[] = ['target_id' => $resource_id];
            }
          }
        }
        else {
          $resource = [['target_id' => $this->post[$field_resource]]];
        }
        $paragraph->set($field_resource, $resource);
      }
    }
    // Set creator.
    if (!empty($field_settings["creator"]) && $action == 'inserted' && !empty($fieldDefinitions[$field_settings['creator']])) {
      $paragraph->set($field_settings["creator"], $this->currentUser()->id());
    }
    // Set constraint.
    if (!empty($field_settings["constraint"]) && !empty($this->post['constraint_type']) && !empty($fieldDefinitions[$field_settings['constraint']])) {
      $paragraph->set($field_settings["constraint"], [
        'first' => $this->post['constraint_type'] ?? NULL,
        'second' => $this->post['constraint_date'] ?? NULL,
      ]);
    }

    // Update schedule planned.
    if (!empty($this->post['listSchedulePlanned'])) {
      $this->updateSchedulePlanned($field_settings, $type_date, $time_timezone, $utc_timezone);
    }
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc