work_time-1.0.x-dev/src/Plugin/rest/resource/ApiWorkTimeResource.php

src/Plugin/rest/resource/ApiWorkTimeResource.php
<?php

namespace Drupal\work_time\Plugin\rest\resource;

use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\BcRoute;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\rest\ModifiedResourceResponse;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\user\Entity\User;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Represents Api Work Time records as resources.
 *
 * @RestResource (
 *   id = "api_work_time",
 *   label = @Translation("Api Work Time"),
 *   uri_paths = {
 *     "canonical" = "/api/work-time/{entity_id}/{entity_field}",
 *     "create" = "/api/work-time"
 *   }
 * )
 *
 * @DCG
 * This plugin exposes database records as REST resources. In order to enable it
 * import the resource configuration into active configuration storage. You may
 * find an example of such configuration in the following file:
 * core/modules/rest/config/optional/rest.resource.entity.node.yml.
 * Alternatively you can make use of REST UI module.
 * @see https://www.drupal.org/project/restui
 * For accessing Drupal entities through REST interface use
 * \Drupal\rest\Plugin\rest\resource\EntityResource plugin.
 */
class ApiWorkTimeResource extends ResourceBase implements DependentPluginInterface {

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $dbConnection;

  /**
   * Entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Current user service.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $account;

  /**
   * Constructs a Drupal\rest\Plugin\rest\resource\EntityResource object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param array $serializer_formats
   *   The available serialization formats.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   * @param \Drupal\Core\Database\Connection $db_connection
   *   The database connection.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Session\AccountProxyInterface $account
   *   The current user.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, array $serializer_formats, LoggerInterface $logger, Connection $db_connection, EntityTypeManagerInterface $entity_type_manager, AccountProxyInterface $account) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);
    $this->dbConnection = $db_connection;
    $this->entityTypeManager = $entity_type_manager;
    $this->account = $account;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->getParameter('serializer.formats'),
      $container->get('logger.factory')->get('rest'),
      $container->get('database'),
      $container->get('entity_type.manager'),
      $container->get('current_user'),
    );
  }

  /**
   * Responds to GET requests.
   *
   * @param int $entity_id
   *   Entity id.
   * @param string $entity_field
   *   Entity field.
   *
   * @return \Drupal\rest\ResourceResponse
   *   The response containing the record.
   */
  public function get($entity_id, $entity_field) {
    $records = FALSE;
    if ($entity_field == 'user') {
      $records = $this->getCurrentPlaying($entity_id);
    }
    else {
      $records = $this->loadEntities($entity_id, $entity_field);
    }
    return new ModifiedResourceResponse($records, 200);
  }

  /**
   * Responds to POST requests and saves the new record.
   *
   * @param mixed $data
   *   Data to write into the database.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   */
  public function post($data) {
    $workTimeStorage = $this->entityTypeManager->getStorage('work_time');
    $task = $type = '';
    $currentTimestamp = strtotime('now');
    // Load user's work time has stopped is null.
    $query = $workTimeStorage->getQuery()
      ->condition('uid', $this->account->id())
      ->condition('stopped', NULL, 'IS NULL');
    $workTimes = $query->execute();
    if (!empty($data['entityType']) && !empty($data['entityId'])) {
      $taskManager = $this->entityTypeManager->getStorage($type = $data['entityType']);
      $task = $taskManager->load($idTask = $data['entityId']);
      $taskManager->resetCache([$data['entityId']]);
    }
    // State is stopped.
    if (!empty($workTimes)) {
      foreach ($workTimes as $workTimeId) {
        $workTime = $workTimeStorage->load($workTimeId);
        $start = $workTime->get('created')->value;
        $workTime->set('stopped', $currentTimestamp);
        $workTime->set('time_total', $currentTimestamp - $start);
        $workTime->save();
        // Save value to field.
        if (!empty($task) && !empty($data['entityField']) && !empty($task->get($data['entityField']))) {
          $task->get($data['entityField'])->appendItem([
            'value' => gmdate(DateTimeItemInterface::DATETIME_STORAGE_FORMAT, $start),
            'end_value' => gmdate(DateTimeItemInterface::DATETIME_STORAGE_FORMAT, $currentTimestamp),
          ]);
          $task->save();
        }
      }
    }
    $label = $data['label'] ?? $this->t('New task');
    if (!empty($task)) {
      if (in_array($type, ['user'])) {
        $label = $task->getDisplayName();
      }
      elseif ($type == 'taxonomy_term') {
        $label = $task->getName();
      }
      elseif (method_exists($task, 'getTitle')) {
        $label = $task->getTitle();
      }
    }

    $label = empty($label) ? $this->t('New task') : $label;
    $created_record = ['data' => 'Worktime Save'];
    if ($data['play'] != 'true') {
      $workTime = $workTimeStorage
        ->create([
          'label' => $label,
          'uid' => $this->account->id(),
          'created' => $currentTimestamp,
          'entity_id' => $idTask ?? '',
          'entity_type' => $type ?? '',
          'entity_field' => $data['entityField'] ?? '',
          'reference_id' => $data['referenceId'] ?? '',
          'reference_field' => $data['referenceField'] ?? '',
          'reference_type' => $data['referenceType'] ?? '',
          'stopped' => NULL,
          'type' => 0,
        ]);
      $workTime->save();
      $id = $workTime->id();
      $created_record = $this->loadRecord($id);
    }

    // Return the newly created record in the response body.
    return new ModifiedResourceResponse($created_record, 200);
  }

  /**
   * Responds to entity PATCH requests.
   *
   * @param int $entity_id
   *   The ID of the record.
   * @param string $entity_field
   *   Type of data.
   * @param mixed $data
   *   Data to write into the database.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   */
  public function patch(int $entity_id = 0, $entity_field = '', $data = []) {
    $update_record = ['data' => 'Work time update'];
    if (empty($entity_id)) {
      $uid = $this->account->id();
      $query = $this->dbConnection->select('work_time', 'w')
        ->fields('w', ['id'])
        ->condition('stopped', '', 'IS NULL')
        ->condition('uid', $uid);
      $wids = $query->execute()->fetchCol();
      if (!empty($wids)) {
        $entity_id = current($wids);
      }
    }
    if ($entity_id) {
      $update_record = $this->updateRecord($entity_id, $data);
    }
    // Return the newly created record in the response body.
    return $update_record;
  }

  /**
   * Responds to entity DELETE requests.
   *
   * @param int $entity_id
   *   Entity id.
   * @param string $entity_field
   *   Entity Field.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   */
  public function delete($entity_id, $entity_field) {

    // Make sure the record still exists.
    $checkExist = $this->loadRecord($entity_id);
    if (!empty($checkExist)) {
      $this->dbConnection->delete('work_time')
        ->condition('id', $entity_id)
        ->execute();
      $this->logger->notice('Api Work Time record @id has been deleted.', ['@id' => $entity_id]);
    }
    // Deleted responses have an empty body.
    return new ModifiedResourceResponse(NULL, 204);
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function routes() {
    $collection = parent::routes();

    // Take out BC routes added in base class.
    // @see https://www.drupal.org/node/2865645
    // @todo Remove this in Drupal 9.
    foreach ($collection as $route_name => $route) {
      if ($route instanceof BcRoute) {
        $collection->remove($route_name);
      }
    }

    return $collection;
  }

  /**
   * Loads record from database.
   *
   * @param int $id
   *   The ID of the record.
   *
   * @return array
   *   The database record.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
   */
  protected function loadRecord($id) {
    $record = $this->dbConnection->query(
      'SELECT * FROM {work_time} WHERE id = :id', [':id' => $id])->fetchAssoc();
    if (!$record) {
      throw new NotFoundHttpException('The record was not found.');
    }
    return $record;
  }

  /**
   * Updates record.
   *
   * @param int $id
   *   The ID of the record.
   * @param array $record
   *   The record to validate.
   *
   * @return \Drupal\rest\ModifiedResourceResponse
   *   The HTTP response object.
   */
  protected function updateRecord($id, array $record) {

    // Make sure the record already exists.
    $this->loadRecord($id);

    $this->dbConnection->update('work_time')
      ->fields($record)
      ->condition('id', $id)
      ->execute();

    $this->logger->notice('Api Work Time record @id has been updated.', ['@id' => $id]);

    // Return the updated record in the response body.
    $updated_record = $this->loadRecord($id);
    return new ModifiedResourceResponse($updated_record, 200);
  }

  /**
   * {@inheritdoc}
   */
  protected function loadEntities($entity_id, $entity_field) {
    $query = $this->dbConnection->select('work_time', 'w')
      ->fields('w')
      ->condition('stopped', '', 'IS NOT NULL')
      ->condition('entity_id', $entity_id)
      ->condition('entity_field', $entity_field);
    $query->addExpression("FROM_UNIXTIME(created,'%Y-%m-%d')", 'date');
    $work_times = $query->execute();
    $records = [];
    $projects = [];
    $options = ['absolute' => TRUE];
    foreach ($work_times as $work_time) {
      $user = User::load($work_time->uid);
      if (empty($records[$work_time->uid])) {
        $name = $user->getDisplayName();
        preg_match_all('/(?<=\b)\w/iu', $name, $initials);
        $records[$work_time->uid] = [
          'name' => $name,
          'label' => $work_time->label,
          'initial' => strtoupper(implode('', array_slice($initials[0], 0, 2))),
          'details' => [],
        ];
      }

      if (!empty($work_time->reference_id) && !empty($work_time->reference_field) && empty($projects[$work_time->reference_id])) {
        $task = $this->entityTypeManager->getStorage($work_time->entity_type)
          ->load($entity_id);
        $referenceItem = $task->get($work_time->reference_field)
          ->referencedEntities();
        $node = current($referenceItem);
        $projects[$work_time->reference_id] = $node;
        $work_time->project = Link::fromTextAndUrl($node->getTitle(), $node->toUrl('canonical', $options))
          ->toString();
      }
      $records[$work_time->uid]['details'][] = (array) $work_time;
    }
    return array_values($records);
  }

  /**
   * {@inheritdoc}
   */
  private function getCurrentPlaying($entity_id) {
    $uid = $this->account->id();
    $query = $this->dbConnection->select('work_time', 'w')
      ->fields('w', ['created'])
      ->condition('stopped', '', 'IS NULL')
      ->condition('uid', $uid)
      ->condition('entity_id', $entity_id);
    $query->execute();
  }

}

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

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