Open Data Catalog v2.0.0
Service.php
Go to the documentation of this file.
1 <?php
2 
4 
6 use Drupal\Core\Config\ConfigFactory;
7 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
12 use Maquina\StateMachine\Machine;
13 use Maquina\StateMachine\MachineOfMachines;
14 use SqlParser\SqlParser;
15 use Symfony\Component\DependencyInjection\ContainerInterface;
16 
20 class Service implements ContainerInjectionInterface {
26  private $configFactory;
27 
33  private $datastoreService;
34 
38  public static function create(ContainerInterface $container) {
39  return new static(
40  $container->get('dkan.datastore.service'),
41  $container->get('config.factory')
42  );
43  }
44 
53  public function __construct(DatastoreService $datastoreService, ConfigFactory $configFactory) {
54 
55  $this->datastoreService = $datastoreService;
56  $this->configFactory = $configFactory;
57  }
58 
71  public function runQuery(string $queryString, $showDbColumns = FALSE): array {
72  $queryObject = $this->getQueryObject($queryString);
73 
74  $identifier = NULL; $version = NULL;
75  [$identifier, $version] = $this->getResourceIdentifierAndVersion($queryString);
76 
77  $databaseTable = $this->getDatabaseTable($identifier, $version);
78 
79  $result = $databaseTable->query($queryObject);
80 
81  $schema = $databaseTable->getSchema();
82  $fields = $schema['fields'];
83 
84  return array_map(function ($row) use ($fields, $showDbColumns) {
85  if (!$showDbColumns) {
86  unset($row->record_number);
87  }
88 
89  $arrayRow = (array) $row;
90 
91  $newRow = [];
92 
93  foreach ($arrayRow as $fieldName => $value) {
94  if (!$showDbColumns && isset($fields[$fieldName]['description']) && !empty($fields[$fieldName]['description'])) {
95  $newRow[$fields[$fieldName]['description']] = $value;
96  }
97  else {
98  $newRow[$fieldName] = $value;
99  }
100  }
101 
102  return (object) $newRow;
103  }, $result);
104  }
105 
117  public function getResourceIdentifierAndVersion(string $sqlString): array {
118  $stateMachine = $this->validate($sqlString);
119  $someIdentifier = $this->getTableNameFromSelect($stateMachine->gsm('select'));
120  return Resource::getIdentifierAndVersion($someIdentifier);
121  }
122 
126  private function getDatabaseTable($identifier, $version = NULL): DatabaseTable {
127  return $this->datastoreService->getStorage($identifier, $version);
128  }
129 
133  private function getTableNameFromSelect(MachineOfMachines $selectMachine): string {
134  $machine = $selectMachine->gsm('table_var');
135  $strings = $this->getStringsFromStringMachine($machine);
136  if (empty($strings)) {
137  throw new \Exception("No table name");
138  }
139  return $strings[0];
140  }
141 
151  private function getQueryObject(string $sqlString): Query {
152  return $this->getQueryObjectFromStateMachine($this->validate($sqlString));
153  }
154 
158  private function validate(string $sqlString): MachineOfMachines {
159  $parser = new SqlParser();
160  if ($parser->validate($sqlString) === FALSE) {
161  throw new \Exception("Invalid query string.");
162  }
163 
164  return $parser->getValidatingMachine();
165  }
166 
176  private function getQueryObjectFromStateMachine(MachineOfMachines $state_machine): Query {
177  $object = new Query();
178  $this->setQueryObjectSelect($object, $state_machine->gsm('select'));
179  $this->setQueryObjectWhere($object, $state_machine->gsm('where'));
180  $this->setQueryObjectOrderBy($object, $state_machine->gsm('order_by'));
181  $this->setQueryObjectLimit($object, $state_machine->gsm('limit'));
182 
183  return $object;
184  }
185 
194  private function setQueryObjectSelect(Query $object, MachineOfMachines $state_machine) {
195  $strings = $this->getStringsFromStringMachine($state_machine->gsm('select_count_all'));
196  if (!empty($strings)) {
197  $object->count();
198  return;
199  }
200 
201  $strings = $this->getStringsFromStringMachine($state_machine->gsm('select_var_all'));
202  if (!empty($strings)) {
203  return;
204  }
205 
206  $strings = $this->getStringsFromStringMachine($state_machine->gsm('select_var'));
207  foreach ($strings as $property) {
208  $object->filterByProperty($property);
209  }
210  }
211 
220  private function setQueryObjectWhere(Query $object, MachineOfMachines $state_machine) {
221  $properties = $this->getStringsFromStringMachine($state_machine->gsm('where_column'));
222  $quoted_string = $state_machine->gsm('quoted_string');
223  if (!($quoted_string instanceof MachineOfMachines)) {
224  throw new \Exception("State machine error.");
225  }
226  $values = $this->getStringsFromStringMachine($quoted_string->gsm('string'));
227 
228  foreach ($properties as $index => $property) {
229  $value = $values[$index];
230  if ($value) {
231  $object->conditionByIsEqualTo($property, $value);
232  }
233  }
234  }
235 
244  private function setQueryObjectOrderBy(Query $object, MachineOfMachines $state_machine) {
245  $properties = $this->getStringsFromStringMachine($state_machine->gsm('order_var'));
246 
247  $direction = $this->getStringsFromStringMachine($state_machine->gsm('order_asc'));
248  $sortMethod = (!empty($direction)) ? "sortByAscending" : "sortByDescending";
249 
250  foreach ($properties as $property) {
251  $object->$sortMethod($property);
252  }
253  }
254 
258  private function setQueryObjectLimit(Query $object, MachineOfMachines $state_machine) {
259  $limit = $this->getStringsFromStringMachine($state_machine->gsm('numeric1'));
260 
261  if (empty($limit)) {
262  return;
263  }
264 
265  $limit = $limit[0];
266 
267  $rows_limit = $this->configFactory->get('datastore.settings')->get('rows_limit');
268  if (!$object->count && isset($limit) && $limit > $rows_limit) {
269  $limit = $rows_limit;
270  }
271 
272  $object->limitTo($limit);
273 
274  $offset = $this->getStringsFromStringMachine($state_machine->gsm('numeric2'));
275 
276  if (!empty($offset)) {
277  $object->offsetBy($offset[0]);
278  }
279  }
280 
284  private function getStringsFromStringMachine(Machine $machine): array {
285  return (new GetStringsFromStateMachineExecution($machine->execution))->get();
286  }
287 
291  public function getResourceUuid(string $sqlString) {
292  $stateMachine = $this->validate($sqlString);
293  $identifier = $this->getTableNameFromSelect($stateMachine->gsm('select'));
294 
295  // Are we dealing with a distribution id?
296  if (substr_count($identifier, '__') == 0) {
297  return $identifier;
298  }
299  return NULL;
300  }
301 
302 }
Drupal\common\Resource
Definition: Resource.php:28
Drupal\datastore\SqlEndpoint\Helper\GetStringsFromStateMachineExecution
Definition: GetStringsFromStateMachineExecution.php:8
Drupal\datastore\SqlEndpoint
Drupal\datastore\SqlEndpoint\Service\create
static create(ContainerInterface $container)
Definition: Service.php:38
Drupal\datastore\Service
Definition: DatastoreQuery.php:3
Drupal\datastore\SqlEndpoint\Service
Definition: Service.php:20
Drupal\common\Storage\Query
Definition: Query.php:13
Drupal\common\Resource\getIdentifierAndVersion
static getIdentifierAndVersion($string)
Definition: Resource.php:197
Drupal\datastore\SqlEndpoint\Service\__construct
__construct(DatastoreService $datastoreService, ConfigFactory $configFactory)
Definition: Service.php:53
Drupal\datastore\SqlEndpoint\Service\getResourceIdentifierAndVersion
getResourceIdentifierAndVersion(string $sqlString)
Definition: Service.php:117
Drupal\datastore\Storage\DatabaseTable
Definition: DatabaseTable.php:15
Drupal\datastore\SqlEndpoint\Service\runQuery
runQuery(string $queryString, $showDbColumns=FALSE)
Definition: Service.php:71
Drupal\datastore\SqlEndpoint\Service\getResourceUuid
getResourceUuid(string $sqlString)
Definition: Service.php:291