1: | <?php |
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | namespace Aurora\System; |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | |
15: | |
16: | |
17: | abstract class AbstractContainer |
18: | { |
19: | public const SESSION_CONTAINER_PREFIX = 'sess_object_container'; |
20: | |
21: | |
22: | |
23: | |
24: | public $__USE_TRIM_IN_STRINGS__; |
25: | |
26: | |
27: | |
28: | |
29: | protected $sParentClassName; |
30: | |
31: | |
32: | |
33: | |
34: | protected $sSessionUniqueProperty; |
35: | |
36: | |
37: | |
38: | |
39: | protected $aContainer; |
40: | |
41: | |
42: | |
43: | |
44: | protected $aObsolete; |
45: | |
46: | |
47: | |
48: | |
49: | protected $aTrimer; |
50: | |
51: | |
52: | |
53: | |
54: | protected $aLower; |
55: | |
56: | |
57: | |
58: | |
59: | protected $aUpper; |
60: | |
61: | |
62: | |
63: | |
64: | |
65: | public function __construct($sParentClassName, $sSessionUniqueProperty = '') |
66: | { |
67: | $this->__USE_TRIM_IN_STRINGS__ = false; |
68: | $this->sParentClassName = $sParentClassName; |
69: | $this->sSessionUniqueProperty = $sSessionUniqueProperty; |
70: | |
71: | $this->aContainer = array(); |
72: | $this->aObsolete = array(); |
73: | $this->aTrimer = array(); |
74: | $this->aLower = array(); |
75: | $this->aUpper = array(); |
76: | } |
77: | |
78: | |
79: | |
80: | |
81: | |
82: | public function SetDefaults($aValues) |
83: | { |
84: | $this->MassSetValues($aValues); |
85: | $this->FlushObsolete(); |
86: | } |
87: | |
88: | |
89: | |
90: | |
91: | |
92: | public function SetTrimer($aValues) |
93: | { |
94: | $this->aTrimer = $aValues; |
95: | } |
96: | |
97: | |
98: | |
99: | |
100: | |
101: | public function SetLower($aValues) |
102: | { |
103: | $this->aLower = $aValues; |
104: | } |
105: | |
106: | |
107: | |
108: | |
109: | |
110: | public function SetUpper($aValues) |
111: | { |
112: | $this->aUpper = $aValues; |
113: | } |
114: | |
115: | |
116: | |
117: | |
118: | |
119: | public function MassSetValues($aValues) |
120: | { |
121: | foreach ($aValues as $sKey => $mValue) { |
122: | $this->{$sKey} = $mValue; |
123: | } |
124: | } |
125: | |
126: | |
127: | |
128: | |
129: | public function InitByDbRow($oRow) |
130: | { |
131: | $aMap = $this->getMap(); |
132: | foreach ($aMap as $sKey => $aTypes) { |
133: | if (isset($aTypes[1]) && \property_exists($oRow, $aTypes[1])) { |
134: | if ('password' === $aTypes[0]) { |
135: | $this->{$sKey} = Utils::DecryptValue($oRow->{$aTypes[1]}); |
136: | } elseif ('datetime' === $aTypes[0]) { |
137: | $iDateTime = 0; |
138: | $aDateTime = Utils::DateParse($oRow->{$aTypes[1]}); |
139: | if (\is_array($aDateTime)) { |
140: | $iDateTime = \gmmktime( |
141: | $aDateTime['hour'], |
142: | $aDateTime['minute'], |
143: | $aDateTime['second'], |
144: | $aDateTime['month'], |
145: | $aDateTime['day'], |
146: | $aDateTime['year'] |
147: | ); |
148: | |
149: | if (false === $iDateTime || $iDateTime <= 0) { |
150: | $iDateTime = 0; |
151: | } |
152: | } |
153: | |
154: | $this->{$sKey} = $iDateTime; |
155: | } elseif ('serialize' === $aTypes[0]) { |
156: | $this->{$sKey} = ('' === $oRow->{$aTypes[1]} || !\is_string($oRow->{$aTypes[1]})) ? |
157: | '' : \unserialize($oRow->{$aTypes[1]}); |
158: | } else { |
159: | $this->{$sKey} = $oRow->{$aTypes[1]}; |
160: | } |
161: | |
162: | $this->FlushObsolete($sKey); |
163: | } |
164: | } |
165: | } |
166: | |
167: | |
168: | |
169: | |
170: | |
171: | public function GetObsoleteValue($sKey) |
172: | { |
173: | if (\key_exists($sKey, $this->aObsolete)) { |
174: | return $this->aObsolete[$sKey]; |
175: | } |
176: | |
177: | return null; |
178: | } |
179: | |
180: | |
181: | |
182: | |
183: | |
184: | public function FlushObsolete($nsKey = null) |
185: | { |
186: | if (null === $nsKey) { |
187: | $this->aObsolete = array(); |
188: | } else { |
189: | if (\key_exists($nsKey, $this->aObsolete)) { |
190: | unset($this->aObsolete[$nsKey]); |
191: | } |
192: | } |
193: | } |
194: | |
195: | |
196: | |
197: | |
198: | |
199: | |
200: | public function GetSessionValue($sKey, $mDefault = null) |
201: | { |
202: | $aValues = Session::get($this->getSessionUniqueKey(), null); |
203: | |
204: | return (\is_array($aValues) && \array_key_exists($sKey, $aValues)) ? $aValues[$sKey] : $mDefault; |
205: | } |
206: | |
207: | |
208: | |
209: | |
210: | |
211: | public function SetSessionValue($sKey, $mValue) |
212: | { |
213: | $sUniqueKey = $this->getSessionUniqueKey(); |
214: | $aValues = Session::get($sUniqueKey, array()); |
215: | if (!\is_array($aValues)) { |
216: | $aValues = array(); |
217: | } |
218: | |
219: | $aValues[$sKey] = $mValue; |
220: | Session::Set($sUniqueKey, $aValues); |
221: | } |
222: | |
223: | |
224: | |
225: | |
226: | protected function getSessionUniqueKey() |
227: | { |
228: | $sUniqueKey = (0 === \strlen($this->sSessionUniqueProperty)) ? '' : $this->{$this->sSessionUniqueProperty}; |
229: | return AbstractContainer::SESSION_CONTAINER_PREFIX.$this->sParentClassName.$sUniqueKey; |
230: | } |
231: | |
232: | |
233: | |
234: | |
235: | public function SessionUniqueProperty() |
236: | { |
237: | return $this->sSessionUniqueProperty; |
238: | } |
239: | |
240: | |
241: | |
242: | |
243: | public function SessionUniquePropertyValue() |
244: | { |
245: | return (0 === \strlen($this->sSessionUniqueProperty)) ? '' : $this->{$this->sSessionUniqueProperty}; |
246: | } |
247: | |
248: | |
249: | |
250: | |
251: | |
252: | |
253: | public function IsProperty($sPropertyName) |
254: | { |
255: | $aMap = $this->getMap(); |
256: | return isset($aMap[$sPropertyName]); |
257: | } |
258: | |
259: | |
260: | |
261: | |
262: | |
263: | public function __isset($sPropertyName) |
264: | { |
265: | return $this->IsProperty($sPropertyName); |
266: | } |
267: | |
268: | |
269: | |
270: | |
271: | |
272: | |
273: | public function __set($sKey, $mValue) |
274: | { |
275: | $aMap = $this->getMap(); |
276: | if (isset($aMap[$sKey])) { |
277: | $this->setType($mValue, $aMap[$sKey][0]); |
278: | |
279: | if (\key_exists($sKey, $this->aContainer)) { |
280: | $this->aObsolete[$sKey] = $this->aContainer[$sKey]; |
281: | } |
282: | |
283: | if (($this->__USE_TRIM_IN_STRINGS__ && 0 === \strpos($aMap[$sKey][0], 'string')) || |
284: | (\in_array($sKey, $this->aTrimer) && \is_string($mValue))) { |
285: | $mValue = trim($mValue); |
286: | } |
287: | |
288: | if (\is_string($mValue)) { |
289: | if (\in_array($sKey, $this->aLower)) { |
290: | $mValue = \strtolower($mValue); |
291: | } elseif (\in_array($sKey, $this->aUpper)) { |
292: | $mValue = \strtoupper($mValue); |
293: | } |
294: | } |
295: | |
296: | $this->aContainer[$sKey] = $mValue; |
297: | } else { |
298: | throw new Exceptions\BaseException(Exceptions\Errs::Container_UndefinedProperty, null, array('{{PropertyName}}' => $sKey)); |
299: | } |
300: | } |
301: | |
302: | |
303: | |
304: | |
305: | |
306: | |
307: | |
308: | |
309: | public function __get($sKey) |
310: | { |
311: | $mReturn = null; |
312: | if (\array_key_exists($sKey, $this->aContainer)) { |
313: | $mReturn = $this->aContainer[$sKey]; |
314: | } else { |
315: | throw new Exceptions\Exception('Undefined property '.$sKey); |
316: | } |
317: | |
318: | return $mReturn; |
319: | } |
320: | |
321: | |
322: | |
323: | |
324: | |
325: | protected function setType(&$mValue, $sType) |
326: | { |
327: | $sType = \strtolower($sType); |
328: | if (\in_array($sType, array('string', 'int', 'bool', 'array'))) { |
329: | \settype($mValue, $sType); |
330: | } elseif (\in_array($sType, array('datetime'))) { |
331: | \settype($mValue, 'int'); |
332: | } elseif (\in_array($sType, array('password'))) { |
333: | \settype($mValue, 'string'); |
334: | } elseif (0 === \strpos($sType, 'string(')) { |
335: | \settype($mValue, 'string'); |
336: | if (0 < \strlen($mValue)) { |
337: | $iSize = \substr($sType, 7, -1); |
338: | if (\is_numeric($iSize) && (int) $iSize < \strlen($mValue)) { |
339: | |
340: | $mValue = Utils::Utf8Truncate($mValue, (int) $iSize); |
341: | } |
342: | } |
343: | } |
344: | } |
345: | |
346: | |
347: | |
348: | |
349: | public function initBeforeChange() |
350: | { |
351: | return true; |
352: | } |
353: | |
354: | |
355: | |
356: | |
357: | public function validate() |
358: | { |
359: | return true; |
360: | } |
361: | |
362: | |
363: | |
364: | |
365: | public function getMap() |
366: | { |
367: | return array(); |
368: | } |
369: | |
370: | |
371: | |
372: | |
373: | public static function getStaticMap() |
374: | { |
375: | return array(); |
376: | } |
377: | |
378: | |
379: | |
380: | |
381: | |
382: | |
383: | public static function DbReadKeys($aMap) |
384: | { |
385: | $aResult = array(); |
386: | foreach ($aMap as $aTypes) { |
387: | if (isset($aTypes[1])) { |
388: | $aResult[] = $aTypes[1]; |
389: | } |
390: | } |
391: | return $aResult; |
392: | } |
393: | |
394: | |
395: | |
396: | |
397: | |
398: | |
399: | |
400: | public static function DbWriteKeys($aMap, $bInsert) |
401: | { |
402: | $aResult = array(); |
403: | foreach ($aMap as $sKey => $aTypes) { |
404: | if (isset($aTypes[1])) { |
405: | $bUseInInsert = $bUseInUpdate = true; |
406: | |
407: | if (isset($aTypes[2]) && !$aTypes[2]) { |
408: | $bUseInInsert = false; |
409: | } |
410: | |
411: | if (isset($aTypes[3]) && !$aTypes[3]) { |
412: | $bUseInUpdate = false; |
413: | } |
414: | |
415: | if (($bInsert && $bUseInInsert) || (!$bInsert && $bUseInUpdate)) { |
416: | $aResult[$aTypes[1]] = $sKey; |
417: | } |
418: | } |
419: | } |
420: | return $aResult; |
421: | } |
422: | |
423: | |
424: | |
425: | |
426: | |
427: | |
428: | |
429: | |
430: | public static function DbUpdateArray($oObject, $oHelper, $aExclude = array()) |
431: | { |
432: | $aResult = array(); |
433: | $aExclude = \is_array($aExclude) && 0 < \count($aExclude) ? $aExclude : array(); |
434: | |
435: | $sQueryParams = ''; |
436: | $oSettings =& Api::GetSettings(); |
437: | $bUseLogQueryParams = (bool) $oSettings->GetValue('DBLogQueryParams', false); |
438: | |
439: | $oObject->initBeforeChange(); |
440: | |
441: | $aStaticMap = $oObject->getMap(); |
442: | $aMap = AbstractContainer::DbWriteKeys($aStaticMap, false); |
443: | |
444: | foreach ($aMap as $sDbKey => $sObjectKey) { |
445: | if (\in_array($sDbKey, $aExclude)) { |
446: | continue; |
447: | } |
448: | |
449: | $mValue = $oObject->{$sObjectKey}; |
450: | if (isset($aStaticMap[$sObjectKey][0])) { |
451: | if ('password' === $aStaticMap[$sObjectKey][0]) { |
452: | $mValue = Utils::EncryptValue($mValue); |
453: | } elseif ('datetime' === $aStaticMap[$sObjectKey][0]) { |
454: | $mValue = $oHelper->TimeStampToDateFormat($mValue); |
455: | } elseif ('serialize' === $aStaticMap[$sObjectKey][0]) { |
456: | $mValue = '' === $mValue ? '' : \serialize($mValue); |
457: | } |
458: | } |
459: | |
460: | $aResult[] = $oHelper->EscapeColumn($sDbKey).' = '. |
461: | (\is_string($mValue) ? $oHelper->EscapeString($mValue) : (int) $mValue); |
462: | |
463: | if ($bUseLogQueryParams) { |
464: | $sQueryParams .= |
465: | AU_API_CRLF.AU_API_TAB.$sDbKey.' = '.( |
466: | \is_string($mValue) ? $oHelper->EscapeString($mValue) : (int) $mValue |
467: | ); |
468: | } |
469: | } |
470: | |
471: | if ($bUseLogQueryParams) { |
472: | Api::Log($sQueryParams); |
473: | } |
474: | |
475: | return $aResult; |
476: | } |
477: | |
478: | |
479: | |
480: | |
481: | |
482: | |
483: | |
484: | |
485: | |
486: | public static function DbGetObjectSqlString($sWhere, $sTableName, $aStaticMap, $oHelper) |
487: | { |
488: | $aMap = AbstractContainer::DbReadKeys($aStaticMap); |
489: | $aMap = \array_map(array($oHelper, 'EscapeColumn'), $aMap); |
490: | |
491: | $sSql = 'SELECT %s FROM %s WHERE %s'; |
492: | |
493: | return \sprintf($sSql, \implode(', ', $aMap), $sTableName, $sWhere); |
494: | } |
495: | |
496: | |
497: | |
498: | |
499: | |
500: | |
501: | |
502: | |
503: | public static function DbCreateObjectSqlString($sTableName, $oObject, $oHelper) |
504: | { |
505: | $sSql = ''; |
506: | $aResults = self::DbInsertArrays($oObject, $oHelper); |
507: | |
508: | if ($aResults[0] && $aResults[1]) { |
509: | $sSql = 'INSERT INTO %s ( %s ) VALUES ( %s )'; |
510: | $sSql = \sprintf($sSql, $sTableName, \implode(', ', $aResults[0]), \implode(', ', $aResults[1])); |
511: | } |
512: | |
513: | return $sSql; |
514: | } |
515: | |
516: | |
517: | |
518: | |
519: | |
520: | |
521: | |
522: | |
523: | public static function DbUpdateObjectSqlString($sTableName, $oObject, $oHelper) |
524: | { |
525: | $aResult = self::DbUpdateArray($oObject, $oHelper); |
526: | $mValue = $oObject->SessionUniquePropertyValue(); |
527: | |
528: | $sSql = 'UPDATE %s SET %s WHERE %s = %s'; |
529: | return \sprintf( |
530: | $sSql, |
531: | $sTableName, |
532: | \implode(', ', $aResult), |
533: | $oHelper->EscapeColumn($oObject->SessionUniqueProperty()), |
534: | (\is_string($mValue) ? $oHelper->EscapeString($mValue) : (int) $mValue) |
535: | ); |
536: | } |
537: | |
538: | |
539: | |
540: | |
541: | |
542: | |
543: | public static function DbInsertArrays($oObject, $oHelper) |
544: | { |
545: | $aResult = array(false, false); |
546: | |
547: | $sQueryParams = ''; |
548: | $oSettings =& Api::GetSettings(); |
549: | $bUseLogQueryParams = (bool) $oSettings->GetValue('DBLogQueryParams', false); |
550: | |
551: | $oObject->initBeforeChange(); |
552: | |
553: | $aStaticMap = $oObject->getMap(); |
554: | $aMap = AbstractContainer::DbWriteKeys($aStaticMap, true); |
555: | |
556: | $aDbKeys = \array_keys($aMap); |
557: | $aResult[0] = \array_map(array(&$oHelper, 'EscapeColumn'), $aDbKeys); |
558: | |
559: | $aDbValues = \array_values($aMap); |
560: | foreach ($aDbValues as $iIndex => $sKey) { |
561: | $mValue = $oObject->{$sKey}; |
562: | if (isset($aStaticMap[$sKey][0])) { |
563: | if ('password' === $aStaticMap[$sKey][0]) { |
564: | $mValue = Utils::EncryptValue($mValue); |
565: | } elseif ('datetime' === $aStaticMap[$sKey][0]) { |
566: | $mValue = $oHelper->TimeStampToDateFormat($mValue); |
567: | } elseif ('serialize' === $aStaticMap[$sKey][0]) { |
568: | $mValue = '' === $mValue ? '' : serialize($mValue); |
569: | } |
570: | } |
571: | |
572: | $aDbValues[$iIndex] = \is_string($mValue) |
573: | ? $oHelper->EscapeString($mValue) : (int) $mValue; |
574: | |
575: | if ($bUseLogQueryParams) { |
576: | $sDbKey = isset($aDbKeys[$iIndex]) ? $aDbKeys[$iIndex] : '!unknown!'; |
577: | $sQueryParams .= AU_API_CRLF.AU_API_TAB.$sDbKey.' = '.$aDbValues[$iIndex]; |
578: | } |
579: | } |
580: | |
581: | $aResult[1] = $aDbValues; |
582: | |
583: | if ($bUseLogQueryParams) { |
584: | Api::Log($sQueryParams); |
585: | } |
586: | |
587: | return $aResult; |
588: | } |
589: | } |
590: | |