1: <?php
2: /*****************************************************************************************
3: * X2Engine Open Source Edition is a customer relationship management program developed by
4: * X2Engine, Inc. Copyright (C) 2011-2016 X2Engine Inc.
5: *
6: * This program is free software; you can redistribute it and/or modify it under
7: * the terms of the GNU Affero General Public License version 3 as published by the
8: * Free Software Foundation with the addition of the following permission added
9: * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10: * IN WHICH THE COPYRIGHT IS OWNED BY X2ENGINE, X2ENGINE DISCLAIMS THE WARRANTY
11: * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12: *
13: * This program is distributed in the hope that it will be useful, but WITHOUT
14: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15: * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
16: * details.
17: *
18: * You should have received a copy of the GNU Affero General Public License along with
19: * this program; if not, see http://www.gnu.org/licenses or write to the Free
20: * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21: * 02110-1301 USA.
22: *
23: * You can contact X2Engine, Inc. P.O. Box 66752, Scotts Valley,
24: * California 95067, USA. or at email address contact@x2engine.com.
25: *
26: * The interactive user interfaces in modified source and object code versions
27: * of this program must display Appropriate Legal Notices, as required under
28: * Section 5 of the GNU Affero General Public License version 3.
29: *
30: * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31: * these Appropriate Legal Notices must retain the display of the "Powered by
32: * X2Engine" logo. If the display of the logo is not reasonably feasible for
33: * technical reasons, the Appropriate Legal Notices must display the words
34: * "Powered by X2Engine".
35: *****************************************************************************************/
36:
37: /**
38: * Base class for behaviors which store attributes in a different form than
39: * when the model and its attributes are loaded.
40: *
41: * Its purpose is to be used in cases whenever the stored value in the database
42: * will be different in some way from the value of the attribute when it is
43: * loaded in the model. For example, storing a JSON string in a database record,
44: * and having the corresponding model attribute be the decoded JSON object as
45: * an associative array. Thus, the transformation is transparent and requires no
46: * extra action in the code where the model is being used.
47: *
48: * In all child classes, methods {@link unpackAttribute()} and
49: * {@link packAttribute()} must be inverses of each other. In other words, given
50: * a value X, the value returned by unpackAttribute(packAttribute(X)) should be
51: * identical to X. This ensures that the storage of the data does not modify the
52: * data, one critical requirement of all database-driven software. Exceptions
53: * can be made only if any loss or addition of data is intentional and stops
54: * after a certain number of iterations of packing and unpacking.
55: *
56: * @package application.components
57: * @author Demitri Morgan <demitri@x2engine.com>
58: */
59: abstract class TransformedFieldStorageBehavior extends CActiveRecordBehavior {
60:
61: /**
62: * Array of attributes to transform.
63: * @var array
64: */
65: public $transformAttributes = array();
66:
67: /**
68: * If true, specifies that the array {@link transformAttributes} has keys
69: * that refer to the attribute names and values referring to options for
70: * each attribute. Otherwise, it is a simple array containing attribute names.
71: * @var type
72: */
73: protected $hasOptions = false;
74:
75: /**
76: * In child classes, this method takes the "working"/"unpacked" value of the
77: * attribute, and returns the value that is to be stored in the database.
78: */
79: public abstract function packAttribute($name);
80:
81: /**
82: * In child classes, this method returns the "working" value, after
83: * retrieval from the database.
84: */
85: public abstract function unpackAttribute($name);
86:
87: /**
88: * Prepares all attributes for storage
89: */
90: public function packAll(){
91: $owner = $this->getOwner();
92: foreach($this->hasOptions ? array_keys($this->transformAttributes) : $this->transformAttributes as $name){
93: $owner->$name = $this->packAttribute($name);
94: }
95: }
96:
97: /**
98: * Prepares all attributes for usage in the code, after database interaction
99: */
100: public function unpackAll(){
101: $owner = $this->getOwner();
102: foreach($this->hasOptions ?
103: array_keys($this->transformAttributes) : $this->transformAttributes as $name){
104: $owner->$name = $this->unpackAttribute($name);
105: }
106: }
107:
108: public function beforeSave($event){
109: $this->packAll();
110: }
111:
112: public function afterSave($event){
113: $this->unpackAll();
114: }
115:
116: public function afterFind($event){
117: $this->unpackAll();
118: }
119:
120: }
121:
122: ?>
123: