Open Monograph Press  3.3.0
FilterDAO.inc.php
1 <?php
2 
42 import('lib.pkp.classes.filter.Filter');
43 
44 class FilterDAO extends DAO {
47 
50 
51 
66  function configureObject($filterClassName, $filterGroupSymbolic, $settings = array(), $asTemplate = false, $contextId = 0, $subFilters = array(), $persist = true) {
67  // Retrieve the filter group from the database.
68  $filterGroupDao = DAORegistry::getDAO('FilterGroupDAO'); /* @var $filterGroupDao FilterGroupDAO */
69  $filterGroup = $filterGroupDao->getObjectBySymbolic($filterGroupSymbolic);
70  if (!is_a($filterGroup, 'FilterGroup')) return false;
71 
72  // Instantiate the filter.
73  $filter = instantiate($filterClassName, 'PersistableFilter', null, 'execute', $filterGroup); /* @var $filter PersistableFilter */
74  if (!is_object($filter)) return false;
75 
76  // Is this a template?
77  $filter->setIsTemplate((boolean)$asTemplate);
78 
79  // Add sub-filters (if any).
80  if (!empty($subFilters)) {
81  assert(is_a($filter, 'CompositeFilter'));
82  assert(is_array($subFilters));
83  foreach($subFilters as $subFilter) {
84  $filter->addFilter($subFilter);
85  unset($subFilter);
86  }
87  }
88 
89  // Parameterize the filter.
90  assert(is_array($settings));
91  foreach($settings as $key => $value) {
92  $filter->setData($key, $value);
93  }
94 
95  // Persist the filter.
96  if ($persist) {
97  $filterId = $this->insertObject($filter, $contextId);
98  if (!is_integer($filterId) || $filterId == 0) return false;
99  }
100 
101  return $filter;
102  }
103 
111  function insertObject($filter, $contextId = CONTEXT_ID_NONE) {
112  $filterGroup = $filter->getFilterGroup();
113  assert($filterGroup->getSymbolic() != FILTER_GROUP_TEMPORARY_ONLY);
114 
115  $this->update(
116  sprintf('INSERT INTO filters
117  (filter_group_id, context_id, display_name, class_name, is_template, parent_filter_id, seq)
118  VALUES (?, ?, ?, ?, ?, ?, ?)'),
119  array(
120  (int) $filterGroup->getId(),
121  (int) $contextId,
122  $filter->getDisplayName(),
123  $filter->getClassName(),
124  $filter->getIsTemplate()?1:0,
125  (int) $filter->getParentFilterId(),
126  (int) $filter->getSequence()
127  )
128  );
129  $filter->setId((int)$this->getInsertId());
131  'filter_settings', $filter,
132  array('filter_id' => $filter->getId())
133  );
134 
135  // Recursively insert sub-filters.
136  $this->_insertSubFilters($filter);
137 
138  return $filter->getId();
139  }
140 
146  function getObject($filter) {
147  return $this->getObjectById($filter->getId());
148  }
149 
156  function getObjectById($filterId, $allowSubfilter = false) {
157  $result = $this->retrieve(
158  'SELECT * FROM filters
159  WHERE '.($allowSubfilter ? '' : 'parent_filter_id = 0 AND '). '
160  filter_id = ?',
161  (int) $filterId
162  );
163 
164  $filter = null;
165  if ($result->RecordCount() != 0) {
166  $filter = $this->_fromRow($result->GetRowAssoc(false));
167  }
168 
169  $result->Close();
170  return $filter;
171  }
172 
183  function getObjectsByClass($className, $contextId = CONTEXT_ID_NONE, $getTemplates = false, $allowSubfilters = false) {
184  $result = $this->retrieve(
185  'SELECT * FROM filters
186  WHERE context_id = ? AND
187  class_name = ? AND
188  ' . ($allowSubfilters ? '' : ' parent_filter_id = 0 AND ') . '
189  ' . ($getTemplates ? ' is_template = 1' : ' is_template = 0'),
190  array((int) $contextId, $className)
191  );
192 
193  $daoResultFactory = new DAOResultFactory($result, $this, '_fromRow', array('filter_id'));
194  return $daoResultFactory;
195  }
196 
209  function getObjectsByGroupAndClass($groupSymbolic, $className, $contextId = CONTEXT_ID_NONE, $getTemplates = false, $allowSubfilters = false) {
210  $result = $this->retrieve(
211  'SELECT f.* FROM filters f'.
212  ' INNER JOIN filter_groups fg ON f.filter_group_id = fg.filter_group_id'.
213  ' WHERE fg.symbolic = ? AND f.context_id = ? AND f.class_name = ?'.
214  ' '.($allowSubfilters ? '' : 'AND f.parent_filter_id = 0').
215  ' AND '.($getTemplates ? 'f.is_template = 1' : 'f.is_template = 0'),
216  array($groupSymbolic, (int) $contextId, $className)
217  );
218 
219  return new DAOResultFactory($result, $this, '_fromRow', array('filter_id'));
220  }
221 
234  function getObjectsByTypeDescription($inputTypeDescription, $outputTypeDescription, $data = null, $dataIsInput = true) {
235  static $filterCache = array();
236  static $objectFilterCache = array();
237 
238  // We do not yet support array data types. Implement when required.
239  assert(!is_array($data));
240 
241  // Build the adapter cache.
242  $filterCacheKey = md5($inputTypeDescription.'=>'.$outputTypeDescription);
243  if (!isset($filterCache[$filterCacheKey])) {
244  // Get all adapter filters.
245  $result = $this->retrieve(
246  'SELECT f.*'.
247  ' FROM filters f'.
248  ' INNER JOIN filter_groups fg ON f.filter_group_id = fg.filter_group_id'.
249  ' WHERE fg.input_type like ?'.
250  ' AND fg.output_type like ?'.
251  ' AND f.parent_filter_id = 0 AND f.is_template = 0',
252  array($inputTypeDescription, $outputTypeDescription)
253  );
254 
255  // Instantiate all filters.
256  $filterFactory = new DAOResultFactory($result, $this, '_fromRow', array('filter_id'));
257  $filterCache[$filterCacheKey] = $filterFactory->toAssociativeArray();
258  }
259 
260  // Return all filter candidates if no data is given to check against.
261  if (is_null($data)) return $filterCache[$filterCacheKey];
262 
263  // Build the object-specific adapter cache.
264  $objectFilterCacheKey = md5($filterCacheKey.(is_object($data)?get_class($data):"'$data'").($dataIsInput?'in':'out'));
265  if (!isset($objectFilterCache[$objectFilterCacheKey])) {
266  $objectFilterCache[$objectFilterCacheKey] = array();
267  foreach($filterCache[$filterCacheKey] as $filterCandidateId => $filterCandidate) { /* @var $filterCandidate PersistableFilter */
268  // Check whether the given object can be transformed
269  // with this filter.
270  if ($dataIsInput) {
271  $filterDataType = $filterCandidate->getInputType();
272  } else {
273  $filterDataType = $filterCandidate->getOutputType();
274  }
275  if ($filterDataType->checkType($data)) $objectFilterCache[$objectFilterCacheKey][$filterCandidateId] = $filterCandidate;
276  unset($filterCandidate);
277  }
278  }
279 
280  return $objectFilterCache[$objectFilterCacheKey];
281  }
282 
299  function getObjectsByGroup($groupSymbolic, $contextId = CONTEXT_ID_NONE, $getTemplates = false, $checkRuntimeEnvironment = true) {
300  // 1) Get all available transformations in the group.
301  $result = $this->retrieve(
302  'SELECT f.* FROM filters f'.
303  ' INNER JOIN filter_groups fg ON f.filter_group_id = fg.filter_group_id'.
304  ' WHERE fg.symbolic = ? AND '.($getTemplates ? 'f.is_template = 1' : 'f.is_template = 0').
305  ' '.(is_null($contextId) ? '' : 'AND f.context_id in (0, '.(int)$contextId.')').
306  ' AND f.parent_filter_id = 0',
307  $groupSymbolic
308  );
309 
310 
311  // 2) Instantiate and return all transformations in the
312  // result set that comply with the current runtime
313  // environment.
314  $matchingFilters = array();
315  foreach($result->GetRows() as $filterRow) {
316  $filterInstance = $this->_fromRow($filterRow);
317  if (!$checkRuntimeEnvironment || $filterInstance->isCompatibleWithRuntimeEnvironment()) {
318  $matchingFilters[$filterInstance->getId()] = $filterInstance;
319  }
320  unset($filterInstance);
321  }
322 
323  return $matchingFilters;
324  }
325 
330  function updateObject($filter) {
331  $filterGroup = $filter->getFilterGroup();
332  assert($filterGroup->getSymbolic() != FILTER_GROUP_TEMPORARY_ONLY);
333 
334  $this->update(
335  'UPDATE filters
336  SET filter_group_id = ?,
337  display_name = ?,
338  class_name = ?,
339  is_template = ?,
340  parent_filter_id = ?,
341  seq = ?
342  WHERE filter_id = ?',
343  array(
344  (int) $filterGroup->getId(),
345  $filter->getDisplayName(),
346  $filter->getClassName(),
347  $filter->getIsTemplate()?1:0,
348  (int) $filter->getParentFilterId(),
349  (int) $filter->getSequence(),
350  (int) $filter->getId()
351  )
352  );
354  'filter_settings', $filter,
355  array('filter_id' => $filter->getId())
356  );
357 
358  // Do we update a composite filter?
359  if (is_a($filter, 'CompositeFilter')) {
360  // Delete all sub-filters
361  $this->_deleteSubFiltersByParentFilterId($filter->getId());
362 
363  // Re-insert sub-filters
364  $this->_insertSubFilters($filter);
365  }
366  }
367 
373  function deleteObject($filter) {
374  return $this->deleteObjectById($filter->getId());
375  }
376 
382  function deleteObjectById($filterId) {
383  $filterId = (int)$filterId;
384  $this->update('DELETE FROM filters WHERE filter_id = ?', (int) $filterId);
385  $this->update('DELETE FROM filter_settings WHERE filter_id = ?', (int) $filterId);
386  $this->_deleteSubFiltersByParentFilterId($filterId);
387  return true;
388  }
389 
390 
391  //
392  // Overridden methods from DAO
393  //
397  function updateDataObjectSettings($tableName, $dataObject, $idArray) {
398  // Make sure that the update function finds the filter settings
399  $this->additionalFieldNames = $dataObject->getSettingNames();
400  $this->localeFieldNames = $dataObject->getLocalizedSettingNames();
401 
402  // Add runtime settings
403  foreach($dataObject->supportedRuntimeEnvironmentSettings() as $runtimeSetting => $defaultValue) {
404  if ($dataObject->hasData($runtimeSetting)) $this->additionalFieldNames[] = $runtimeSetting;
405  }
406 
407  // Update the filter settings
408  parent::updateDataObjectSettings($tableName, $dataObject, $idArray);
409 
410  // Reset the internal fields
411  unset($this->additionalFieldNames, $this->localeFieldNames);
412  }
413 
414 
415  //
416  // Implement template methods from DAO
417  //
421  function getAdditionalFieldNames() {
422  assert(is_array($this->additionalFieldNames));
424  }
425 
429  function getLocaleFieldNames() {
430  assert(is_array($this->localeFieldNames));
432  }
433 
434 
435  //
436  // Protected helper methods
437  //
442  function getInsertId() {
443  return parent::_getInsertId('filters', 'filter_id');
444  }
445 
446 
447  //
448  // Private helper methods
449  //
456  function _newDataObject($filterClassName, $filterGroupId) {
457  // Instantiate the filter group.
458  $filterGroupDao = DAORegistry::getDAO('FilterGroupDAO'); /* @var $filterGroupDao FilterGroupDAO */
459  $filterGroup = $filterGroupDao->getObjectById($filterGroupId);
460  assert(is_a($filterGroup, 'FilterGroup'));
461 
462  // Instantiate the filter
463  $filter = instantiate($filterClassName, 'PersistableFilter', null, 'execute', $filterGroup); /* @var $filter PersistableFilter */
464  if (!is_object($filter)) fatalError('Error while instantiating class "'.$filterClassName.'" as filter!');
465 
466  return $filter;
467  }
468 
476  function _fromRow($row) {
477  static $lockedFilters = array();
478  $filterId = $row['filter_id'];
479 
480  // Check the filter lock (to detect loops).
481  // NB: This is very important otherwise the request
482  // could eat up lots of memory if the PHP memory max was
483  // set too high.
484  if (isset($lockedFilters[$filterId])) fatalError('Detected a loop in the definition of the filter with id '.$filterId.'!');
485 
486  // Lock the filter id.
487  $lockedFilters[$filterId] = true;
488 
489  // Instantiate the filter.
490  $filter = $this->_newDataObject($row['class_name'], (integer)$row['filter_group_id']);
491 
492  // Configure the filter instance
493  $filter->setId((int)$row['filter_id']);
494  $filter->setDisplayName($row['display_name']);
495  $filter->setIsTemplate((boolean)$row['is_template']);
496  $filter->setParentFilterId((int)$row['parent_filter_id']);
497  $filter->setSequence((int)$row['seq']);
498  $this->getDataObjectSettings('filter_settings', 'filter_id', $row['filter_id'], $filter);
499 
500  // Recursively retrieve sub-filters of this filter.
501  $this->_populateSubFilters($filter);
502 
503  // Release the lock on the filter id.
504  unset($lockedFilters[$filterId]);
505 
506  return $filter;
507  }
508 
514  function _populateSubFilters($parentFilter) {
515  if (!is_a($parentFilter, 'CompositeFilter')) {
516  // Nothing to do. Only composite filters
517  // can have sub-filters.
518  return;
519  }
520 
521  // Retrieve the sub-filters from the database.
522  $parentFilterId = $parentFilter->getId();
523  $result = $this->retrieve(
524  'SELECT * FROM filters WHERE parent_filter_id = ? ORDER BY seq',
525  (int) $parentFilterId
526  );
527  $daoResultFactory = new DAOResultFactory($result, $this, '_fromRow', array('filter_id'));
528 
529  // Add sub-filters.
530  while (!$daoResultFactory->eof()) {
531  // Retrieve the sub filter.
532  // NB: This recursively loads sub-filters
533  // of this filter via _fromRow().
534  $subFilter = $daoResultFactory->next();
535 
536  // Add the sub-filter to the filter list
537  // of its parent filter.
538  $parentFilter->addFilter($subFilter);
539  }
540  }
541 
547  function _insertSubFilters($parentFilter) {
548  if (!is_a($parentFilter, 'CompositeFilter')) {
549  // Nothing to do. Only composite filters
550  // can have sub-filters.
551  return;
552  }
553 
554  // Recursively insert sub-filters
555  foreach($parentFilter->getFilters() as $subFilter) {
556  $subFilter->setParentFilterId($parentFilter->getId());
557  $subfilterId = $this->insertObject($subFilter);
558  assert(is_numeric($subfilterId));
559  }
560  }
561 
567  function _deleteSubFiltersByParentFilterId($parentFilterId) {
568  $parentFilterId = (int)$parentFilterId;
569 
570  // Identify sub-filters.
571  $result = $this->retrieve(
572  'SELECT * FROM filters WHERE parent_filter_id = ?',
573  (int) $parentFilterId
574  );
575 
576  $allSubFilterRows = $result->GetArray();
577  foreach($allSubFilterRows as $subFilterRow) {
578  // Delete sub-filters
579  // NB: We need to do this before we delete
580  // sub-sub-filters to avoid loops.
581  $subFilterId = $subFilterRow['filter_id'];
582  $this->deleteObjectById($subFilterId);
583 
584  // Recursively delete sub-sub-filters.
585  $this->_deleteSubFiltersByParentFilterId($subFilterId);
586  }
587  }
588 }
589 
590 
FilterDAO\updateDataObjectSettings
updateDataObjectSettings($tableName, $dataObject, $idArray)
Definition: FilterDAO.inc.php:403
FilterDAO\deleteObjectById
deleteObjectById($filterId)
Definition: FilterDAO.inc.php:388
DAOResultFactory
Wrapper around ADORecordSet providing "factory" features for generating objects from DAOs.
Definition: DAOResultFactory.inc.php:21
instantiate
& instantiate($fullyQualifiedClassName, $expectedTypes=null, $expectedPackages=null, $expectedMethods=null, $constructorArg=null)
Definition: functions.inc.php:165
FilterDAO\getLocaleFieldNames
getLocaleFieldNames()
Definition: FilterDAO.inc.php:435
FilterDAO\configureObject
configureObject($filterClassName, $filterGroupSymbolic, $settings=array(), $asTemplate=false, $contextId=0, $subFilters=array(), $persist=true)
Definition: FilterDAO.inc.php:72
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
FilterDAO\_fromRow
_fromRow($row)
Definition: FilterDAO.inc.php:482
FilterDAO\updateObject
updateObject($filter)
Definition: FilterDAO.inc.php:336
FilterDAO\_deleteSubFiltersByParentFilterId
_deleteSubFiltersByParentFilterId($parentFilterId)
Definition: FilterDAO.inc.php:573
DAO\retrieve
& retrieve($sql, $params=false, $callHooks=true)
Definition: DAO.inc.php:85
FilterDAO\insertObject
insertObject($filter, $contextId=CONTEXT_ID_NONE)
Definition: FilterDAO.inc.php:117
FilterDAO\_insertSubFilters
_insertSubFilters($parentFilter)
Definition: FilterDAO.inc.php:553
FilterDAO\getObjectById
getObjectById($filterId, $allowSubfilter=false)
Definition: FilterDAO.inc.php:162
FilterDAO\_newDataObject
_newDataObject($filterClassName, $filterGroupId)
Definition: FilterDAO.inc.php:462
FilterDAO\getObjectsByGroupAndClass
getObjectsByGroupAndClass($groupSymbolic, $className, $contextId=CONTEXT_ID_NONE, $getTemplates=false, $allowSubfilters=false)
Definition: FilterDAO.inc.php:215
FilterDAO\getAdditionalFieldNames
getAdditionalFieldNames()
Definition: FilterDAO.inc.php:427
FilterDAO\getObjectsByTypeDescription
getObjectsByTypeDescription($inputTypeDescription, $outputTypeDescription, $data=null, $dataIsInput=true)
Definition: FilterDAO.inc.php:240
DAO\update
update($sql, $params=false, $callHooks=true, $dieOnError=true)
Definition: DAO.inc.php:214
FilterDAO\getObject
getObject($filter)
Definition: FilterDAO.inc.php:152
DAO\getDataObjectSettings
getDataObjectSettings($tableName, $idFieldName, $idFieldValue, $dataObject)
Definition: DAO.inc.php:582
FilterDAO
Operations for retrieving and modifying Filter objects.
Definition: FilterDAO.inc.php:44
fatalError
if(!function_exists('import')) fatalError($reason)
Definition: functions.inc.php:32
FilterDAO\getInsertId
getInsertId()
Definition: FilterDAO.inc.php:448
DAO
Operations for retrieving and modifying objects from a database.
Definition: DAO.inc.php:31
FilterDAO\getObjectsByGroup
getObjectsByGroup($groupSymbolic, $contextId=CONTEXT_ID_NONE, $getTemplates=false, $checkRuntimeEnvironment=true)
Definition: FilterDAO.inc.php:305
FilterDAO\_populateSubFilters
_populateSubFilters($parentFilter)
Definition: FilterDAO.inc.php:520
FilterDAO\getObjectsByClass
getObjectsByClass($className, $contextId=CONTEXT_ID_NONE, $getTemplates=false, $allowSubfilters=false)
Definition: FilterDAO.inc.php:189
FilterDAO\deleteObject
deleteObject($filter)
Definition: FilterDAO.inc.php:379
FilterDAO\$localeFieldNames
$localeFieldNames
Definition: FilterDAO.inc.php:55
FilterDAO\$additionalFieldNames
$additionalFieldNames
Definition: FilterDAO.inc.php:49