1 <?php
2 /**
3 * Plug-ins for additional functionality in your DataObjects.
4 *
5 * Note: DataObjectDecorators are not actually Decorators in the GoF Design Patterns sense of the
6 * word. A better name for this class would be DataExtension. However, in the interests of
7 * backward compatibility we haven't renamed the class.
8 *
9 * @package sapphire
10 * @subpackage model
11 */
12 abstract class DataObjectDecorator extends Extension {
13
14 /**
15 * Statics on a {@link DataObject} subclass
16 * which can be decorated onto. This list is
17 * limited for security and performance reasons.
18 *
19 * Keys are the static names, and the values are whether or not the value is an array that should
20 * be merged.
21 *
22 * @var array
23 */
24 protected static $decoratable_statics = array(
25 'db' => true,
26 'has_one' => true,
27 'belongs_to' => true,
28 'indexes' => true,
29 'defaults' => true,
30 'has_many' => true,
31 'many_many' => true,
32 'belongs_many_many' => true,
33 'many_many_extraFields' => true,
34 'searchable_fields' => true,
35 'api_access' => false,
36 );
37
38 private static $extra_statics_loaded = array();
39
40 /**
41 * Load the extra static definitions for the given extension
42 * class name, called by {@link Object::add_extension()}
43 *
44 * @param string $class Class name of the owner class (or owner base class)
45 * @param string $extension Class name of the extension class
46 */
47 public static function load_extra_statics($class, $extension) {
48 if(!empty(self::$extra_statics_loaded[$class][$extension])) return;
49 self::$extra_statics_loaded[$class][$extension] = true;
50
51 if(preg_match('/^([^(]*)/', $extension, $matches)) {
52 $extensionClass = $matches[1];
53 } else {
54 user_error("Bad extenion '$extension' - can't find classname", E_USER_WARNING);
55 return;
56 }
57
58 // @deprecated 2.4 - use extraStatics() now, not extraDBFields()
59 if(method_exists($extensionClass, 'extraDBFields')) {
60 user_error('DataObjectDecorator::extraDBFields() is deprecated. Please use extraStatics() instead.', E_USER_NOTICE);
61 $extraStaticsMethod = 'extraDBFields';
62 } else {
63 $extraStaticsMethod = 'extraStatics';
64 }
65
66 // If the extension has been manually applied to a subclass, we should ignore that.
67 if(Object::has_extension(get_parent_class($class), $extensionClass)) return;
68
69 $statics = call_user_func(array($extensionClass, $extraStaticsMethod), $class, $extension);
70
71 if($statics) {
72 foreach($statics as $name => $newVal) {
73 if(isset(self::$decoratable_statics[$name])) {
74
75 // Array to be merged
76 if(self::$decoratable_statics[$name]) {
77 $origVal = Object::uninherited_static($class, $name);
78 // Can't use add_static_var() here as it would merge the array rather than replacing
79 Object::set_static($class, $name, array_merge((array)$origVal, $newVal));
80
81 // Value to be overwritten
82 } else {
83 Object::set_static($class, $name, $newVal);
84 }
85 }
86 }
87
88 DataObject::$cache_has_own_table[$class] = null;
89 DataObject::$cache_has_own_table_field[$class] = null;
90 }
91 }
92
93 /**
94 * Edit the given query object to support queries for this extension
95 *
96 * @param SQLQuery $query Query to augment.
97 */
98 function augmentSQL(SQLQuery &$query) {
99 }
100
101 /**
102 * Update the database schema as required by this extension.
103 */
104 function augmentDatabase() {
105 }
106
107 /**
108 * Augment a write-record request.
109 *
110 * @param SQLQuery $manipulation Query to augment.
111 */
112 function augmentWrite(&$manipulation) {
113 }
114
115 function onBeforeWrite() {
116 }
117
118 function onAfterWrite() {
119 }
120
121 function onBeforeDelete() {
122 }
123
124 function onAfterDelete() {
125 }
126
127 function requireDefaultRecords() {
128 }
129
130 function populateDefaults() {
131 }
132
133 function can($member) {
134 }
135
136 function canEdit($member) {
137 }
138
139 function canDelete($member) {
140 }
141
142 function canCreate($member) {
143 }
144
145 /**
146 * Define extra database fields
147 *
148 * Return a map where the keys are db, has_one, etc, and the values are
149 * additional fields/relations to be defined.
150 *
151 * @return array Returns a map where the keys are db, has_one, etc, and
152 * the values are additional fields/relations to be defined.
153 */
154 function extraStatics() {
155 return array();
156 }
157
158 /**
159 * This function is used to provide modifications to the form in the CMS
160 * by the decorator. By default, no changes are made. {@link DataObject->getCMSFields()}.
161 *
162 * Please consider using {@link updateFormFields()} to globally add
163 * formfields to the record. The method {@link updateCMSFields()}
164 * should just be used to add or modify tabs, or fields which
165 * are specific to the CMS-context.
166 *
167 * Caution: Use {@link FieldSet->addFieldToTab()} to add fields.
168 *
169 * @param FieldSet $fields FieldSet with a contained TabSet
170 */
171 function updateCMSFields(FieldSet &$fields) {
172 }
173
174 /**
175 * This function is used to provide modifications to the form used
176 * for front end forms. {@link DataObject->getFrontEndFields()}
177 *
178 * Caution: Use {@link FieldSet->push()} to add fields.
179 *
180 * @param FieldSet $fields FieldSet without TabSet nesting
181 */
182 function updateFrontEndFields(FieldSet &$fields) {
183 }
184
185 /**
186 * This is used to provide modifications to the form actions
187 * used in the CMS. {@link DataObject->getCMSActions()}.
188 *
189 * @param FieldSet $actions FieldSet
190 */
191 function updateCMSActions(FieldSet &$actions) {
192 }
193
194 /**
195 * this function is used to provide modifications to the summary fields in CMS
196 * by the decorator
197 * By default, the summaryField() of its owner will merge more fields defined in the decorator's
198 * $extra_fields['summary_fields']
199 */
200 function updateSummaryFields(&$fields){
201 $extra_fields = $this->extraStatics();
202 if(isset($extra_fields['summary_fields'])){
203 $summary_fields = $extra_fields['summary_fields'];
204
205 // if summary_fields were passed in numeric array,
206 // convert to an associative array
207 if($summary_fields && array_key_exists(0, $summary_fields)) {
208 $summary_fields = array_combine(array_values($summary_fields), array_values($summary_fields));
209 }
210 if($summary_fields) $fields = array_merge($fields, $summary_fields);
211 }
212 }
213
214 /**
215 * this function is used to provide modifications to the fields labels in CMS
216 * by the decorator
217 * By default, the fieldLabels() of its owner will merge more fields defined in the decorator's
218 * $extra_fields['field_labels']
219 */
220 function updateFieldLabels(&$lables){
221 $extra_fields = $this->extraStatics();
222 if(isset($extra_fields['field_labels'])){
223 $field_labels = $extra_fields['field_labels'];
224 if($field_labels) $lables = array_merge($lables, $field_labels);
225 }
226 }
227
228 /**
229 * Clear any internal caches.
230 */
231 function flushCache() {
232 }
233
234 }
235 ?>
236