root/trunk/midcom/midcom.helper.datamanager2/datamanager.php

Revision 17556, 15.5 kB (checked in by flack, 3 weeks ago)

yet more PHP5-style constructors

  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * @package midcom.helper.datamanager2
4  * @author The Midgard Project, http://www.midgard-project.org
5  * @version $Id$
6  * @copyright The Midgard Project, http://www.midgard-project.org
7  * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
8  */
9
10 /**
11  * Datamanager 2 Data Manager core class.
12  *
13  * This class controls all type I/O operations, including entering and exiting
14  * editing operations and creation support. It brings Types, Schemas and Storage objects
15  * together.
16  *
17  * @package midcom.helper.datamanager2
18  */
19 class midcom_helper_datamanager2_datamanager extends midcom_baseclasses_components_purecode
20 {
21     /**
22      * The schema database to use for operation. This variable will always contain a parsed
23      * representation of the schema, so that one can swiftly switch between individual schemas
24      * of the Database. This is a list of midcom_helper_datamanager2_schema
25      * instances, indexed by their name.
26      *
27      * @var Array
28      * @access private
29      */
30     var $_schemadb = null;
31
32     /**
33      * This variable holds the schema currently in use, it has been created from the array
34      * stored in the $_schemadb member.
35      *
36      * This object can be modified as long as the types are not initialized. If you change
37      * the schema afterwards, the changes will not propagate to any dependant object until
38      * you reinitialize the class.
39      *
40      * @var midcom_helper_datamanager2_schema
41      */
42     var $schema = null;
43
44     /**
45      * The id (array index) of the current schema
46      * @var string schema_name
47      */
48     var $schema_name = '';
49
50     /**
51      * This is the storage implementation which is used for operation on the types. It encapsulates
52      * the storage target.
53      *
54      * @var midcom_helper_datamanager2_storage
55      * @access public
56      */
57     var $storage = null;
58
59     /**
60      * This is a listing of all types that have been loaded from the storage object. You may
61      * manipulate these types and their values at will, and then store them back to the database
62      * using the functions available in this class.
63      *
64      * @var Array
65      */
66     var $types = null;
67
68     /**
69      * This variable contains an Array of all validation errors that have occurred
70      * during saving. As outlined in the type, these messages my have inline-html
71      * in it and it is assumed to be localized.
72      *
73      * The errors are indexed by field name.
74      *
75      * @var Array
76      * @see midcom_helper_datamanager2_type::$validation_error
77      */
78     var $validation_errors = Array();
79
80     /**
81      * Reference to the form manager instance which is currently in use. Usually, it is created and referenced here by the controller
82      * class during initialization.
83      *
84      * @var midcom_helper_datamanager2_formmanager
85      */
86     var $formmanager = null;
87
88     /**
89      * The constructor loads the schema database to use but does nothing else
90      * so far.
91      *
92      * @param Array &$schemadb A list of midcom_helper_datamanager2_schema instances,
93      *     indexed by their schema name. This member is taken by reference.
94      * @see midcom_helper_datamanager2_schema::load_database()
95      */
96     function __construct(&$schemadb)
97     {
98          $this->_component = 'midcom.helper.datamanager2';
99          parent::__construct();
100          $this->_schemadb =& $schemadb;
101     }
102
103     /**
104      * This function activates the given schema. This will drop all existing types
105      * and create a new set of them which are in the default state at this point.
106      *
107      * This will reset the existing schema and type listing. If a storage object
108      * exists, the change of the schema will be propagated implicitly, as it will
109      * reference the schema member of ours.
110      *
111      * @param string $name The name of the schema to use, omit this to use the default
112      *     schema.
113      * @return boolean Indicating success.
114      */
115     function set_schema($name = null)
116     {
117         if (!is_array($this->_schemadb))
118         {
119             debug_push_class(__CLASS__, __FUNCTION__);
120             debug_add("The active schema database is invalid.", MIDCOM_LOG_ERROR);
121             debug_pop();
122             return false;
123         }
124         if (   $name !== null
125             && ! array_key_exists($name, $this->_schemadb))
126         {
127             debug_push_class(__CLASS__, __FUNCTION__);
128             debug_add("The schema {$name} was not found in the active schema database.", MIDCOM_LOG_INFO);
129             debug_pop();
130             return false;
131         }
132
133         if ($name === null)
134         {
135             reset($this->_schemadb);
136             $name = key($this->_schemadb);
137         }
138
139         $this->schema =& $this->_schemadb[$name];
140         $this->schema_name = $name;
141
142         return $this->_load_types();
143     }
144
145
146     /**
147      * This function sets the system to use a specific storage object. You can pass
148      * either a MidCOM DBA object or a fully initialized storage subclass. The former
149      * is automatically wrapped in a midcom storage object. If you pass your own
150      * storage object, ensure that it uses the same schema as this class. Ideally,
151      * you should use references for this.
152      *
153      * This call will fail if there is no schema set. All types will be set and
154      * initialized to the new storage object. Thus, it is possible to call set_storage
155      * repeatedly thus switching an existing DM instance over to a new storage object
156      * as long as you work with the same schema.
157      *
158      * @param mixed &$object A reference to either a MidCOM DBA class or a subclass of
159      *     midcom_helper_datamanager2_storage.
160      * @return boolean Indicating success.
161      */
162     function set_storage(&$object)
163     {
164         if ($this->schema === null)
165         {
166             debug_push_class(__CLASS__, __FUNCTION__);
167             debug_add('Cannot initialize to a storage object if the schema is not yet set.', MIDCOM_LOG_INFO);
168             debug_pop();
169             return false;
170         }
171
172         if (! is_a($object, 'midcom_helper_datamanager2_storage'))
173         {
174             $this->storage = new midcom_helper_datamanager2_storage_midgard($this->schema, $object);
175         }
176         else
177         {
178             $this->storage =& $object;
179         }
180
181         // For reasons I do not completely comprehend, PHP drops the storage references into the types
182         // in the lines above. Right now the only solution (except debugging this 5 hours long line
183         // by line) I see is explicitly setting the storage references in the types.
184         foreach ($this->types as $type => $copy)
185         {
186             $this->types[$type]->set_storage($this->storage);
187         }
188
189         $this->storage->load($this->types);
190
191         return true;
192     }
193
194     /**
195      * This function will create all type objects for the current schema. It will load class
196      * files where necessary (using require_once), and then create a set of instances
197      * based on the schema.
198      *
199      * @return boolean Indicating success
200      * @access private
201      */
202     function _load_types()
203     {
204         $this->types = Array();
205
206         foreach ($this->schema->fields as $name => $config)
207         {
208             if (!isset($config['type']) )
209             {
210                 throw new Exception("The field {$name} is missing type");
211             }
212
213             $filename = MIDCOM_ROOT . "/midcom/helper/datamanager2/type/{$config['type']}.php";
214             $classname = "midcom_helper_datamanager2_type_{$config['type']}";
215             require_once($filename);
216
217             $this->types[$name] = new $classname();
218             if (! $this->types[$name]->initialize($name, $config['type_config'], $this->storage))
219             {
220                 debug_push_class(__CLASS__, __FUNCTION__);
221                 debug_add("Failed to initialize the type for {$name}, see the debug level log for full details.",
222                     MIDCOM_LOG_INFO);
223                 debug_pop();
224                 return false;
225             }
226         }
227
228         return true;
229     }
230
231
232     /**
233      * This function is a shortcut that combines set_schema and set_storage together.
234      * The schema name is looked up in the parameter 'midcom.helper.datamanager2/schema_name',
235      * if it is not found, the first schema from the schema database is used implicitly.
236      *
237      * @see set_schema()
238      * @see set_storage()
239      * @param mixed &$object A reference to either a MidCOM DBA class or a subclass of
240      *     midcom_helper_datamanager2_storage.
241      * @param boolean $strict Whether we should strictly use only the schema given by object params
242      * @return boolean Indicating success.
243      */
244     function autoset_storage(&$object, $strict = false)
245     {
246         if (is_a($object, 'midcom_helper_datamanager2_storage'))
247         {
248             $schema = $object->object->get_parameter('midcom.helper.datamanager2', 'schema_name');
249         }
250         else
251         {
252             $schema = $object->get_parameter('midcom.helper.datamanager2', 'schema_name');
253         }
254
255         if (! $schema)
256         {
257             $schema = null;
258         }
259
260         if (!$this->set_schema($schema))
261         {
262             if (   $strict
263                 || $schema == null)
264             {
265                 return false;
266             }
267             else
268             {
269                 debug_push_class(__CLASS__, __FUNCTION__);
270                 debug_add("Given schema name {$schema} was not found, reverting to default.", MIDCOM_LOG_INFO);
271                 debug_pop();
272                 // Schema database has probably changed so we should be graceful here
273                 if (!$this->set_schema(null))
274                 {
275                     return false;
276                 }
277             }
278
279         }
280         return $this->set_storage($object);
281     }
282
283     /**
284      * This function will save the current state of all types to disk. A full
285      * validation cycle is done beforehand, if any validation fails, the function
286      * aborts and sets the $validation_errors member variable accordingly.
287      *
288      * @return boolean Indicating success
289      */
290     function save()
291     {
292         if (! $this->validate())
293         {
294             debug_push_class(__CLASS__, __FUNCTION__);
295             debug_add(count($this->validation_errors) . ' fields have failed validation, cannot save.',
296                 MIDCOM_LOG_WARN);
297             debug_print_r('Validation errors:', $this->validation_errors);
298             debug_pop();
299             return false;
300         }
301
302         return $this->storage->store($this->types);
303     }
304
305     /**
306      * Validate the current object state. It will populate $validation_errors
307      * accordingly.
308      *
309      * @return boolean Indicating validation success.
310      */
311     function validate()
312     {
313         $this->validation_errors = Array();
314         $validated = true;
315         foreach ($this->schema->fields as $name => $config)
316         {
317             if (! $this->types[$name]->validate())
318             {
319                 $this->validation_errors[$name] = $this->types[$name]->validation_error;
320                 $validated = false;
321             }
322         }
323         return $validated;
324     }
325
326     /**
327      * Little helper function returning an associative array of all field values converted to HTML
328      * using their default convert_to_html option.
329      *
330      * @return Array All field values in their HTML representation indexed by their name.
331      */
332     function get_content_html()
333     {
334         $result = Array();
335         foreach ($this->schema->field_order as $name)
336         {
337             $result[$name] = $this->types[$name]->convert_to_html();
338         }
339         return $result;
340     }
341
342     /**
343      * Little helper function returning an associative array of all field values converted to XML
344      * using their default convert_to_csv or convert_to_raw options.
345      *
346      * @return Array All field values in their XML representation indexed by their name.
347      */
348     function get_content_xml()
349     {
350         $result = Array();
351         foreach ($this->schema->field_order as $name)
352         {
353             if (is_a($this->types[$name], 'midcom_helper_datamanager2_type_blobs'))
354             {
355                 $result[$name] = explode(',', $this->types[$name]->convert_to_csv());
356             }
357             elseif (is_a($this->types[$name], 'midcom_helper_datamanager2_type_select'))
358             {
359                 $this->types[$name]->csv_export_key = true;
360                 $this->types[$name]->multiple_storagemode = 'array';
361                 $result[$name] = $this->types[$name]->convert_to_storage();
362             }
363             else
364             {
365                 $result[$name] = $this->types[$name]->convert_to_storage();
366             }
367         }
368         return $result;
369     }
370
371     /**
372      * Little helper function returning an associative array of all field values converted to CSV
373      * using their default convert_to_csv option.
374      *
375      * @return Array All field values in their CSV representation indexed by their name.
376      */
377     function get_content_csv()
378     {
379         $result = Array();
380         foreach ($this->schema->field_order as $name)
381         {
382             $result[$name] = $this->types[$name]->convert_to_csv();
383         }
384         return $result;
385     }
386
387     /**
388      * Little helper function returning an associative array of all field values converted to email-friendly format
389      * using their default convert_to_email option.
390      *
391      * @return Array All field values in their CSV representation indexed by their name.
392      */
393     function get_content_email()
394     {
395         $result = Array();
396         foreach ($this->schema->field_order as $name)
397         {
398             $result[$name] = $this->types[$name]->convert_to_email();
399         }
400         return $result;
401     }
402
403     /**
404      * Little helper function returning an associative array of all field values converted to
405      * their raw storage representation..
406      *
407      * @return Array All field values in their raw storage representation indexed by their name.
408      */
409     function get_content_raw()
410     {
411         $result = Array();
412         foreach ($this->schema->field_order as $name)
413         {
414             if (!isset($this->types[$name]))
415             {
416                 continue;
417             }
418             $result[$name] = $this->types[$name]->convert_to_raw();
419         }
420         return $result;
421     }
422
423     /**
424      * This function displays a quick view of the record, using some simple div based layout,
425      * which can be formatted using CSS.
426      *
427      * Be aware that this is only geared for simple administration interfaces, it will provide
428      * *no* editing capabilities (like AJAX) etc. If you want that to work, you need a formmanger
429      * instance instead.
430      */
431     function display_view()
432     {
433         // iterate over all types so that they can add their piece to the form
434         echo "<div class=\"midcom_helper_datamanager2_view\">\n";
435         foreach ($this->schema->fields as $name => $config)
436         {
437             if (   isset($config['hidden'])
438                 && $config['hidden'])
439             {
440                 continue;
441             }
442             echo "<div class=\"field\">\n";
443             echo '<div class="title" style="font-weight: bold;">' . $this->schema->translate_schema_string($this->schema->fields[$name]['title']) . "</div>\n";
444             echo '<div class="value" style="margin-left: 5em; min-height: 1em;">';
445
446             if ($config['widget'] == 'chooser')
447             {
448                 $this->formmanager =& new midcom_helper_datamanager2_formmanager($this->schema, $this->types);
449                 $this->formmanager->initialize();
450                 $this->formmanager->widgets[$name]->render_content();
451             }
452             else
453             {
454                 echo $this->types[$name]->convert_to_html();
455             }
456
457             echo "</div>\n";
458             echo "</div>\n";
459         }
460         echo "</div>\n";
461     }
462 }
463 ?>
Note: See TracBrowser for help on using the browser.