Open Data Catalog v2.0.0
AbstractDatabaseTable.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use Contracts\RemoverInterface;
6 use Contracts\RetrieverInterface;
7 use Contracts\StorerInterface;
8 use Dkan\Datastore\Storage\StorageInterface;
9 use Dkan\Datastore\Storage\Database\SqlStorageTrait;
10 use Drupal\Core\Database\Connection;
12 
16 abstract class AbstractDatabaseTable implements StorageInterface, StorerInterface, RetrieverInterface, RemoverInterface {
17  use SqlStorageTrait;
18  use QueryToQueryHelperTrait;
19 
20  protected $connection;
21 
28  abstract protected function getTableName();
29 
36  abstract protected function prepareData(string $data, string $id = NULL): array;
37 
41  abstract protected function primaryKey();
42 
49  public function __construct(Connection $connection) {
50  $this->connection = $connection;
51 
52  if ($this->tableExist($this->getTableName())) {
53  $this->setSchemaFromTable();
54  }
55  }
56 
62  public function retrieve(string $id) {
63  $this->setTable();
64 
65  /* @var $statement StatementInterface */
66  $statement = $this->connection->select($this->getTableName(), 't')
67  ->fields('t', array_keys($this->getSchema()['fields']))
68  ->condition($this->primaryKey(), $id)
69  ->execute();
70 
71  // The docs do not mention it, but fetch can return false.
72  $return = (isset($statement)) ? $statement->fetch() : NULL;
73 
74  return ($return === FALSE) ? NULL : $return;
75  }
76 
82  public function retrieveAll(): array {
83  $this->setTable();
84  $tableName = $this->getTableName();
85 
86  $result = $this->connection->select($tableName, 't')
87  ->fields('t', [$this->primaryKey()])
88  ->execute()
89  ->fetchAll();
90 
91  if ($result === FALSE) {
92  return [];
93  }
94 
95  $result = array_map(function ($item) {
96  return $item->{$this->primaryKey()};
97  }, $result);
98 
99  return $result;
100  }
101 
105  public function store($data, string $id = NULL): string {
106  $this->setTable();
107 
108  $existing = (isset($id)) ? $this->retrieve($id) : NULL;
109 
110  $data = $this->prepareData($data, $id);
111 
112  $returned_id = NULL;
113 
114  if ($existing === NULL) {
115  $fields = $this->getNonSerialFields();
116 
117  if (count($fields) != count($data)) {
118  throw new \Exception("The number of fields and data given do not match: fields - " .
119  json_encode($fields) . " data - " . json_encode($data));
120  }
121 
122  $q = $this->connection->insert($this->getTableName());
123  $q->fields($fields);
124  $q->values($data);
125  $returned_id = $q->execute();
126  }
127  else {
128  $q = $this->connection->update($this->getTableName());
129  $q->fields($data)
130  ->condition($this->primaryKey(), $id)
131  ->execute();
132  }
133 
134  return ($returned_id) ? "$returned_id" : "{$id}";
135  }
136 
146  public function storeMultiple(array $data) : string {
147  $this->setTable();
148 
149  $fields = $this->getNonSerialFields();
150 
151  $q = $this->connection->insert($this->getTableName());
152  $q->fields($fields);
153  foreach ($data as $datum) {
154  $datum = $this->prepareData($datum);
155  if (count($fields) != count($datum)) {
156  throw new \Exception("The number of fields and data given do not match: fields - " .
157  json_encode($fields) . " data - " . json_encode($datum));
158  }
159  $q->values($datum);
160  }
161  return $q->execute();
162  }
163 
167  protected function getNonSerialFields() {
168  $fields = [];
169  foreach ($this->schema['fields'] as $field => $info) {
170  if ($info['type'] != 'serial') {
171  $fields[] = $field;
172  }
173  }
174  return $fields;
175  }
176 
182  public function remove(string $id) {
183  $tableName = $this->getTableName();
184  $this->connection->delete($tableName)
185  ->condition($this->primaryKey(), $id)
186  ->execute();
187  }
188 
192  public function count(): int {
193  $this->setTable();
194  $query = $this->connection->select($this->getTableName());
195  return $query->countQuery()->execute()->fetchField();
196  }
197 
204  public function query(Query $query): array {
205  $this->setTable();
206  $db_query = $this->connection->select($this->getTableName(), 't')
207  ->fields('t', $query->properties);
208 
209  $this->setQueryConditions($db_query, $query);
210  $this->setQueryOrderBy($db_query, $query);
211  $this->setQueryLimitAndOffset($db_query, $query);
212 
213  if ($query->count) {
214  $db_query = $db_query->countQuery();
215  }
216 
217  $result = $db_query->execute()->fetchAll();
218 
219  return $result;
220  }
221 
225  private function setTable() {
226  if (!$this->tableExist($this->getTableName())) {
227  if ($this->schema) {
228  $this->tableCreate($this->getTableName(), $this->schema);
229  }
230  else {
231  throw new \Exception("Could not instantiate the table due to a lack of schema.");
232  }
233  }
234  }
235 
241  public function destroy() {
242  if ($this->tableExist($this->getTableName())) {
243  $this->connection->schema()->dropTable($this->getTableName());
244  }
245  }
246 
250  private function tableExist($table_name) {
251  $exists = $this->connection->schema()->tableExists($table_name);
252  return $exists;
253  }
254 
258  private function tableCreate($table_name, $schema) {
259  $this->connection->schema()->createTable($table_name, $schema);
260  }
261 
265  private function setSchemaFromTable() {
266  $fields_info = $this->connection->query("DESCRIBE `{$this->getTableName()}`")->fetchAll();
267  if (!empty($fields_info)) {
268  $fields = $this->getFieldsFromFieldsInfo($fields_info);
269  $this->setSchema($this->getTableSchema($fields));
270  }
271  }
272 
279  private function getFieldsFromFieldsInfo(array $fieldsInfo) {
280  $fields = [];
281  foreach ($fieldsInfo as $info) {
282  $fields[] = $info->Field;
283  }
284  return $fields;
285  }
286 
290  private function getTableSchema($fields) {
291  $schema = [];
292  $header = $fields;
293  foreach ($header as $field) {
294  $schema['fields'][$field] = [
295  'type' => "text",
296  ];
297  }
298  return $schema;
299  }
300 
301 }
Drupal\dkan_common\Storage\AbstractDatabaseTable\$connection
$connection
Definition: AbstractDatabaseTable.php:20
Drupal\dkan_datastore\Storage\Query
Definition: Query.php:13
Drupal\dkan_common\Storage\AbstractDatabaseTable\primaryKey
primaryKey()
Drupal\dkan_common\Storage\AbstractDatabaseTable\query
query(Query $query)
Definition: AbstractDatabaseTable.php:204
Drupal\dkan_common\Storage\AbstractDatabaseTable\store
store($data, string $id=NULL)
Definition: AbstractDatabaseTable.php:105
Drupal\dkan_common\Storage\AbstractDatabaseTable\storeMultiple
storeMultiple(array $data)
Definition: AbstractDatabaseTable.php:146
Drupal\dkan_common\Storage\AbstractDatabaseTable\__construct
__construct(Connection $connection)
Definition: AbstractDatabaseTable.php:49
Drupal\dkan_common\Storage\AbstractDatabaseTable\getTableName
getTableName()
Drupal\dkan_common\Storage\AbstractDatabaseTable\prepareData
prepareData(string $data, string $id=NULL)
Drupal\dkan_common\Storage\AbstractDatabaseTable\retrieve
retrieve(string $id)
Definition: AbstractDatabaseTable.php:62
Drupal\dkan_common\Storage\AbstractDatabaseTable\destroy
destroy()
Definition: AbstractDatabaseTable.php:241
Drupal\dkan_common\Storage\AbstractDatabaseTable\retrieveAll
retrieveAll()
Definition: AbstractDatabaseTable.php:82
Drupal\dkan_common\Storage\AbstractDatabaseTable
Definition: AbstractDatabaseTable.php:16
Drupal\dkan_datastore\Storage\Query\count
count()
Definition: Query.php:82
Drupal\dkan_common\Storage\AbstractDatabaseTable\count
count()
Definition: AbstractDatabaseTable.php:192
Drupal\dkan_common\Storage\AbstractDatabaseTable\getNonSerialFields
getNonSerialFields()
Definition: AbstractDatabaseTable.php:167
Drupal\dkan_common\Storage
Definition: AbstractDatabaseTable.php:3