fox-1.1.2/src/FoxEntityQuery.php

src/FoxEntityQuery.php
<?php

declare(strict_types=1);

namespace Drupal\fox;

use Drupal\Component\Serialization\Json;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\fox\FoxCommandsHelper as Helper;
use PHPSQLParser\PHPSQLParser;

/**
 * Fox entity query service.
 */
class FoxEntityQuery {

  use StringTranslationTrait;
  use FoxCommandsHelperTrait;
  use FoxCommonFunctionsTrait;

  /**
   * Do entity query.
   *
   * @param string $input
   *   User input.
   * @param array $variables
   *   Current variables.
   * @param array $options
   *   Options values.
   *
   * @return array
   *   Result data.
   */
  public function doEntityQuery(string $input, array $variables, array $options): array {
    $helper = $this->foxCommandsHelper();
    $query_string = $helper->stringRender($input, $variables);

    $parser = new PHPSQLParser($query_string);
    $parsed = $parser->parsed;
    if (empty($parsed)) {
      return $this->errorReturn($this->t('Wrong query or command: "@input"', [
        '@input' => $input,
      ]));
    }

    $debug = $options['mode'] === 'debug';

    $entity_type = $variables['entity_type'] ?? NULL;
    $bundle = $variables['bundle'] ?? NULL;

    // FROM clause.
    if (isset($parsed['FROM'])) {
      $from = current($parsed['FROM'])['no_quotes']['parts'];
      [$entity_type, $bundle] = Helper::getTypeBundle($from);
    }
    else {
      if (empty($entity_type)) {
        return $this->errorReturn($this->t('Empty entity type'));
      }
    }

    try {
      $query = $helper->getEntityQuery($entity_type, $bundle);

      // WHERE clause.
      $where = $parsed['WHERE'] ?? NULL;
      if ($where) {
        $groups = $this->parseWhere($where);
        foreach ($groups as $group) {
          $conditionGroup = NULL;
          if ($group['group_operator'] === 'AND') {
            $conditionGroup = $query->andConditionGroup();
          }
          elseif ($group['group_operator'] === 'OR') {
            $conditionGroup = $query->orConditionGroup();
          }
          if (empty($conditionGroup)) {
            continue;
          }

          foreach ($group['conditions'] as $condition) {
            $value = Helper::prepareValue($condition['value']);
            $conditionGroup->condition($condition['field'], $value, $condition['operator']);
          }
          $query->condition($conditionGroup);
        }
      }

      // ORDER clause.
      $orders = $parsed['ORDER'] ?? NULL;
      if ($orders) {
        foreach ($orders as $order) {
          $query->sort($order['base_expr'], $order['direction']);
        }
      }

      // LIMIT clause.
      $limits = $parsed['LIMIT'] ?? NULL;
      if ($limits) {
        $offset = 0;
        if (is_numeric($limits['offset'])) {
          $offset = $limits['offset'];
        }
        $limit = $limits['rowcount'];
        $query->range($offset, $limit);
      }

      $ids = $query->execute();
    }
    catch (\Exception $e) {
      return $this->errorReturn($e->getMessage());
    }

    // Format data.
    $data = $header = $entities = [];
    $header[] = '#';
    $number = 1;
    // SELECT clause.
    $select = $parsed['SELECT'] ?? NULL;
    if ($select) {
      if (!empty($ids)) {
        $entities = $helper->entityTypeManager()
          ->getStorage($entity_type)
          ->loadMultiple($ids);
      }

      $all_fields = FALSE;
      foreach ($select as $id => $field) {
        $name = $field['base_expr'];
        if ($name === '*') {
          $all_fields = TRUE;
          unset($select[$id]);
          continue;
        }
        $header[] = ucfirst($name);
      }

      // Get fields from entity type definition.
      if ($all_fields) {
        $entity_types_definitions = $helper
          ->entityTypeManager()
          ->getDefinitions();
        $entity_type_definition = $entity_types_definitions[$entity_type] ?? NULL;
        if ($entity_type_definition) {
          $entity_type_group = $entity_type_definition->getGroup();

          if ($entity_type_group === 'content') {
            $definitions = $helper
              ->entityFieldManager()
              ->getFieldDefinitions($entity_type, $bundle ?? $entity_type);
          }
          else {
            $definitions = $entity_type_definition->getPropertiesToExport();
          }

          foreach (array_keys($definitions) as $field) {
            $header[] = ucfirst($field);
            $select[] = ['base_expr' => $field];
          }
        }
      }

      foreach ($entities as $entity) {
        $row = [];
        $row[] = $number++;
        foreach ($select as $field) {
          $name = $field['base_expr'];
          if (method_exists($entity, 'hasField') && !$entity->hasField($name)) {
            return $this->errorReturn($this->t('Wrong field "@name"', [
              '@name' => $name,
            ]));
          }

          $value = $entity->get($name);
          if (!$value) {
            $value = '';
          }

          if (is_object($value)) {
            $value = $value->getString();
          }
          elseif (is_array($value)) {
            $value = Json::encode($value);
          }

          $row[$name] = $value;
        }
        $data[] = $row;
      }
    }
    else {
      $header[] = $this->t('Id');
      foreach ($ids as $id) {
        $data[] = [$number++, $id];
      }
    }

    $result = [
      'message' => [
        'header' => $header,
        'data' => $data,
      ],
      'variables' => [
        'entity_type' => $entity_type,
        'bundle' => $bundle,
        'count' => count($data),
        'id' => NULL,
      ],
    ];

    // Set first occurency to record.
    if (!empty($ids)) {
      $first_id = reset($ids);
      $recno = $helper->getRecnoById($first_id, $result['variables']);
      if ($recno) {
        $result['variables']['id'] = $first_id;
        $result['variables']['recno'] = $recno;
      }
    }
    else {
      $result['variables']['id'] = NULL;
      $result['variables']['recno'] = NULL;
      $result['warning'] = $this->t('Empty data');
    }

    // INTO clause.
    $into = $parsed['INTO'] ?? NULL;
    if ($into) {
      $name = $into[1];
      $result['variables']['into'][$name] = $data ?? [];
      $result['message'] = [];
    }

    if ($debug) {
      if (method_exists($query, '__toString')) {
        $result['debug'] = (string) $query;
      }
    }

    return $result;
  }

  /**
   * Where parsing.
   *
   * @param array $where
   *   Where data.
   *
   * @return array
   *   Condition groups.
   */
  protected function parseWhere(array $where): array {
    $groups = [];
    $current_group_operator = NULL;
    $group_index = -1;
    for ($i = 0; $i < count($where);) {
      if ($where[$i]['expr_type'] == 'colref') {
        $value = $where[$i + 2]['base_expr'];
        if ($where[$i + 2]['expr_type'] === 'in-list') {
          $value = [];
          foreach ($where[$i + 2]['sub_tree'] as $item) {
            $value[] = $item['base_expr'];
          }
        }

        $condition = [
          'field' => $where[$i]['base_expr'],
          'operator' => $where[$i + 1]['base_expr'],
          'value' => $value,
        ];
        $i += 3;
      }

      if ($i >= count($where)) {
        if (empty($current_group_operator)) {
          $group_operator = 'AND';
          $groups[++$group_index] = [
            'group_operator' => $group_operator,
            'conditions' => [0 => $condition],
          ];
        }
        else {
          $groups[$group_index]['conditions'][] = $condition;
        }
        break;
      }

      if ($where[$i]['expr_type'] == 'operator' && !empty($condition)) {
        $group_operator = strtoupper($where[$i]['base_expr']);
        if ($group_operator != $current_group_operator) {
          $groups[++$group_index] = [
            'group_operator' => $group_operator,
            'conditions' => [0 => $condition],
          ];
          $current_group_operator = $group_operator;
        }
        else {
          $groups[$group_index]['conditions'][] = $condition;
        }
      }

      if ($where[$i]['expr_type'] == 'bracket_expression') {
        $sub_tree = $where[$i]['sub_tree'];
        $sub_group = $this->parseWhere($sub_tree);
        $groups = array_merge($groups, $sub_group);
      }

      $i++;
    }

    return $groups;
  }

}

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

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