/[cvs]/nfo/php/libs/org.netfrag.glib/Data/Driver/Proxy.php
ViewVC logotype

Annotation of /nfo/php/libs/org.netfrag.glib/Data/Driver/Proxy.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Mon Mar 3 21:48:26 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.3: +7 -1 lines
FILE REMOVED
refactored to DesignPattern::RemoteProxy

1 joko 1.3 <?php
2    
3     /**
4     * -------------------------------------------------------------------------
5 joko 1.4 * $Id: Proxy.php,v 1.3 2003/03/01 04:56:38 joko Exp $
6 joko 1.3 * -------------------------------------------------------------------------
7     * $Log: Proxy.php,v $
8 joko 1.4 * Revision 1.3 2003/03/01 04:56:38 joko
9     * new comment style for large blocks - stolen from phpHtmlLib
10     * commit-log encapsulated into such a block
11     * introduced some documentation
12     * refactored todo (now also inside a stylish block)
13     *
14 joko 1.3 * Revision 1.2 2003/02/13 21:48:09 joko
15     * + caching mechanisms more configurable now
16     *
17     * Revision 1.1 2003/02/09 17:23:21 joko
18     * + refactored from flib/Application/RPC/ProxyObject.php
19     *
20     * Revision 1.7 2003/02/03 03:31:38 jonen
21     * - moved '$encoder->toISO()' to 'Remote.php'
22     *
23     * Revision 1.6 2002/12/22 13:26:20 jonen
24     * + added support of tangram independent id (e.g. Data::UUID) toggled by option at conrtuctor
25     *
26     * Revision 1.5 2002/12/18 22:36:49 jonen
27     * + added support to get remote objects via backend via 'guid'
28     * + renamed '_loadBackend' to '_loadRemote'
29     * + constructor now accepts additional options:
30     * + remote: try to get object via '_loadRemote' ...
31     * + oid: use the given identifier as an 'oid' when doing '_loadRemote'
32     * + guid: use the given identifier as a 'guid' when doing '_loadRemote'
33     *
34     * Revision 1.4 2002/12/12 02:46:31 joko
35     * + state (session) gets flushed when data was successfully loaded from remote side
36     * + fixed _loadBackend
37     * + fixed flushState
38     *
39     * Revision 1.3 2002/12/06 04:12:54 joko
40     * + replaced 'xyzCache' through 'xyzProxy'
41     * + function store(...)
42     *
43     * Revision 1.2 2002/12/05 21:44:09 joko
44     * + debugging
45     *
46     * Revision 1.1 2002/12/01 17:23:58 joko
47     * + initial check-in
48     *
49     * Revision 1.11 2002/11/12 06:05:58 cvsjoko
50     * + renamed class: Text_Encode -> TextEncode
51     *
52     * Revision 1.10 2002/10/29 19:15:33 cvsjoko
53     * - moved utf8/iso-conversion to lib/utils/Text_Encode.php
54     *
55     * Revision 1.9 2002/10/26 12:32:36 cvsjoko
56     * - removed debugging via "print"
57     * + added generic logging via PEAR::Log
58     *
59     * Revision 1.8 2002/10/22 09:51:38 cvsmax
60     * + moved semi-method 'createBackend' to method $site->user->create at User.class.php
61     *
62     * Revision 1.7 2002/10/21 18:27:09 cvsjoko
63     * - manually disabled any form of caching
64     *
65     * Revision 1.6 2002/10/17 03:48:47 cvsmax
66     * + new
67     * + function _createBackend create new Backend
68     * + function _create api-create
69     *
70     * Revision 1.5 2002/10/16 03:37:54 cvsjoko
71     * + bugfix: wrong comparison in restriction to save to array
72     *
73     * Revision 1.4 2002/10/10 03:04:23 cvsjoko
74     * + no debug-output
75     *
76     * Revision 1.3 2002/10/10 03:03:27 cvsjoko
77     * + bugfix: save object to cache only if payload from backend isn't empty
78     *
79     * Revision 1.2 2002/10/10 02:40:06 cvsjoko
80     * + new level of data-caching (session and persistant)
81     * + function _loadState loads data from session
82     * + function _saveState saves data to session
83     * + function save api-save (session & backend)
84     * + function _commit saves data to backend
85     * + handy utils
86     * + function _setAttributes
87     * + function flushState
88     *
89     * Revision 1.1 2002/10/09 00:51:39 cvsjoko
90     * + new
91     * -------------------------------------------------------------------------
92     */
93    
94     /**
95     *
96     * Data::Driver::Proxy -- Multiple stage data fetching and caching
97     *
98     *
99     * This class (Data::Driver::Proxy) provides an abstract framework
100     * for loading/saving arbitrary data from/to data storages interfaced
101     * by storage *proxy*-drivers.
102     * Don't mix these up with the concrete storage *handle*-drivers
103     * doing the lowlevel stuff (opening files, talking sql, etc.).
104     * These proxy-drivers are "just" wrappers around them
105     * providing a more highlevel, consistent API making
106     * it easier for Data::Driver::Proxy to do its main work:
107     *
108     * Multiple stage data fetching and caching:
109     *
110     * DATA, ...
111     * ... also refered to as data, should be handled as
112     * something called data.
113     *
114     * STAGES
115     * x native php4 session: serialized payload
116     * x single rdbms table: serialized payload
117     * x ... via custom database wrapper
118     * x included php-file, included php-library
119     * o object, component, package, callbacks
120     * x ... via php PEAR DB abstraction objects
121     * x remote objects (items): flat attribute hash
122     * o use Data::Object::Identity
123     * o via Data::Driver::Proxy::RPC or others
124     * o Data::Object::Encoder: encodes/decodes values
125     * o Data::Object::Interpolator: interpolates/resolves references
126     *
127     * WORK
128     * x move data transparently around between these stages
129     *
130     * TOOLS
131     *
132     * x Overview - Packages, Handlers and Stages:
133     * This is weird. ;-)
134     * - A Package can be instantiated by its namespaced classname
135     * e.g.: "mkObject('My::Package');"
136     * - A Package can be a Handler for Data::Driver::Proxy
137     * - A Handler implements exactly one Stage
138     * - Data::Driver::Proxy itself embeds these Stages:
139     * x php4-session
140     * x rdbms-table
141     * - An example Handler is Data::Driver::RPC::Remote
142     *
143     * x Handlers:
144     * x Data::Driver::RPC::Remote
145     * Interacts with a RPC::XML server (todo: talk SOAP!)
146     * using PEAR::XML::RPC.
147     * It can cache data for "disconnected mode" using the
148     * o Data::Driver::phpHtmlLib
149     * o Data::Driver::PEAR::DB
150     * x Data::Driver::PEAR::Tree (via Data::Lift)
151     *
152     */
153    
154     /**
155     * Todo:
156     * x extend options to en-/disable caching via a) session and/or b) database
157     * o make feature available via runtime setter-method to these options
158     * o use PEAR::Cache for caching purposes!!!
159     * o refactor database access: use PEAR for this! no more 'connectdb' here!!!
160     * o make database connection more flexible to make possible
161     * to have different (probably named) proxy databases (besides a "main database")
162     * o rename this to Data::Proxy? or split into Data::Query, Data::Result and Data::Wrapper?
163     *
164     */
165 joko 1.1
166    
167     class Data_Driver_Proxy {
168    
169     var $objectId;
170     // purpose ...
171     var $meta;
172     var $payload;
173     var $attributes;
174     var $backend;
175    
176     function Data_Driver_Proxy($objectId = "", $options = array() ) {
177     logp(get_class($this) . "->new()", PEAR_LOG_INFO);
178     global $proxy;
179 joko 1.2
180     // trace
181     //print Dumper($objectId, $options);
182    
183     // initialization/startup
184     $this->_init_meta_options($objectId, $options);
185     $this->_init_caching();
186     $this->_init_load();
187    
188 joko 1.1 }
189    
190 joko 1.2 function _init_meta_options( $objectId="", $options = array() ) {
191     $this->meta = $options;
192    
193 joko 1.1 if ($objectId) {
194     $this->objectId = $objectId;
195    
196     // set default load mechanism
197 joko 1.2 if ( $this->meta[remote] && ((!$this->meta[oid] && !$this->meta[guid]) || ($this->meta[oid] && $this->meta[guid])) && (!$this->meta[key]) ) {
198 joko 1.1 $this->meta[oid] = 1;
199     }
200    
201 joko 1.2 }
202     }
203    
204     function _init_caching() {
205    
206     if ($this->meta[cache][session]) {
207     session_register_safe("proxy");
208     }
209    
210     if ($this->meta[remote]) {
211     $this->backend = mkObject('Data::Driver::RPC::Remote', $this->meta[rpcinfo]);
212     }
213     }
214    
215     function _init_load() {
216     if ($this->objectId) {
217 joko 1.1 $this->load();
218     //$this->_saveProxy();
219     }
220     }
221    
222 joko 1.2
223 joko 1.1 function load() {
224     logp(get_class($this) . "->load()", PEAR_LOG_INFO);
225     if (!$this->_loadState()) {
226     if (!$this->_loadProxy()) {
227    
228     // just load object from remote side if its flagged to be a remote one ...
229     if ($this->meta[remote]) {
230     $this->_loadRemote();
231     }
232    
233     }
234     }
235     }
236    
237     function save($data, $type) {
238     $this->_setAttributes($data);
239     $this->_saveState();
240     if ($type == 'commit') {
241     $this->_commit();
242     }
243     if ($type == 'create') {
244     $this->_create();
245     }
246     }
247    
248     function flush() {
249     $this->flushState();
250     $this->flushProxy();
251     }
252    
253     function _commit() {
254     $this->_saveBackend($this->attributes);
255     $this->flushState();
256     $this->flushProxy();
257     }
258    
259    
260     // TODO: make this work
261     /*
262     function _create() {
263     $this->_createBackend($this->attributes);
264     $this->flushState();
265     $this->flushProxy();
266     }
267     */
268    
269     function getAttributes() {
270     if (!$this->meta[decoded]) {
271     $this->_decode();
272     $this->_saveState();
273     }
274     return $this->attributes;
275     }
276    
277     function _setAttributes($data) {
278     $this->attributes = $data;
279     }
280    
281     function flushProxy() {
282     connectdb();
283     $sql = "DELETE FROM f_proxy WHERE oid='$this->objectId'";
284     send_sql($sql);
285     }
286    
287     function flushState() {
288     global $proxy;
289     unset($proxy[$this->objectId]);
290     $this->meta[decoded] = 0;
291     }
292    
293     function _loadState() {
294     global $proxy;
295 joko 1.2
296     // trace
297     //print Dumper($this);
298    
299     // debug
300     logp(get_class($this) . "->_loadState()");
301    
302 joko 1.1 if ($this->attributes = $proxy[$this->objectId]) {
303     //print "_loadState:" . dumpVar($this->attributes);
304     $this->meta[decoded] = 1;
305     // TODO: make a parameter from this (0 deactivates session-layer)
306     return 0;
307     }
308     }
309    
310     function _saveState() {
311     global $proxy;
312     logp(get_class($this) . "->_saveState()");
313     $proxy[$this->objectId] = $this->attributes;
314     //print "_saveState: " . dumpVar($this->attributes);
315     // TODO: throw exception-message back to user if operation fails
316     }
317    
318     function _loadProxy() {
319 joko 1.2
320     // FIXME!
321     if (!$this->meta[cache][db]) { return; }
322    
323     // trace & debug
324     //print Dumper($this);
325     logp(get_class($this) . "->_loadProxy()");
326    
327 joko 1.1 connectdb();
328     $sql = "SELECT payload FROM f_proxy WHERE oid='$this->objectId'";
329     if ($res = send_sql($sql)) {
330     $row = mysql_fetch_array($res, MYSQL_ASSOC);
331     if ($row) {
332     $this->payload = $row[payload];
333     // TODO: make a parameter from this (0 deactivates mysqldb-layer)
334     return 0;
335     }
336     }
337     }
338    
339     // TODO: use PEAR here
340     function _saveProxy() {
341 joko 1.2
342     // FIXME!
343     if (!$this->meta[cache][db]) { return; }
344    
345 joko 1.1 logp(get_class($this) . "->_saveProxy()");
346     connectdb();
347     if ($this->payload) {
348     //$sql = "INSERT INTO f_proxy SET payload='$this->payload' WHERE oid='$this->objectId'";
349     $sql = "INSERT INTO f_proxy SET oid='$this->objectId', payload='$this->payload'";
350     if (!send_sql($sql)) {
351     $sql = "UPDATE f_proxy SET payload='$this->payload' WHERE oid='$this->objectId'";
352     send_sql($sql);
353     }
354     }
355     }
356    
357     function _loadRemote() {
358     logp(get_class($this) . "->_loadRemote()");
359    
360 joko 1.2 // trace
361     //print Dumper($this->meta);
362 joko 1.1
363     // TODO: test backend for reachability first (eventually cache this information and "reset" it by another party)
364    
365     // 1. check backend-handle
366     if (!$this->backend) {
367     logp(get_class($this) . "->_loadRemote: no backend handle, please check argument 'rpcinfo'", PEAR_LOG_CRIT);
368     return;
369     }
370    
371     // determine backend action by metadata
372     // check for guid or oid
373     if ($this->meta[guid]) {
374     if (!$this->objectId) {
375     logp(get_class($this) . "->_loadRemote: argument 'guid' requires valid objectId", PEAR_LOG_WARNING);
376     return;
377     }
378     if (!$this->meta[classname]) {
379     logp(get_class($this) . "->_loadRemote: argument 'guid' requires 'classname'", PEAR_LOG_WARNING);
380     return;
381     }
382     $args = array( guid => $this->objectId, classname => $this->meta[classname] );
383     $result = $this->backend->send('getObjectByGuid', $args );
384    
385     } elseif ($this->meta[oid]) {
386     if (!$this->objectId) {
387     logp(get_class($this) . "->_loadRemote: argument 'oid' requires valid objectId", PEAR_LOG_WARNING);
388     return;
389     }
390     $result = $this->backend->send('getObject', $this->objectId);
391    
392     } elseif ($this->meta[key]) {
393     if (!$this->meta[command]) {
394     logp(get_class($this) . "->_loadRemote: argument 'key' requires 'command'", PEAR_LOG_WARNING);
395     return;
396     }
397 joko 1.2 /*
398 joko 1.1 if (!$this->meta[query]) {
399     logp(get_class($this) . "->_loadRemote: argument 'key' requires 'query'", PEAR_LOG_WARNING);
400     return;
401     }
402 joko 1.2 */
403 joko 1.1 $result = $this->backend->send($this->meta[command], $this->meta[query]);
404    
405     }
406    
407    
408    
409     if ($result) {
410     //print "result: " . dumpVar($result) . "<br>";
411     if (count($result) == 0) { return; }
412    
413     // FIXME: this is dangerous!
414     if ($_GET[debug]) {
415     print Dumper($result);
416     }
417    
418     $this->payload = serialize($result);
419     // ----- move this to _encode some times
420    
421     $this->_saveProxy();
422     //print "oid: $this->objectId<br>";
423     $this->flushState();
424     } else {
425     //print "Error in _loadRemote!!!<br>";
426     logp(get_class($this) . "->_loadRemote: error while trying to talk to remote side", PEAR_LOG_CRIT);
427     }
428    
429     }
430    
431     function _saveBackend($result) {
432     logp(get_class($this) . "->_saveBackend()");
433    
434     //$encoder = new TextEncode($result);
435     //$encoder->toUTF8();
436    
437     // check for guid or oid
438     if($this->meta[guid]) {
439     $args = array( 'guid' => $this->objectId, 'classname' => $this->meta[classname], 'data' => $result );
440     $response = $this->backend->send('saveObjectByGuid', $args, array( utf8 => 1) );
441     }
442     if($this->meta[oid]) {
443     $response = $this->backend->send('saveObject', array('oid' => $this->objectId, 'data' => $result), array( utf8 => 1) );
444     }
445     }
446    
447     function _decode() {
448     // fill attributes-hashtable from message-hashtable
449     if (!$this->payload) { return; }
450     //if ($this->attributes = $backend->decodeData($this->payload)) {
451     if ($this->attributes = unserialize($this->payload)) {
452     $this->meta[decoded] = 1;
453     }
454     }
455    
456     function store($struct) {
457     $this->payload = serialize($struct);
458     $this->_saveProxy();
459     }
460    
461     }
462    
463     ?>

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed