Open Monograph Press  3.3.0
SchemaDAO.inc.php
1 <?php
15 import('lib.pkp.classes.db.DAO');
16 import('classes.core.Services');
17 
18 abstract class SchemaDAO extends DAO {
20  var $schemaName;
21 
24 
27 
30 
32  var $primaryTableColumns = array();
33 
39  abstract public function newDataObject();
40 
46  public function getById($objectId) {
47  $result = $this->retrieve(
48  'SELECT * FROM ' . $this->tableName . ' WHERE ' . $this->primaryKeyColumn . ' = ?',
49  (int) $objectId
50  );
51 
52  $returner = null;
53  if ($result->RecordCount() != 0) {
54  $returner = $this->_fromRow($result->GetRowAssoc(false));
55  }
56  $result->Close();
57  return $returner;
58  }
59 
66  public function insertObject($object) {
67  $schemaService = Services::get('schema');
68  $schema = $schemaService->get($this->schemaName);
69  $sanitizedProps = $schemaService->sanitize($this->schemaName, $object->_data);
70 
71  $primaryDbProps = $this->_getPrimaryDbProps($object);
72 
73  if (empty($primaryDbProps)) {
74  throw new Exception('Tried to insert ' . get_class($object) . ' without any properties for the ' . $this->tableName . ' table.');
75  }
76 
77  $columnsList = join(', ', array_keys($primaryDbProps));
78  $bindList = join(', ', array_fill(0, count($primaryDbProps), '?'));
79  $this->update("INSERT INTO $this->tableName ($columnsList) VALUES ($bindList)", array_values($primaryDbProps));
80 
81  $object->setId($this->getInsertId());
82 
83  // Add additional properties to settings table if they exist
84  if (count($sanitizedProps) !== count($primaryDbProps)) {
85  $columns = array($this->primaryKeyColumn, 'locale', 'setting_name', 'setting_value');
86  $columnsList = join(', ', $columns);
87  $bindList = join(', ', array_fill(0, count($columns), '?'));
88  foreach ($schema->properties as $propName => $propSchema) {
89  if (!isset($sanitizedProps[$propName]) || array_key_exists($propName, $this->primaryTableColumns)) {
90  continue;
91  }
92  if (!empty($propSchema->multilingual)) {
93  foreach ($sanitizedProps[$propName] as $localeKey => $localeValue) {
94  $this->update("INSERT INTO $this->settingsTableName ($columnsList) VALUES ($bindList)", array(
95  $object->getId(),
96  $localeKey,
97  $propName,
98  $this->convertToDB($localeValue, $schema->properties->{$propName}->type),
99  ));
100  }
101  } else {
102  $this->update("INSERT INTO $this->settingsTableName ($columnsList) VALUES ($bindList)", array(
103  $object->getId(),
104  '',
105  $propName,
106  $this->convertToDB($sanitizedProps[$propName], $schema->properties->{$propName}->type),
107  ));
108  }
109  }
110  }
111 
112  return $object->getId();
113  }
114 
130  public function updateObject($object) {
131  $schemaService = Services::get('schema');
132  $schema = $schemaService->get($this->schemaName);
133  $sanitizedProps = $schemaService->sanitize($this->schemaName, $object->_data);
134 
135  $primaryDbProps = $this->_getPrimaryDbProps($object);
136 
137  $set = join('=?,', array_keys($primaryDbProps)) . '=?';
138  $this->update(
139  "UPDATE $this->tableName SET $set WHERE $this->primaryKeyColumn = ?",
140  array_merge(array_values($primaryDbProps), array($object->getId()))
141  );
142 
143  $deleteSettings = [];
144  $keyColumns = [$this->primaryKeyColumn, 'locale', 'setting_name'];
145  foreach ($schema->properties as $propName => $propSchema) {
146  if (array_key_exists($propName, $this->primaryTableColumns)) {
147  continue;
148  } elseif (!isset($sanitizedProps[$propName])) {
149  $deleteSettings[] = $propName;
150  continue;
151  }
152  if (!empty($propSchema->multilingual)) {
153  foreach ($sanitizedProps[$propName] as $localeKey => $localeValue) {
154  // Delete rows with a null value
155  if (is_null($localeValue)) {
156  $this->update("DELETE FROM $this->settingsTableName WHERE $this->primaryKeyColumn = ? AND setting_name = ? AND locale = ?", [
157  $object->getId(),
158  $propName,
159  $localeKey,
160  ]);
161  } else {
162  $updateArray = [
163  $this->primaryKeyColumn => $object->getId(),
164  'locale' => $localeKey,
165  'setting_name' => $propName,
166  'setting_value' => $this->convertToDB($localeValue, $schema->properties->{$propName}->type),
167  ];
168  $this->replace($this->settingsTableName, $updateArray, $keyColumns);
169  }
170  }
171  } else {
172  $updateArray = [
173  $this->primaryKeyColumn => $object->getId(),
174  'locale' => '',
175  'setting_name' => $propName,
176  'setting_value' => $this->convertToDB($sanitizedProps[$propName], $schema->properties->{$propName}->type),
177  ];
178  $this->replace($this->settingsTableName, $updateArray, $keyColumns);
179  }
180  }
181 
182  if (count($deleteSettings)) {
183  $deleteSettingNames = join(',', array_map(function($settingName) {
184  return "'$settingName'";
185  }, $deleteSettings));
186  $this->update("DELETE FROM $this->settingsTableName WHERE $this->primaryKeyColumn = ? AND setting_name in ($deleteSettingNames)", [
187  $object->getId(),
188  ]);
189  }
190  }
191 
199  public function deleteObject($object) {
200  $this->deleteById($object->getId());
201  }
202 
208  public function deleteById($objectId) {
209  $this->update(
210  "DELETE FROM $this->tableName WHERE $this->primaryKeyColumn = ?",
211  (int) $objectId
212  );
213  $this->update(
214  "DELETE FROM $this->settingsTableName WHERE $this->primaryKeyColumn = ?",
215  (int) $objectId
216  );
217  }
218 
225  public function _fromRow($primaryRow) {
226  $schemaService = Services::get('schema');
227  $schema = $schemaService->get($this->schemaName);
228 
229  $object = $this->newDataObject();
230 
231  foreach ($this->primaryTableColumns as $propName => $column) {
232  if (isset($primaryRow[$column])) {
233  $object->setData(
234  $propName,
235  $this->convertFromDb($primaryRow[$column], $schema->properties->{$propName}->type)
236  );
237  }
238  }
239 
240  $result = $this->retrieve(
241  "SELECT * FROM $this->settingsTableName WHERE $this->primaryKeyColumn = ?",
242  array($primaryRow[$this->primaryKeyColumn])
243  );
244 
245  while (!$result->EOF) {
246  $settingRow = $result->getRowAssoc(false);
247  if (!empty($schema->properties->{$settingRow['setting_name']})) {
248  $object->setData(
249  $settingRow['setting_name'],
250  $this->convertFromDB(
251  $settingRow['setting_value'],
252  $schema->properties->{$settingRow['setting_name']}->type
253  ),
254  empty($settingRow['locale']) ? null : $settingRow['locale']
255  );
256  }
257  $result->MoveNext();
258  }
259 
260  return $object;
261  }
262 
267  public function getInsertId() {
268  return $this->_getInsertId($this->tableName, $this->primaryKeyColumn);
269  }
270 
277  private function _getPrimaryDbProps($object) {
278  $schema = Services::get('schema')->get($this->schemaName);
279  $sanitizedProps = Services::get('schema')->sanitize($this->schemaName, $object->_data);
280 
281  $primaryDbProps = [];
282  foreach ($this->primaryTableColumns as $propName => $columnName) {
283  if ($propName !== 'id' && array_key_exists($propName, $sanitizedProps)) {
284  $primaryDbProps[$columnName] = $this->convertToDB($sanitizedProps[$propName], $schema->properties->{$propName}->type);
285  // Convert empty string values for DATETIME columns into null values
286  // because an empty string can not be saved to a DATETIME column
287  if ($primaryDbProps[$columnName] === ''
288  && isset($schema->properties->{$propName}->validation)
289  && (
290  in_array('date_format:Y-m-d H:i:s', $schema->properties->{$propName}->validation)
291  || in_array('date_format:Y-m-d', $schema->properties->{$propName}->validation)
292  )
293  ) {
294  $primaryDbProps[$columnName] = null;
295  }
296  }
297  }
298 
299  return $primaryDbProps;
300  }
301 }
SchemaDAO\updateObject
updateObject($object)
Definition: SchemaDAO.inc.php:145
SchemaDAO\$primaryKeyColumn
$primaryKeyColumn
Definition: SchemaDAO.inc.php:41
DAO\retrieve
& retrieve($sql, $params=false, $callHooks=true)
Definition: DAO.inc.php:85
SchemaDAO\$tableName
$tableName
Definition: SchemaDAO.inc.php:29
SchemaDAO\insertObject
insertObject($object)
Definition: SchemaDAO.inc.php:81
SchemaDAO\getById
getById($objectId)
Definition: SchemaDAO.inc.php:61
SchemaDAO\$schemaName
$schemaName
Definition: SchemaDAO.inc.php:23
SchemaDAO\newDataObject
newDataObject()
SchemaDAO\deleteById
deleteById($objectId)
Definition: SchemaDAO.inc.php:223
SchemaDAO\$settingsTableName
$settingsTableName
Definition: SchemaDAO.inc.php:35
DAO\update
update($sql, $params=false, $callHooks=true, $dieOnError=true)
Definition: DAO.inc.php:214
SchemaDAO\_fromRow
_fromRow($primaryRow)
Definition: SchemaDAO.inc.php:240
SchemaDAO\getInsertId
getInsertId()
Definition: SchemaDAO.inc.php:282
SchemaDAO\deleteObject
deleteObject($object)
Definition: SchemaDAO.inc.php:214
DAO
Operations for retrieving and modifying objects from a database.
Definition: DAO.inc.php:31
SchemaDAO\$primaryTableColumns
$primaryTableColumns
Definition: SchemaDAO.inc.php:47
SchemaDAO
A base class for DAOs which rely on a json-schema file to define the data object.
Definition: SchemaDAO.inc.php:18
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49