Open Monograph Press  3.3.0
FilterHelper.inc.php
1 <?php
15 class FilterHelper {
24  function installFilterGroups($filterGroupsNode) {
25  // Install filter groups.
26  $filterGroupDao = DAORegistry::getDAO('FilterGroupDAO'); /* @var $filterGroupDao FilterGroupDAO */
27  import('lib.pkp.classes.filter.FilterGroup');
28 
29  foreach ($filterGroupsNode->getChildren() as $filterGroupNode) { /* @var $filterGroupNode XMLNode */
30  $filterGroupSymbolic = $filterGroupNode->getAttribute('symbolic');
31 
32  // Make sure that the filter group has not been
33  // installed before to guarantee idempotence.
34  $existingFilterGroup =& $filterGroupDao->getObjectBySymbolic($filterGroupSymbolic);
35  if (!is_null($existingFilterGroup)) continue;
36 
37  // Instantiate and configure the filter group.
38  $filterGroup = new FilterGroup();
39  $filterGroup->setSymbolic($filterGroupSymbolic);
40  $filterGroup->setDisplayName($filterGroupNode->getAttribute('displayName'));
41  $filterGroup->setDescription($filterGroupNode->getAttribute('description'));
42  $filterGroup->setInputType($filterGroupNode->getAttribute('inputType'));
43  $filterGroup->setOutputType($filterGroupNode->getAttribute('outputType'));
44 
45  // Install the filter group.
46  $installedGroupId = $filterGroupDao->insertObject($filterGroup);
47  assert(is_integer($installedGroupId));
48 
49  unset($filterGroup);
50  }
51  }
52 
63  function &configureFilter($filterNode, $persist = true) {
64  // Install filters.
65  $filterDao = DAORegistry::getDAO('FilterDAO'); /* @var $filterDao FilterDAO */
66 
67  $filterGroupSymbolic = $filterNode->getAttribute('inGroup');
68  $filterClassName = $filterNode->getAttribute('class');
69  $isTemplate = $filterNode->getAttribute('isTemplate');
70 
71  // We have to include the filter class before going on
72  // so that all required constants are defined before they
73  // might be used in settings.
74  if (PKPString::regexp_match('/^[a-zA-Z0-9.]+$/', $filterClassName)) {
75  import($filterClassName);
76  }
77 
78  // Go through the filter sub-nodes. This can be nested
79  // filters or filter settings.
80  $subNodes = $filterNode->getChildren();
81  $settings = array();
82  $subFilters = array();
83  foreach($subNodes as $subNode) { /* @var $subNode XMLNode */
84  switch($subNode->getName()) {
85  case 'setting':
86  // Get the filter setting.
87  list($name, $value) = $this->getFilterSetting($subNode);
88  $settings[$name] = $value;
89  unset($name, $value);
90  break;
91 
92  case 'filter':
93  // Recursively configure sub-filters.
94  $subFilter =& $this->configureFilter($subNode, false);
95  $subFilters[] =& $subFilter;
96  unset($subFilter);
97  break;
98  }
99  }
100 
101  // We ensure idempotence of plug-in installation by checking
102  // for existing identical filters.
103  $similarFilterFactory = $filterDao->getObjectsByGroupAndClass($filterGroupSymbolic, $filterClassName, 0, $isTemplate);
104  if ($similarFilterFactory->getCount() > 0) {
105  // 1) Find similar filters.
106  $similarFilters = $similarFilterFactory->toArray();
107 
108  // 2) Go through similar filters and eliminate them
109  // if they don't have the exact same settings.
110  foreach($similarFilters as $index => $similarFilter) { /* @var $similarFilter PersistableFilter */
111  if (!$this->compareFilters($similarFilter, $settings, $subFilters)) unset($similarFilters[$index]);
112  }
113 
114  // There can be a maximum of exactly one identical transformation
115  // in the database otherwise we've somehow installed a duplicate filter.
116  $identicalFilters = count($similarFilters);
117  assert($identicalFilters <= 1);
118 
119  // 3) If the filter has been installed before then return the existing filter.
120  if ($identicalFilters) {
121  $existingFilter = array_pop($similarFilters);
122  return $existingFilter;
123  }
124  }
125 
126  // Configure (and optionally install) the filter.
127  $installedFilter = $filterDao->configureObject($filterClassName, $filterGroupSymbolic, $settings, $isTemplate, 0, $subFilters, $persist);
128  assert(is_a($installedFilter, 'PersistableFilter'));
129 
130  return $installedFilter;
131  }
132 
141  function compareFilters(&$filterA, $filterBSettings, &$filterBSubfilters) {
142  // Compare settings.
143  foreach($filterBSettings as $name => $value) {
144  if (!($filterA->hasSetting($name) || in_array($name, $filterA->getInternalSettings()))
145  || $filterA->getData($name) != $value) {
146  return false;
147  }
148  }
149 
150  // Compare sub-filters.
151  if (is_a($filterA, 'CompositeFilter')) {
152  // Compare sub-filters of composite filters.
153  foreach($filterBSubfilters as $filterBSubfilter) { /* @var $filterBSubfilter PersistableFilter */
154  $seq = $filterBSubfilter->getSequence();
155  $filterASubfilter =& $filterA->getFilter($seq);
156  if (!$filterASubfilter || !$filterBSubfilter || get_class($filterASubfilter) != get_class($filterBSubfilter)) {
157  return false;
158  }
159 
160  // Extract sub-filter settings.
161  $filterBSubfilterSettings = array();
162  foreach($filterBSubfilter->getSettingNames() as $filterBSubfilterSettingName) {
163  if ($filterBSubfilter->hasData($filterBSubfilterSettingName)) {
164  $filterBSubfilterSettings[$filterBSubfilterSettingName] = $filterBSubfilter->getData($filterBSubfilterSettingName);
165  }
166  }
167 
168  // Extract sub-filter sub-filters.
169  if (is_a($filterBSubfilter, 'CompositeFilter')) {
170  $filterBSubfilterSubfilters =& $filterBSubfilter->getFilters();
171  } else {
172  $filterBSubfilterSubfilters = array();
173  }
174 
175  // Recurse.
176  if (!$this->compareFilters($filterASubfilter, $filterBSubfilterSettings, $filterBSubfilterSubfilters)) return false;
177  }
178  }
179 
180  return true;
181  }
182 
191  function getFilterSetting($settingNode) {
192  // Retrieve the setting name.
193  $nameNode =& $settingNode->getChildByName('name');
194  assert(is_a($nameNode, 'XMLNode'));
195  $name = $nameNode->getValue();
196 
197  // Retrieve the setting value.
198  $type = $settingNode->getAttribute('type');
199  $valueNode =& $settingNode->getChildByName('value');
200  assert(is_a($valueNode, 'XMLNode'));
201  switch($type) {
202  case 'string':
203  $value = (string)$valueNode->getValue();
204  break;
205 
206  case 'bool':
207  $value = (boolean)$valueNode->getValue();
208  break;
209 
210  case 'int':
211  $value = (integer)$valueNode->getValue();
212  break;
213 
214  case 'const':
215  $constName = $valueNode->getValue();
216  assert(defined($constName));
217  $value = constant($constName);
218  break;
219 
220  case 'object':
221  $value = array();
222  $arrayNode =& $valueNode->getChildByName('array');
223  $value = $this->readArraySetting($arrayNode);
224  break;
225 
226  default:
227  // Unknown type.
228  assert(false);
229  $value = null;
230  }
231 
232  // Add the setting to the list.
233  $setting = array($name, $value);
234  return $setting;
235  }
236 
242  function readArraySetting($arrayNode) {
243  $resultArray = array();
244  foreach($arrayNode->getChildren() as $elementNode) { /* @var $elementNode XMLNode */
245  $key = $elementNode->getAttribute('key');
246 
247  $subArrayNode = $elementNode->getChildByName('array');
248  if (is_a($subArrayNode, 'XMLNode')) {
249  // Recurse into sub-array.
250  $value = $this->readArraySetting($subArrayNode);
251  } else {
252  // Read the element value.
253  $value = $elementNode->getValue();
254  }
255 
256  // Add the element to the result set.
257  if (isset($key)) {
258  $resultArray[$key] = $value;
259  } else {
260  $resultArray[] = $value;
261  }
262  }
263 
264  return $resultArray;
265  }
266 }
267 
FilterHelper\compareFilters
compareFilters(&$filterA, $filterBSettings, &$filterBSubfilters)
Definition: FilterHelper.inc.php:141
FilterGroup
Class that represents filter groups.
Definition: FilterGroup.inc.php:45
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
FilterHelper\readArraySetting
readArraySetting($arrayNode)
Definition: FilterHelper.inc.php:242
FilterHelper\installFilterGroups
installFilterGroups($filterGroupsNode)
Definition: FilterHelper.inc.php:24
PKPString\regexp_match
static regexp_match($pattern, $subject)
Definition: PKPString.inc.php:245
FilterHelper
Class that provides filter-related helper methods.
Definition: FilterHelper.inc.php:15
FilterHelper\configureFilter
& configureFilter($filterNode, $persist=true)
Definition: FilterHelper.inc.php:63
FilterHelper\getFilterSetting
getFilterSetting($settingNode)
Definition: FilterHelper.inc.php:191