| Code Coverage
| Lines | Functions and Methods | Classes and Traits
Total | 48.33% covered (danger) | 48.33% | 246 / 509 | 46.67% covered (danger) | 46.67% | 21 / 45 | CRAP | 0.00% covered (danger) | 0.00% | 0 / 2
SeedDMS_Core_Attribute | 57.38% covered (warning) | 57.38% | 35 / 61 | 46.15% covered (danger) | 46.15% | 6 / 13 | 123.51 | 0.00% covered (danger) | 0.00% | 0 / 1
__construct | 100.00% covered (success) | 100.00% | 6 / 6 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setDMS | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getDMS | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getID | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getValue | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
__getParsedValue | 0.00% covered (danger) | 0.00% | 0 / 8 | 0.00% covered (danger) | 0.00% | 0 / 1 | 30 |
getValueAsArray | 100.00% covered (success) | 100.00% | 3 / 3 | 100.00% covered (success) | 100.00% | 1 / 1 | 2 |
getValueAsString | 66.67% covered (warning) | 66.67% | 2 / 3 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.15 |
setValue | 66.67% covered (warning) | 66.67% | 20 / 30 | 0.00% covered (danger) | 0.00% | 0 / 1 | 25.48 |
validate | 0.00% covered (danger) | 0.00% | 0 / 4 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 |
getValidationError | 0.00% covered (danger) | 0.00% | 0 / 1 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 |
setValidationError | 0.00% covered (danger) | 0.00% | 0 / 1 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 |
getAttributeDefinition | 0.00% covered (danger) | 0.00% | 0 / 1 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2 |
SeedDMS_Core_AttributeDefinition | 47.10% covered (danger) | 47.10% | 211 / 448 | 46.88% covered (danger) | 46.88% | 15 / 32 | 8624.19 | 0.00% covered (danger) | 0.00% | 0 / 1
__construct | 100.00% covered (success) | 100.00% | 12 / 12 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setDMS | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getDMS | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getID | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getName | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setName | 85.71% covered (warning) | 85.71% | 6 / 7 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.01 |
getObjType | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setObjType | 85.71% covered (warning) | 85.71% | 6 / 7 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.01 |
getType | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setType | 85.71% covered (warning) | 85.71% | 6 / 7 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.01 |
getMultipleValues | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setMultipleValues | 85.71% covered (warning) | 85.71% | 6 / 7 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.01 |
getMinValues | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setMinValues | 85.71% covered (warning) | 85.71% | 6 / 7 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.01 |
getMaxValues | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setMaxValues | 85.71% covered (warning) | 85.71% | 6 / 7 | 0.00% covered (danger) | 0.00% | 0 / 1 | 2.01 |
getValueSet | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
getValueSetSeparator | 85.71% covered (warning) | 85.71% | 6 / 7 | 0.00% covered (danger) | 0.00% | 0 / 1 | 4.05 |
getValueSetAsArray | 100.00% covered (success) | 100.00% | 3 / 3 | 100.00% covered (success) | 100.00% | 1 / 1 | 2 |
getValueSetValue | 100.00% covered (success) | 100.00% | 6 / 6 | 100.00% covered (success) | 100.00% | 1 / 1 | 3 |
setValueSet | 84.62% covered (warning) | 84.62% | 11 / 13 | 0.00% covered (danger) | 0.00% | 0 / 1 | 3.03 |
getRegex | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |
setRegex | 90.00% covered (success) | 90.00% | 9 / 10 | 0.00% covered (danger) | 0.00% | 0 / 1 | 4.02 |
isUsed | 0.00% covered (danger) | 0.00% | 0 / 12 | 0.00% covered (danger) | 0.00% | 0 / 1 | 56 |
parseValue | 36.36% covered (danger) | 36.36% | 16 / 44 | 0.00% covered (danger) | 0.00% | 0 / 1 | 146.73 |
createValue | 76.47% covered (warning) | 76.47% | 13 / 17 | 0.00% covered (danger) | 0.00% | 0 / 1 | 25.21 |
getStatistics | 0.00% covered (danger) | 0.00% | 0 / 87 | 0.00% covered (danger) | 0.00% | 0 / 1 | 1406 |
remove | 0.00% covered (danger) | 0.00% | 0 / 6 | 0.00% covered (danger) | 0.00% | 0 / 1 | 12 |
getObjects | 0.00% covered (danger) | 0.00% | 0 / 33 | 0.00% covered (danger) | 0.00% | 0 / 1 | 272 |
removeValue | 0.00% covered (danger) | 0.00% | 0 / 39 | 0.00% covered (danger) | 0.00% | 0 / 1 | 272 |
validate | 82.86% covered (warning) | 82.86% | 87 / 105 | 0.00% covered (danger) | 0.00% | 0 / 1 | 105.10 |
getValidationError | 100.00% covered (success) | 100.00% | 1 / 1 | 100.00% covered (success) | 100.00% | 1 / 1 | 1 |

1 | <?php
2 | declare(strict_types=1);
3 |
4 | /**
5 | * Implementation of the attribute object in the document management system
6 | *
7 | * @category DMS
8 | * @package SeedDMS_Core
9 | * @license GPL 2
10 | * @version @version@
11 | * @author Uwe Steinmann <uwe@steinmann.cx>
12 | * @copyright Copyright (C) 2012-2024 Uwe Steinmann
13 | * @version Release: @package_version@
14 | */
15 |
16 | /**
17 | * Class to represent an attribute in the document management system
18 | *
19 | * Attributes are key/value pairs which can be attachted to documents,
20 | * folders and document content. The number of attributes is unlimited.
21 | * Each attribute has a value and is related to an attribute definition,
22 | * which holds the name and other information about the attribute.
23 | *
24 | * @see SeedDMS_Core_AttributeDefinition
25 | *
26 | * @category DMS
27 | * @package SeedDMS_Core
28 | * @author Uwe Steinmann <uwe@steinmann.cx>
29 | * @copyright Copyright (C) 2012-2024 Uwe Steinmann
30 | * @version Release: @package_version@
31 | */
32 | class SeedDMS_Core_Attribute { /* {{{ */
33 | /**
34 | * @var integer id of attribute
35 | *
36 | * @access protected
37 | */
38 | protected $_id;
39 |
40 | /**
41 | * @var SeedDMS_Core_Folder|SeedDMS_Core_Document|SeedDMS_Core_DocumentContent SeedDMS_Core_Object folder, document or document content
42 | * this attribute belongs to
43 | *
44 | * @access protected
45 | */
46 | protected $_obj;
47 |
48 | /**
49 | * @var SeedDMS_Core_AttributeDefinition definition of this attribute
50 | *
51 | * @access protected
52 | */
53 | protected $_attrdef;
54 |
55 | /**
56 | * @var mixed value of this attribute
57 | *
58 | * @access protected
59 | */
60 | protected $_value;
61 |
62 | /**
63 | * @var integer validation error
64 | *
65 | * @access protected
66 | */
67 | protected $_validation_error;
68 |
69 | /**
70 | * @var SeedDMS_Core_DMS reference to the dms instance this attribute belongs to
71 | *
72 | * @access protected
73 | */
74 | protected $_dms;
75 |
76 | /**
77 | * SeedDMS_Core_Attribute constructor.
78 | * @param $id
79 | * @param $obj
80 | * @param $attrdef
81 | * @param $value
82 | */
83 | public function __construct($id, $obj, $attrdef, $value) { /* {{{ */
84 | $this->_id = $id;
85 | $this->_obj = $obj;
86 | $this->_attrdef = $attrdef;
87 | $this->_value = $value;
88 | $this->_validation_error = 0;
89 | $this->_dms = null;
90 | } /* }}} */
91 |
92 | /**
93 | * Set reference to dms
94 | *
95 | * @param SeedDMS_Core_DMS $dms
96 | */
97 | public function setDMS($dms) { /* {{{ */
98 | $this->_dms = $dms;
99 | } /* }}} */
100 |
101 | /**
102 | * Get dms of attribute
103 | *
104 | * @return object $dms
105 | */
106 | public function getDMS() { return $this->_dms; }
107 |
108 | /**
109 | * Get internal id of attribute
110 | *
111 | * @return integer id
112 | */
113 | public function getID() { return $this->_id; }
114 |
115 | /**
116 | * Return attribute value as stored in database
117 | *
118 | * This function will return the value of multi value attributes
119 | * including the separator char.
120 | *
121 | * @return string the attribute value as it is stored in the database.
122 | */
123 | public function getValue() { return $this->_value; }
124 |
125 | /**
126 | * Return attribute value parsed into a php type or object
127 | *
128 | * This function will return the value of multi value attributes
129 | * including the separator char.
130 | *
131 | * DEPRECATED
132 | *
133 | * @return string the attribute value as it is stored in the database.
134 | */
135 | public function __getParsedValue() { /* {{{ */
136 | switch ($this->_attrdef->getType()) {
137 | case SeedDMS_Core_AttributeDefinition::type_float:
138 | return (float) $this->_value;
139 | break;
140 | case SeedDMS_Core_AttributeDefinition::type_boolean:
141 | return (bool) $this->_value;
142 | break;
143 | case SeedDMS_Core_AttributeDefinition::type_int:
144 | return (int) $this->_value;
145 | break;
146 | default:
147 | return $this->_value;
148 | }
149 | } /* }}} */
150 |
151 | /**
152 | * Return attribute values as an array
153 | *
154 | * This function returns the attribute value as an array. The array
155 | * has one element for non multi value attributes and n elements for
156 | * multi value attributes.
157 | *
158 | * @return array the attribute values
159 | */
160 | public function getValueAsArray() { /* {{{ */
161 | if (is_array($this->_value))
162 | return $this->_value;
163 | else
164 | return [$this->_value];
165 | } /* }}} */
166 |
167 | public function getValueAsString() { /* {{{ */
168 | if (is_array($this->_value))
169 | return implode(', ', $this->_value);
170 | else
171 | return (string) $this->_value;
172 | } /* }}} */
173 |
174 | /**
175 | * Set a value of an attribute
176 | *
177 | * The attribute is completely deleted if the value is an empty string
178 | * or empty array. An array of values is only allowed if the attribute may
179 | * have multiple values. If an array is passed and the attribute may
180 | * have only a single value, then the first element of the array will
181 | * be taken.
182 | *
183 | * @param string $values value as string or array to be set
184 | * @return boolean true if operation was successfull, otherwise false
185 | */
186 | public function setValue($values) { /* {{{*/
187 | $db = $this->_dms->getDB();
188 |
189 | /* if $values is an array but the attribute definition does not allow
190 | * multi values, then the first element of the array is taken.
191 | */
192 | if ($values && is_array($values) && !$this->_attrdef->getMultipleValues())
193 | $values = $values[0];
194 |
195 | /* Create a value to be stored in the database */
196 | $value = $this->_attrdef->createValue($values);
197 |
198 | switch (get_class($this->_obj)) {
199 | case $this->_dms->getClassname('document'):
200 | if (trim($value) === '')
201 | $queryStr = "DELETE FROM `tblDocumentAttributes` WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
202 | else
203 | $queryStr = "UPDATE `tblDocumentAttributes` SET `value` = ".$db->qstr($value)." WHERE `document` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
204 | break;
205 | case $this->_dms->getClassname('documentcontent'):
206 | if (trim($value) === '')
207 | $queryStr = "DELETE FROM `tblDocumentContentAttributes` WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
208 | else
209 | $queryStr = "UPDATE `tblDocumentContentAttributes` SET `value` = ".$db->qstr($value)." WHERE `content` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
210 | break;
211 | case $this->_dms->getClassname('folder'):
212 | if (trim($value) === '')
213 | $queryStr = "DELETE FROM `tblFolderAttributes` WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
214 | else
215 | $queryStr = "UPDATE `tblFolderAttributes` SET `value` = ".$db->qstr($value)." WHERE `folder` = " . $this->_obj->getID() . " AND `attrdef` = " . $this->_attrdef->getId();
216 | break;
217 | default:
218 | return false;
219 | }
220 | if (!$db->getResult($queryStr))
221 | return false;
222 |
223 | $oldvalue = $this->_value;
224 | $this->_value = $values;
225 |
226 | /* Check if 'onPostUpdateAttribute' callback is set */
227 | $kk = (trim($value) === '') ? 'Remove' : 'Update';
228 | if (isset($this->_dms->callbacks['onPost'.$kk.'Attribute'])) {
229 | foreach ($this->_dms->callbacks['onPost'.$kk.'Attribute'] as $callback) {
230 | if (!call_user_func($callback[0], $callback[1], $this->_obj, $this->_attrdef, $value, $oldvalue)) {
231 | }
232 | }
233 | }
234 |
235 | return true;
236 | } /* }}} */
237 |
238 | /**
239 | * Validate attribute value
240 | *
241 | * This function checks if the attribute values fits the attribute
242 | * definition.
243 | * If the validation fails the validation error will be set which
244 | * can be requested by SeedDMS_Core_Attribute::getValidationError()
245 | *
246 | * @return boolean true if validation succeeds, otherwise false
247 | */
248 | public function validate() { /* {{{ */
249 | /** @var SeedDMS_Core_AttributeDefinition $attrdef */
250 | $attrdef = $this->_attrdef;
251 | $result = $attrdef->validate($this->_value);
252 | $this->_validation_error = $attrdef->getValidationError();
253 | return $result;
254 | } /* }}} */
255 |
256 | /**
257 | * Get validation error from last validation
258 | *
259 | * @return integer error code
260 | */
261 | public function getValidationError() { return $this->_validation_error; }
262 |
263 | /**
264 | * Set validation error
265 | *
266 | * @param integer error code
267 | */
268 | public function setValidationError($error) { $this->_validation_error = $error; }
269 |
270 | /**
271 | * Get definition of attribute
272 | *
273 | * @return object attribute definition
274 | */
275 | public function getAttributeDefinition() { return $this->_attrdef; }
276 |
277 | } /* }}} */
278 |
279 | /**
280 | * Class to represent an attribute definition in the document management system
281 | *
282 | * Attribute definitions specify the name, type, object type, minimum and
283 | * maximum values and a value set. The object type determines the object
284 | * an attribute may be attached to. If the object type is set to object_all
285 | * the attribute can be used for documents, document content and folders.
286 | *
287 | * The type of an attribute specifies the skalar data type.
288 | *
289 | * Attributes for which multiple values are allowed must have the
290 | * multiple flag set to true and specify a value set. A value set
291 | * is a string consisting of n separated values. The separator is the
292 | * first char of the value set. A possible value could be '|REV-A|REV-B'
293 | * If multiple values are allowed, then minvalues and maxvalues may
294 | * restrict the allowed number of values.
295 | *
296 | * @see SeedDMS_Core_Attribute
297 | *
298 | * @category DMS
299 | * @package SeedDMS_Core
300 | * @author Markus Westphal, Malcolm Cowe, Uwe Steinmann <uwe@steinmann.cx>
301 | * @copyright Copyright (C) 2012-2024 Uwe Steinmann
302 | * @version Release: @package_version@
303 | */
304 | class SeedDMS_Core_AttributeDefinition { /* {{{ */
305 | /**
306 | * @var integer id of attribute definition
307 | *
308 | * @access protected
309 | */
310 | protected $_id;
311 |
312 | /**
313 | * @var string name of attribute definition
314 | *
315 | * @access protected
316 | */
317 | protected $_name;
318 |
319 | /**
320 | * @var string object type of attribute definition. This can be one of
321 | * type_int, type_float, type_string, type_boolean, type_url, or type_email.
322 | *
323 | * @access protected
324 | */
325 | protected $_type;
326 |
327 | /**
328 | * @var string type of attribute definition. This can be one of objtype_all,
329 | * objtype_folder, objtype_document, or objtype_documentcontent.
330 | *
331 | * @access protected
332 | */
333 | protected $_objtype;
334 |
335 | /**
336 | * @var boolean whether an attribute can have multiple values
337 | *
338 | * @access protected
339 | */
340 | protected $_multiple;
341 |
342 | /**
343 | * @var integer minimum values of an attribute
344 | *
345 | * @access protected
346 | */
347 | protected $_minvalues;
348 |
349 | /**
350 | * @var integer maximum values of an attribute
351 | *
352 | * @access protected
353 | */
354 | protected $_maxvalues;
355 |
356 | /**
357 | * @var string list of possible values of an attribute
358 | *
359 | * @access protected
360 | */
361 | protected $_valueset;
362 |
363 | /**
364 | * @var string regular expression the value must match
365 | *
366 | * @access protected
367 | */
368 | protected $_regex;
369 |
370 | /**
371 | * @var integer validation error
372 | *
373 | * @access protected
374 | */
375 | protected $_validation_error;
376 |
377 | /**
378 | * @var SeedDMS_Core_DMS reference to the dms instance this attribute definition belongs to
379 | *
380 | * @access protected
381 | */
382 | protected $_dms;
383 |
384 | /**
385 | * @var string just the separator of a value set (not used)
386 | *
387 | * @access protected
388 | */
389 | protected $_separator;
390 |
391 | /*
392 | * Possible skalar data types of an attribute
393 | */
394 | const type_int = 1;
395 | const type_float = 2;
396 | const type_string = 3;
397 | const type_boolean = 4;
398 | const type_url = 5;
399 | const type_email = 6;
400 | const type_date = 7;
401 |
402 | /*
403 | * Addtional data types of an attribute representing objects in seeddms
404 | */
405 | const type_folder = 101;
406 | const type_document = 102;
407 | //const type_documentcontent = 103;
408 | const type_user = 104;
409 | const type_group = 105;
410 |
411 | /*
412 | * The object type for which a attribute may be used
413 | */
414 | const objtype_all = 0;
415 | const objtype_folder = 1;
416 | const objtype_document = 2;
417 | const objtype_documentcontent = 3;
418 |
419 | /*
420 | * The validation error codes
421 | */
422 | const val_error_none = 0;
423 | const val_error_min_values = 1;
424 | const val_error_max_values = 2;
425 | const val_error_boolean = 8;
426 | const val_error_int = 6;
427 | const val_error_date = 9;
428 | const val_error_float = 7;
429 | const val_error_regex = 3;
430 | const val_error_email = 5;
431 | const val_error_url = 4;
432 | const val_error_document = 10;
433 | const val_error_folder = 11;
434 | const val_error_user = 12;
435 | const val_error_group = 13;
436 | const val_error_valueset = 14;
437 |
438 | /**
439 | * Constructor
440 | *
441 | * @param integer $id internal id of attribute definition
442 | * @param string $name name of attribute
443 | * @param integer $objtype type of object for which this attribute definition
444 | * may be used.
445 | * @param integer $type skalar type of attribute
446 | * @param boolean $multiple set to true if multiple values are allowed
447 | * @param integer $minvalues minimum number of values
448 | * @param integer $maxvalues maximum number of values
449 | * @param string $valueset separated list of allowed values, the first char
450 | * is taken as the separator
451 | * @param $regex
452 | */
453 | public function __construct($id, $name, int $objtype, int $type, $multiple, $minvalues, $maxvalues, $valueset, $regex) { /* {{{ */
454 | $this->_id = $id;
455 | $this->_name = $name;
456 | $this->_type = $type;
457 | $this->_objtype = $objtype;
458 | $this->_multiple = $multiple;
459 | $this->_minvalues = $minvalues;
460 | $this->_maxvalues = $maxvalues;
461 | $this->_valueset = $valueset;
462 | $this->_separator = substr($valueset, 0, 1);
463 | $this->_regex = $regex;
464 | $this->_dms = null;
465 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_none;
466 | } /* }}} */
467 |
468 | /**
469 | * Set reference to dms
470 | *
471 | * @param SeedDMS_Core_DMS $dms
472 | */
473 | public function setDMS($dms) { /* {{{ */
474 | $this->_dms = $dms;
475 | } /* }}} */
476 |
477 | /**
478 | * Get dms of attribute definition
479 | *
480 | * @return object $dms
481 | */
482 | public function getDMS() { return $this->_dms; }
483 |
484 | /**
485 | * Get internal id of attribute definition
486 | *
487 | * @return integer id
488 | */
489 | public function getID() { return $this->_id; }
490 |
491 | /**
492 | * Get name of attribute definition
493 | *
494 | * @return string name
495 | */
496 | public function getName() { return $this->_name; }
497 |
498 | /**
499 | * Set name of attribute definition
500 | *
501 | * @param string $name name of attribute definition
502 | * @return boolean true on success, otherwise false
503 | */
504 | public function setName($name) { /* {{{ */
505 | $db = $this->_dms->getDB();
506 |
507 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `name` =".$db->qstr($name)." WHERE `id` = " . $this->_id;
508 | $res = $db->getResult($queryStr);
509 | if (!$res)
510 | return false;
511 |
512 | $this->_name = $name;
513 | return true;
514 | } /* }}} */
515 |
516 | /**
517 | * Get object type of attribute definition
518 | *
519 | * This can be one of objtype_all,
520 | * objtype_folder, objtype_document, or objtype_documentcontent.
521 | *
522 | * @return integer type
523 | */
524 | public function getObjType() { return $this->_objtype; }
525 |
526 | /**
527 | * Set object type of attribute definition
528 | *
529 | * This can be one of objtype_all,
530 | * objtype_folder, objtype_document, or objtype_documentcontent.
531 | *
532 | * @param integer $objtype type
533 | * @return bool
534 | */
535 | public function setObjType($objtype) { /* {{{ */
536 | $db = $this->_dms->getDB();
537 |
538 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `objtype` =".intval($objtype)." WHERE `id` = " . $this->_id;
539 | $res = $db->getResult($queryStr);
540 | if (!$res)
541 | return false;
542 |
543 | $this->_objtype = $objtype;
544 | return true;
545 | } /* }}} */
546 |
547 | /**
548 | * Get type of attribute definition
549 | *
550 | * This can be one of type_int, type_float, type_string, type_boolean,
551 | * type_url, type_email.
552 | *
553 | * @return integer type
554 | */
555 | public function getType() { return $this->_type; }
556 |
557 | /**
558 | * Set type of attribute definition
559 | *
560 | * This can be one of type_int, type_float, type_string, type_boolean,
561 | * type_url, type_email.
562 | *
563 | * @param integer $type type
564 | * @return bool
565 | */
566 | public function setType($type) { /* {{{ */
567 | $db = $this->_dms->getDB();
568 |
569 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `type` =".intval($type)." WHERE `id` = " . $this->_id;
570 | $res = $db->getResult($queryStr);
571 | if (!$res)
572 | return false;
573 |
574 | $this->_type = $type;
575 | return true;
576 | } /* }}} */
577 |
578 | /**
579 | * Check if attribute definition allows multi values for attribute
580 | *
581 | * @return boolean true if attribute may have multiple values
582 | */
583 | public function getMultipleValues() { return $this->_multiple; }
584 |
585 | /**
586 | * Set if attribute definition allows multi values for attribute
587 | *
588 | * @param boolean $mv true if attribute may have multiple values, otherwise
589 | * false
590 | * @return bool
591 | */
592 | public function setMultipleValues($mv) { /* {{{ */
593 | $db = $this->_dms->getDB();
594 |
595 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `multiple` =".intval($mv)." WHERE `id` = " . $this->_id;
596 | $res = $db->getResult($queryStr);
597 | if (!$res)
598 | return false;
599 |
600 | $this->_multiple = $mv;
601 | return true;
602 | } /* }}} */
603 |
604 | /**
605 | * Return minimum number of values for attributes
606 | *
607 | * Attributes with multiple values may be limited to a range
608 | * of values. This functions returns the minimum number of values.
609 | *
610 | * @return integer minimum number of values
611 | */
612 | public function getMinValues() { return $this->_minvalues; }
613 |
614 | public function setMinValues($minvalues) { /* {{{ */
615 | $db = $this->_dms->getDB();
616 |
617 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `minvalues` =".intval($minvalues)." WHERE `id` = " . $this->_id;
618 | $res = $db->getResult($queryStr);
619 | if (!$res)
620 | return false;
621 |
622 | $this->_minvalues = $minvalues;
623 | return true;
624 | } /* }}} */
625 |
626 | /**
627 | * Return maximum number of values for attributes
628 | *
629 | * Attributes with multiple values may be limited to a range
630 | * of values. This functions returns the maximum number of values.
631 | *
632 | * @return integer maximum number of values
633 | */
634 | public function getMaxValues() { return $this->_maxvalues; }
635 |
636 | public function setMaxValues($maxvalues) { /* {{{ */
637 | $db = $this->_dms->getDB();
638 |
639 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `maxvalues` =".intval($maxvalues)." WHERE `id` = " . $this->_id;
640 | $res = $db->getResult($queryStr);
641 | if (!$res)
642 | return false;
643 |
644 | $this->_maxvalues = $maxvalues;
645 | return true;
646 | } /* }}} */
647 |
648 | /**
649 | * Get the value set as saved in the database
650 | *
651 | * This is a string containing the list of valueѕ separated by a
652 | * delimiter which also precedes the whole string, e.g. '|Yes|No'
653 | *
654 | * Use {@link SeedDMS_Core_AttributeDefinition::getValueSetAsArray()}
655 | * for a list of values returned as an array.
656 | *
657 | * @return string value set
658 | */
659 | public function getValueSet() { /* {{{ */
660 | return $this->_valueset;
661 | } /* }}} */
662 |
663 | /**
664 | * Get the separator used for the value set
665 | *
666 | * This is the first char of the value set string.
667 | *
668 | * @return string separator or an empty string if a value set is not set
669 | */
670 | public function getValueSetSeparator() { /* {{{ */
671 | if (strlen($this->_valueset) > 1) {
672 | return $this->_valueset[0];
673 | } elseif ($this->_multiple) {
674 | if ($this->_type == SeedDMS_Core_AttributeDefinition::type_boolean)
675 | return '';
676 | else
677 | return ',';
678 | } else {
679 | return '';
680 | }
681 | } /* }}} */
682 |
683 | /**
684 | * Get the whole value set as an array
685 | *
686 | * Each element is trimmed.
687 | *
688 | * @return array values of value set or false if the value set has
689 | * less than 2 chars
690 | */
691 | public function getValueSetAsArray() { /* {{{ */
692 | if (strlen($this->_valueset) > 1)
693 | return array_map('trim', explode($this->_valueset[0], substr($this->_valueset, 1)));
694 | else
695 | return array();
696 | } /* }}} */
697 |
698 | /**
699 | * Get the n'th trimmed value of a value set
700 | *
701 | * @param $ind starting from 0 for the first element in the value set
702 | * @return string n'th value of value set or false if the index is
703 | * out of range or the value set has less than 2 chars
704 | * @internal param int $index
705 | */
706 | public function getValueSetValue($ind) { /* {{{ */
707 | if (strlen($this->_valueset) > 1) {
708 | $tmp = explode($this->_valueset[0], substr($this->_valueset, 1));
709 | if (isset($tmp[$ind]))
710 | return trim($tmp[$ind]);
711 | else
712 | return false;
713 | } else
714 | return false;
715 | } /* }}} */
716 |
717 | /**
718 | * Set the value set
719 | *
720 | * A value set is a list of values allowed for an attribute. The values
721 | * are separated by a char which must also be the first char of the
722 | * value set string. The method decomposes the value set, removes all
723 | * leading and trailing white space from the elements and recombines them
724 | * into a string.
725 | *
726 | * @param string $valueset
727 | * @return boolean true if value set could be set, otherwise false
728 | */
729 | public function setValueSet($valueset) { /* {{{ */
730 | /*
731 | $tmp = array();
732 | foreach ($valueset as $value) {
733 | $tmp[] = str_replace('"', '""', $value);
734 | }
735 | $valuesetstr = implode(",", $tmp);
736 | */
737 | $valueset = trim($valueset);
738 | if ($valueset) {
739 | $valuesetarr = array_map('trim', explode($valueset[0], substr($valueset, 1)));
740 | $valuesetstr = $valueset[0].implode($valueset[0], $valuesetarr);
741 | } else {
742 | $valuesetstr = '';
743 | }
744 |
745 | $db = $this->_dms->getDB();
746 |
747 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `valueset` =".$db->qstr($valuesetstr)." WHERE `id` = " . $this->_id;
748 | $res = $db->getResult($queryStr);
749 | if (!$res)
750 | return false;
751 |
752 | $this->_valueset = $valuesetstr;
753 | $this->_separator = substr($valuesetstr, 0, 1);
754 | return true;
755 | } /* }}} */
756 |
757 | /**
758 | * Get the regular expression as saved in the database
759 | *
760 | * @return string regular expression
761 | */
762 | public function getRegex() { /* {{{ */
763 | return $this->_regex;
764 | } /* }}} */
765 |
766 | /**
767 | * Set the regular expression
768 | *
769 | * A value of the attribute must match this regular expression.
770 | *
771 | * The methods checks if the regular expression is valid by running
772 | * preg_match() on an empty string and see if it fails. Trying to set
773 | * an invalid regular expression will not overwrite the current
774 | * regular expression.
775 | *
776 | * All leading and trailing spaces of $regex will be removed.
777 | *
778 | * @param string $regex
779 | * @return boolean true if regex could be set or is invalid, otherwise false
780 | */
781 | public function setRegex($regex) { /* {{{ */
782 | $db = $this->_dms->getDB();
783 |
784 | $regex = trim($regex);
785 | if ($regex && @preg_match($regex, '') === false)
786 | return false;
787 |
788 | $queryStr = "UPDATE `tblAttributeDefinitions` SET `regex` =".$db->qstr($regex)." WHERE `id` = " . $this->_id;
789 | $res = $db->getResult($queryStr);
790 | if (!$res)
791 | return false;
792 |
793 | $this->_regex = $regex;
794 | return true;
795 | } /* }}} */
796 |
797 | /**
798 | * Check if the attribute definition is used
799 | *
800 | * Checks all documents, folders and document content whether at least
801 | * one of them referenceѕ this attribute definition
802 | *
803 | * @return boolean true if attribute definition is used, otherwise false
804 | */
805 | public function isUsed() { /* {{{ */
806 | $db = $this->_dms->getDB();
807 |
808 | $queryStr = "SELECT * FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id;
809 | $resArr = $db->getResultArray($queryStr);
810 | if (is_array($resArr) && count($resArr) == 0) {
811 | $queryStr = "SELECT * FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id;
812 | $resArr = $db->getResultArray($queryStr);
813 | if (is_array($resArr) && count($resArr) == 0) {
814 | $queryStr = "SELECT * FROM `tblDocumentContentAttributes` WHERE `attrdef`=".$this->_id;
815 | $resArr = $db->getResultArray($queryStr);
816 | if (is_array($resArr) && count($resArr) == 0) {
817 | return false;
818 | }
819 | }
820 | }
821 | return true;
822 | } /* }}} */
823 |
824 | /**
825 | * Parse a given value stored in the database according to attribute definition
826 | *
827 | * The return value is an array, if the attribute allows multiple values.
828 | * Otherwise it is a single value.
829 | * If the type of attribute is any of document, folder, user,
830 | * or group then this method will fetch each object from the database and
831 | * return an array of SeedDMS_Core_Document, SeedDMS_Core_Folder, etc.
832 | *
833 | * @param $value string
834 | * @return array|bool
835 | */
836 | public function parseValue(string $value) { /* {{{ */
837 | if ($this->getMultipleValues()) {
838 | /* If the value doesn't start with the separator used in the value set,
839 | * then assume that the value was not saved with a leading separator.
840 | * This can happen, if the value was previously a single value from
841 | * the value set and later turned into a multi value attribute.
842 | */
843 | $sep = substr($value, 0, 1);
844 | $vsep = $this->getValueSetSeparator();
845 | if ($sep == $vsep)
846 | $values = explode($sep, substr($value, 1));
847 | else
848 | $values = array($value);
849 | } else {
850 | $values = array($value);
851 | }
852 |
853 | $tmp = [];
854 | switch ((string) $this->getType()) {
855 | case self::type_document:
856 | foreach ($values as $value) {
857 | if ($u = $this->_dms->getDocument((int) $value))
858 | $tmp[] = $u;
859 | }
860 | $values = $tmp;
861 | break;
862 | case self::type_folder:
863 | foreach ($values as $value) {
864 | if ($u = $this->_dms->getFolder((int) $value))
865 | $tmp[] = $u;
866 | }
867 | $values = $tmp;
868 | break;
869 | case self::type_user:
870 | foreach ($values as $value) {
871 | if ($u = $this->_dms->getUser((int) $value))
872 | $tmp[] = $u;
873 | }
874 | $values = $tmp;
875 | break;
876 | case self::type_group:
877 | foreach ($values as $value) {
878 | if ($u = $this->_dms->getGroup((int) $value))
879 | $tmp[] = $u;
880 | }
881 | $values = $tmp;
882 | break;
883 | case self::type_boolean:
884 | foreach ($values as $value) {
885 | $tmp[] = (bool) $value;
886 | }
887 | $values = $tmp;
888 | break;
889 | case self::type_int:
890 | foreach ($values as $value) {
891 | $tmp[] = (int) $value;
892 | }
893 | $values = $tmp;
894 | break;
895 | case self::type_float:
896 | foreach ($values as $value) {
897 | $tmp[] = (float) $value;
898 | }
899 | $values = $tmp;
900 | break;
901 | }
902 |
903 | if ($this->getMultipleValues())
904 | return $values;
905 | else
906 | return $values[0];
907 | } /* }}} */
908 |
909 | /**
910 | * Create the value stored in the database
911 | */
912 | public function createValue($values) { /* {{{ */
913 | if (is_array($values)) {
914 | switch ($this->getType()) {
915 | case SeedDMS_Core_AttributeDefinition::type_document:
916 | case SeedDMS_Core_AttributeDefinition::type_folder:
917 | case SeedDMS_Core_AttributeDefinition::type_user:
918 | case SeedDMS_Core_AttributeDefinition::type_group:
919 | $tmp = array_map(fn($value): int => is_object($value) ? (int) $value->getId() : (int) $value, $values);
920 | break;
921 | case SeedDMS_Core_AttributeDefinition::type_boolean:
922 | $tmp = array_map(fn($value): int => $value ? '1' : '0', $values);
923 | break;
924 | default:
925 | $tmp = $values;
926 | }
927 | } else {
928 | switch ($this->getType()) {
929 | case SeedDMS_Core_AttributeDefinition::type_document:
930 | case SeedDMS_Core_AttributeDefinition::type_folder:
931 | case SeedDMS_Core_AttributeDefinition::type_user:
932 | case SeedDMS_Core_AttributeDefinition::type_group:
933 | $tmp = is_object($values) ? [$values->getId()] : (is_numeric($values) ? [$values] : []);
934 | break;
935 | case SeedDMS_Core_AttributeDefinition::type_boolean:
936 | $tmp = [$values ? 1 : 0];
937 | break;
938 | default:
939 | $tmp = [$values];
940 | }
941 | }
942 |
943 | if ($this->getMultipleValues()) {
944 | $vsep = $this->getValueSetSeparator();
945 | } else {
946 | $vsep = '';
947 | }
948 | return $vsep.implode($vsep, $tmp);
949 | } /* }}} */
950 |
951 | /**
952 | * Return a list of documents, folders, document contents where this
953 | * attribute definition is used
954 | *
955 | * @param integer $limit return not more the n objects of each type
956 | * @return array|bool
957 | */
958 | public function getStatistics($limit = 0) { /* {{{ */
959 | $db = $this->_dms->getDB();
960 |
961 | $result = array('docs'=>array(), 'folders'=>array(), 'contents'=>array());
962 | if ($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
963 | $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_document) {
964 | $queryStr = "SELECT * FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id;
965 | if ($limit)
966 | $queryStr .= " limit ".(int) $limit;
967 | $resArr = $db->getResultArray($queryStr);
968 | if ($resArr) {
969 | foreach ($resArr as $rec) {
970 | if ($doc = $this->_dms->getDocument($rec['document'])) {
971 | $result['docs'][] = $doc;
972 | }
973 | }
974 | }
975 | $valueset = $this->getValueSetAsArray();
976 | $possiblevalues = array();
977 | foreach ($valueset as $value) {
978 | $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>0);
979 | }
980 | $queryStr = "SELECT count(*) c, `value` FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id." GROUP BY `value` ORDER BY c DESC";
981 | $resArr = $db->getResultArray($queryStr);
982 | if ($resArr) {
983 | foreach ($resArr as $row) {
984 | $value = $this->parseValue($row['value']);
985 | $tmpattr = new SeedDMS_Core_Attribute(0, null, $this, $value);
986 | foreach ($tmpattr->getValueAsArray() as $value) {
987 | if (is_object($value))
988 | $key = md5((string) $value->getId());
989 | else
990 | $key = md5((string) $value);
991 | if (isset($possiblevalues[$key])) {
992 | $possiblevalues[$key]['c'] += $row['c'];
993 | } else {
994 | $possiblevalues[$key] = array('value'=>$value, 'c'=>$row['c']);
995 | }
996 | }
997 | }
998 | $result['frequencies']['document'] = $possiblevalues;
999 | }
1000 | }
1001 |
1002 | if ($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
1003 | $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_folder) {
1004 | $queryStr = "SELECT * FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id;
1005 | if ($limit)
1006 | $queryStr .= " limit ".(int) $limit;
1007 | $resArr = $db->getResultArray($queryStr);
1008 | if ($resArr) {
1009 | foreach ($resArr as $rec) {
1010 | if ($folder = $this->_dms->getFolder($rec['folder'])) {
1011 | $result['folders'][] = $folder;
1012 | }
1013 | }
1014 | }
1015 | $valueset = $this->getValueSetAsArray();
1016 | $possiblevalues = array();
1017 | foreach ($valueset as $value) {
1018 | $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>0);
1019 | }
1020 | $queryStr = "SELECT count(*) c, `value` FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id." GROUP BY `value` ORDER BY c DESC";
1021 | $resArr = $db->getResultArray($queryStr);
1022 | if ($resArr) {
1023 | foreach ($resArr as $row) {
1024 | $value = $this->parseValue($row['value']);
1025 | $tmpattr = new SeedDMS_Core_Attribute(0, null, $this, $value);
1026 | foreach ($tmpattr->getValueAsArray() as $value) {
1027 | if (is_object($value))
1028 | $key = md5((string) $value->getId());
1029 | else
1030 | $key = md5((string) $value);
1031 | if (isset($possiblevalues[$key])) {
1032 | $possiblevalues[$key]['c'] += $row['c'];
1033 | } else {
1034 | $possiblevalues[$key] = array('value'=>$value, 'c'=>$row['c']);
1035 | }
1036 | }
1037 | }
1038 | $result['frequencies']['folder'] = $possiblevalues;
1039 | }
1040 | }
1041 |
1042 | if ($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
1043 | $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_documentcontent) {
1044 | $queryStr = "SELECT * FROM `tblDocumentContentAttributes` WHERE `attrdef`=".$this->_id;
1045 | if ($limit)
1046 | $queryStr .= " limit ".(int) $limit;
1047 | $resArr = $db->getResultArray($queryStr);
1048 | if ($resArr) {
1049 | foreach ($resArr as $rec) {
1050 | if ($content = $this->_dms->getDocumentContent($rec['content'])) {
1051 | $result['contents'][] = $content;
1052 | }
1053 | }
1054 | }
1055 | $valueset = $this->getValueSetAsArray();
1056 | $possiblevalues = array();
1057 | foreach ($valueset as $value) {
1058 | $possiblevalues[md5($value)] = array('value'=>$value, 'c'=>0);
1059 | }
1060 | $queryStr = "SELECT count(*) c, `value` FROM `tblDocumentContentAttributes` WHERE `attrdef`=".$this->_id." GROUP BY `value` ORDER BY c DESC";
1061 | $resArr = $db->getResultArray($queryStr);
1062 | if ($resArr) {
1063 | foreach ($resArr as $row) {
1064 | $value = $this->parseValue($row['value']);
1065 | $tmpattr = new SeedDMS_Core_Attribute(0, null, $this, $value);
1066 | foreach ($tmpattr->getValueAsArray() as $value) {
1067 | if (is_object($value))
1068 | $key = md5((string) $value->getId());
1069 | else
1070 | $key = md5((string) $value);
1071 | if (isset($possiblevalues[$key])) {
1072 | $possiblevalues[$key]['c'] += $row['c'];
1073 | } else {
1074 | $possiblevalues[$key] = array('value'=>$value, 'c'=>$row['c']);
1075 | }
1076 | }
1077 | }
1078 | $result['frequencies']['content'] = $possiblevalues;
1079 | }
1080 | }
1081 |
1082 | return $result;
1083 | } /* }}} */
1084 |
1085 | /**
1086 | * Remove the attribute definition
1087 | * Removal is only executed when the definition is not used anymore.
1088 | *
1089 | * @return boolean true on success or false in case of an error
1090 | */
1091 | public function remove() { /* {{{ */
1092 | $db = $this->_dms->getDB();
1093 |
1094 | if ($this->isUsed())
1095 | return false;
1096 |
1097 | // Delete user itself
1098 | $queryStr = "DELETE FROM `tblAttributeDefinitions` WHERE `id` = " . $this->_id;
1099 | if (!$db->getResult($queryStr)) return false;
1100 |
1101 | return true;
1102 | } /* }}} */
1103 |
1104 | /**
1105 | * Get all documents and folders by a given attribute value
1106 | *
1107 | * @param string $attrvalue value of attribute
1108 | * @param integer $limit limit number of documents/folders
1109 | * @return array array containing list of documents and folders
1110 | */
1111 | public function getObjects($attrvalue, $limit = 0, $op = O_EQ) { /* {{{ */
1112 | $db = $this->_dms->getDB();
1113 |
1114 | $result = array('docs'=>array(), 'folders'=>array(), 'contents'=>array());
1115 | if ($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
1116 | $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_document) {
1117 | $queryStr = "SELECT * FROM `tblDocumentAttributes` WHERE `attrdef`=".$this->_id;
1118 | if ($attrvalue != null) {
1119 | $queryStr .= " AND ";
1120 | if ($this->getMultipleValues()) {
1121 | $sep = $this->getValueSetSeparator();
1122 | $queryStr .= "(`value` like ".$db->qstr($sep.$attrvalue.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue.$sep.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue).")";
1123 | } else {
1124 | $queryStr .= "`value`".$op.$db->qstr((string) $attrvalue);
1125 | }
1126 | }
1127 | if ($limit)
1128 | $queryStr .= " limit ".(int) $limit;
1129 | $resArr = $db->getResultArray($queryStr);
1130 | if ($resArr) {
1131 | foreach ($resArr as $rec) {
1132 | if ($doc = $this->_dms->getDocument($rec['document'])) {
1133 | $result['docs'][] = $doc;
1134 | }
1135 | }
1136 | }
1137 | }
1138 |
1139 | if ($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all ||
1140 | $this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_folder) {
1141 | $queryStr = "SELECT * FROM `tblFolderAttributes` WHERE `attrdef`=".$this->_id." AND ";
1142 | if ($this->getMultipleValues()) {
1143 | $sep = $this->getValueSetSeparator();
1144 | $queryStr .= "(`value` like ".$db->qstr($sep.$attrvalue.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue.$sep.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue).")";
1145 | } else {
1146 | $queryStr .= "`value`=".$db->qstr($attrvalue);
1147 | }
1148 | if ($limit)
1149 | $queryStr .= " limit ".(int) $limit;
1150 | $resArr = $db->getResultArray($queryStr);
1151 | if ($resArr) {
1152 | foreach ($resArr as $rec) {
1153 | if ($folder = $this->_dms->getFolder($rec['folder'])) {
1154 | $result['folders'][] = $folder;
1155 | }
1156 | }
1157 | }
1158 | }
1159 |
1160 | return $result;
1161 | } /* }}} */
1162 |
1163 | /**
1164 | * Remove a given attribute value from all documents, versions and folders
1165 | *
1166 | * @param string $attrvalue value of attribute
1167 | * @return array array containing list of documents and folders
1168 | */
1169 | public function removeValue($attrvalue) { /* {{{ */
1170 | $db = $this->_dms->getDB();
1171 |
1172 | foreach (array('document', 'documentcontent', 'folder') as $type) {
1173 | if ($type == 'document') {
1174 | $tablename = "tblDocumentAttributes";
1175 | $objtype = SeedDMS_Core_AttributeDefinition::objtype_document;
1176 | } elseif ($type == 'documentcontent') {
1177 | $tablename = "tblDocumentContentAttributes";
1178 | $objtype = SeedDMS_Core_AttributeDefinition::objtype_documentcontent;
1179 | } elseif ($type == 'folder') {
1180 | $tablename = "tblFolderAttributes";
1181 | $objtype = SeedDMS_Core_AttributeDefinition::objtype_folder;
1182 | }
1183 | if ($this->_objtype == SeedDMS_Core_AttributeDefinition::objtype_all || $objtype) {
1184 | $queryStr = "SELECT * FROM `".$tablename."` WHERE `attrdef`=".$this->_id." AND ";
1185 | if ($this->getMultipleValues()) {
1186 | $sep = $this->getValueSetSeparator();
1187 | $queryStr .= "(`value` like ".$db->qstr($sep.$attrvalue.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue.$sep.'%')." OR `value` like ".$db->qstr('%'.$sep.$attrvalue).")";
1188 | } else {
1189 | $queryStr .= "`value`=".$db->qstr($attrvalue);
1190 | }
1191 |
1192 | $resArr = $db->getResultArray($queryStr);
1193 | if ($resArr) {
1194 | $db->startTransaction();
1195 | foreach ($resArr as $rec) {
1196 | if ($rec['value'] == $attrvalue) {
1197 | $queryStr = "DELETE FROM `".$tablename."` WHERE `id`=".$rec['id'];
1198 | } else {
1199 | if ($this->getMultipleValues()) {
1200 | $sep = substr($rec['value'], 0, 1);
1201 | $vsep = $this->getValueSetSeparator();
1202 | if ($sep == $vsep)
1203 | $values = explode($sep, substr($rec['value'], 1));
1204 | else
1205 | $values = array($rec['value']);
1206 | if (($key = array_search($attrvalue, $values)) !== false) {
1207 | unset($values[$key]);
1208 | }
1209 | if ($values) {
1210 | $queryStr = "UPDATE `".$tablename."` SET `value`=".$db->qstr($sep.implode($sep, $values))." WHERE `id`=".$rec['id'];
1211 | } else {
1212 | $queryStr = "DELETE FROM `".$tablename."` WHERE `id`=".$rec['id'];
1213 | }
1214 | } else {
1215 | }
1216 | }
1217 | if (!$db->getResult($queryStr)) {
1218 | $db->rollbackTransaction();
1219 | return false;
1220 | }
1221 | }
1222 | $db->commitTransaction();
1223 | }
1224 | }
1225 | }
1226 | return true;
1227 | } /* }}} */
1228 |
1229 | /**
1230 | * Validate value against attribute definition
1231 | *
1232 | * This function checks if the given value fits the attribute
1233 | * definition.
1234 | * If the validation fails the validation error will be set which
1235 | * can be requested by SeedDMS_Core_Attribute::getValidationError()
1236 | * Set $new to true if the value to be checked isn't saved to the database
1237 | * already. It will just be passed to the callback onAttributeValidate where
1238 | * it could be used to, e.g. check if a value is unique once it is saved to
1239 | * the database. $object is set to a folder, document or documentcontent
1240 | * if the attribute belongs to such an object. This will be null, if a
1241 | * new object is created.
1242 | *
1243 | * @param string|array $attrvalue attribute value
1244 | * @param object $object set if the current attribute is saved for this object
1245 | * (this will only be passed to the onAttributeValidate callback)
1246 | * @param boolean $new set to true if the value is new value and not taken from
1247 | * an existing attribute
1248 | * (this will only be passed to the onAttributeValidate callback)
1249 | * @return boolean true if validation succeeds, otherwise false
1250 | */
1251 | public function validate($attrvalue, $object = null, $new = false) { /* {{{ */
1252 | /* Check if 'onAttributeValidate' callback is set */
1253 | if (isset($this->_dms->callbacks['onAttributeValidate'])) {
1254 | foreach ($this->_dms->callbacks['onAttributeValidate'] as $callback) {
1255 | $ret = call_user_func($callback[0], $callback[1], $this, $attrvalue, $object, $new);
1256 | if (is_bool($ret))
1257 | return $ret;
1258 | }
1259 | }
1260 |
1261 | /* Turn $attrvalue into an array of values. Checks if $attrvalue starts
1262 | * with a separator char as set in the value set and use it to explode
1263 | * the $attrvalue. If the separator doesn't match or this attribute
1264 | * definition doesn't have a value set, then just create a one element
1265 | * array. if $attrvalue is empty, then create an empty array.
1266 | */
1267 | if ($this->getMultipleValues()) {
1268 | if (is_string($attrvalue) && $attrvalue) {
1269 | $sep = $attrvalue[0];
1270 | $vsep = $this->getValueSetSeparator();
1271 | if ($sep == $vsep)
1272 | $values = explode($attrvalue[0], substr($attrvalue, 1));
1273 | else
1274 | $values = array($attrvalue);
1275 | } elseif (is_array($attrvalue)) {
1276 | $values = $attrvalue;
1277 | } elseif (is_string($attrvalue) && !$attrvalue) {
1278 | $values = array();
1279 | } else
1280 | $values = array($attrvalue);
1281 | } elseif ($attrvalue !== null) {
1282 | $values = array($attrvalue);
1283 | } else {
1284 | $values = array();
1285 | }
1286 |
1287 | /* Check if attribute value has at least the minimum number of values */
1288 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_none;
1289 | if ($this->getMinValues() > count($values)) {
1290 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_min_values;
1291 | return false;
1292 | }
1293 | /* Check if attribute value has not more than maximum number of values */
1294 | if ($this->getMaxValues() && $this->getMaxValues() < count($values)) {
1295 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_max_values;
1296 | return false;
1297 | }
1298 |
1299 | $success = true;
1300 | switch ((string) $this->getType()) {
1301 | case self::type_boolean:
1302 | foreach ($values as $value) {
1303 | $success = $success && (preg_match('/^[01]$/', (string) $value) || $value === true || $value === false);
1304 | }
1305 | if (!$success)
1306 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_boolean;
1307 | break;
1308 | case self::type_int:
1309 | foreach ($values as $value) {
1310 | $success = $success && (preg_match('/^[0-9]*$/', (string) $value) ? true : false);
1311 | }
1312 | if (!$success)
1313 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_int;
1314 | break;
1315 | case self::type_date:
1316 | foreach ($values as $value) {
1317 | $d = explode('-', $value, 3);
1318 | $success = $success && (count($d) == 3) && checkdate((int) $d[1], (int) $d[2], (int) $d[0]);
1319 | }
1320 | if (!$success)
1321 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_date;
1322 | break;
1323 | case self::type_float:
1324 | foreach ($values as $value) {
1325 | $success = $success && is_numeric($value);
1326 | }
1327 | if (!$success)
1328 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_float;
1329 | break;
1330 | case self::type_string:
1331 | if (trim($this->getRegex()) != '') {
1332 | foreach ($values as $value) {
1333 | $success = $success && (preg_match($this->getRegex(), $value) ? true : false);
1334 | }
1335 | }
1336 | if (!$success)
1337 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_regex;
1338 | break;
1339 | case self::type_email:
1340 | foreach ($values as $value) {
1341 | //$success &= filter_var($value, FILTER_VALIDATE_EMAIL) ? true : false;
1342 | $success = $success && (preg_match('/^[a-z0-9._-]+@[a-z0-9-]{2,63}(\.[a-z0-9-]{2,63})*\.[a-z]{2,63}$/i', $value) ? true : false);
1343 | }
1344 | if (!$success)
1345 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_email;
1346 | break;
1347 | case self::type_url:
1348 | foreach ($values as $value) {
1349 | $success = $success && (preg_match('/^http(s)?:\/\/[a-z0-9_-]+(\.[a-z0-9-]{2,63})*(:[0-9]+)?(\/.*)?$/i', $value) ? true : false);
1350 | }
1351 | if (!$success)
1352 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_url;
1353 | break;
1354 | case self::type_document:
1355 | $success = true;
1356 | foreach ($values as $value) {
1357 | if (!$value->isType('document'))
1358 | $success = $success && false;
1359 | }
1360 | if (!$success)
1361 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_document;
1362 | break;
1363 | case self::type_folder:
1364 | $success = true;
1365 | foreach ($values as $value) {
1366 | if (!$value->isType('folder'))
1367 | $success = $success && false;
1368 | }
1369 | if (!$success)
1370 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_folder;
1371 | break;
1372 | case self::type_user:
1373 | $success = true;
1374 | foreach ($values as $value) {
1375 | if (!$value->isType('user'))
1376 | $success = $success && false;
1377 | }
1378 | if (!$success)
1379 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_user;
1380 | break;
1381 | case self::type_group:
1382 | $success = true;
1383 | foreach ($values as $value) {
1384 | if (!$value->isType('group'))
1385 | $success = $success && false;
1386 | }
1387 | if (!$success)
1388 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_group;
1389 | break;
1390 | }
1391 |
1392 | if (!$success)
1393 | return $success;
1394 |
1395 | /* Check if value is in value set */
1396 | if ($valueset = $this->getValueSetAsArray()) {
1397 | /* An empty value cannot be the value set */
1398 | if (!$values) {
1399 | $success = false;
1400 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_valueset;
1401 | } else {
1402 | foreach ($values as $value) {
1403 | if (!in_array($value, $valueset)) {
1404 | $success = false;
1405 | $this->_validation_error = SeedDMS_Core_AttributeDefinition::val_error_valueset;
1406 | }
1407 | }
1408 | }
1409 | }
1410 |
1411 | return $success;
1412 |
1413 | } /* }}} */
1414 |
1415 | /**
1416 | * Get validation error from last validation
1417 | *
1418 | * @return integer error code
1419 | */
1420 | public function getValidationError() { return $this->_validation_error; }
1421 |
1422 | } /* }}} */