/[cvs]/nfo/php/libs/org.netfrag.glib/DesignPattern/RemoteProxy.php
ViewVC logotype

Annotation of /nfo/php/libs/org.netfrag.glib/DesignPattern/RemoteProxy.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Mon Mar 3 22:06:46 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
refactored from Data::Driver::Proxy

1 joko 1.1 <?php
2    
3     /**
4     * -------------------------------------------------------------------------
5     * $Id: Proxy.php,v 1.3 2003/03/01 04:56:38 joko Exp $
6     * -------------------------------------------------------------------------
7     * $Log: Proxy.php,v $
8     * 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     * 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    
166     /**
167     * Load required modules:
168     *
169     */
170     loadModule('DesignPattern::Proxy');
171    
172     class DesignPattern_RemoteProxy extends DesignPattern_Proxy {
173    
174     var $objectId;
175     // purpose ...
176     var $meta;
177     var $payload;
178     var $attributes;
179     var $backend;
180    
181     function DesignPattern_RemoteProxy($objectId = "", $options = array() ) {
182     logp(get_class($this) . "->new()", PEAR_LOG_INFO);
183     global $proxy;
184    
185     // trace
186     //print Dumper($objectId, $options);
187    
188     // initialization/startup
189     $this->_init_meta_options($objectId, $options);
190     $this->_init_caching();
191     $this->_init_load();
192    
193     }
194    
195     function _init_meta_options( $objectId="", $options = array() ) {
196     $this->meta = $options;
197    
198     if ($objectId) {
199     $this->objectId = $objectId;
200    
201     // set default load mechanism
202     if ( $this->meta[remote] && ((!$this->meta[oid] && !$this->meta[guid]) || ($this->meta[oid] && $this->meta[guid])) && (!$this->meta[key]) ) {
203     $this->meta[oid] = 1;
204     }
205    
206     }
207     }
208    
209     function _init_caching() {
210    
211     if ($this->meta[cache][session]) {
212     session_register_safe("proxy");
213     }
214    
215     if ($this->meta[remote]) {
216     //$this->backend = mkObject('Data::Driver::RPC::Remote', $this->meta[rpcinfo]);
217     $this->backend = mkObject('DataSource::Proxy::XMLRPC', $this->meta[rpcinfo]);
218     }
219     }
220    
221     function _init_load() {
222     if ($this->objectId) {
223     $this->load();
224     //$this->_saveProxy();
225     }
226     }
227    
228    
229     function load() {
230     logp(get_class($this) . "->load()", PEAR_LOG_INFO);
231     if (!$this->_loadState()) {
232     if (!$this->_loadProxy()) {
233    
234     // just load object from remote side if its flagged to be a remote one ...
235     if ($this->meta[remote]) {
236     $this->_loadRemote();
237     }
238    
239     }
240     }
241     }
242    
243     function save($data, $type) {
244     $this->_setAttributes($data);
245     $this->_saveState();
246     if ($type == 'commit') {
247     $this->_commit();
248     }
249     if ($type == 'create') {
250     $this->_create();
251     }
252     }
253    
254     function flush() {
255     $this->flushState();
256     $this->flushProxy();
257     }
258    
259     function _commit() {
260     $this->_saveBackend($this->attributes);
261     $this->flushState();
262     $this->flushProxy();
263     }
264    
265    
266     // TODO: make this work
267     /*
268     function _create() {
269     $this->_createBackend($this->attributes);
270     $this->flushState();
271     $this->flushProxy();
272     }
273     */
274    
275     function getAttributes() {
276     if (!$this->meta[decoded]) {
277     $this->_decode();
278     $this->_saveState();
279     }
280     return $this->attributes;
281     }
282    
283     function _setAttributes($data) {
284     $this->attributes = $data;
285     }
286    
287     function flushProxy() {
288     connectdb();
289     $sql = "DELETE FROM f_proxy WHERE oid='$this->objectId'";
290     send_sql($sql);
291     }
292    
293     function flushState() {
294     global $proxy;
295     unset($proxy[$this->objectId]);
296     $this->meta[decoded] = 0;
297     }
298    
299     function _loadState() {
300     global $proxy;
301    
302     // trace
303     //print Dumper($this);
304    
305     // debug
306     logp(get_class($this) . "->_loadState()");
307    
308     if ($this->attributes = $proxy[$this->objectId]) {
309     //print "_loadState:" . dumpVar($this->attributes);
310     $this->meta[decoded] = 1;
311     // TODO: make a parameter from this (0 deactivates session-layer)
312     return 0;
313     }
314     }
315    
316     function _saveState() {
317     global $proxy;
318     logp(get_class($this) . "->_saveState()");
319     $proxy[$this->objectId] = $this->attributes;
320     //print "_saveState: " . dumpVar($this->attributes);
321     // TODO: throw exception-message back to user if operation fails
322     }
323    
324     function _loadProxy() {
325    
326     // FIXME!
327     if (!$this->meta[cache][db]) { return; }
328    
329     // trace & debug
330     //print Dumper($this);
331     logp(get_class($this) . "->_loadProxy()");
332    
333     connectdb();
334     $sql = "SELECT payload FROM f_proxy WHERE oid='$this->objectId'";
335     if ($res = send_sql($sql)) {
336     $row = mysql_fetch_array($res, MYSQL_ASSOC);
337     if ($row) {
338     $this->payload = $row[payload];
339     // TODO: make a parameter from this (0 deactivates mysqldb-layer)
340     return 0;
341     }
342     }
343     }
344    
345     // TODO: use PEAR here
346     function _saveProxy() {
347    
348     // FIXME!
349     if (!$this->meta[cache][db]) { return; }
350    
351     logp(get_class($this) . "->_saveProxy()");
352     connectdb();
353     if ($this->payload) {
354     //$sql = "INSERT INTO f_proxy SET payload='$this->payload' WHERE oid='$this->objectId'";
355     $sql = "INSERT INTO f_proxy SET oid='$this->objectId', payload='$this->payload'";
356     if (!send_sql($sql)) {
357     $sql = "UPDATE f_proxy SET payload='$this->payload' WHERE oid='$this->objectId'";
358     send_sql($sql);
359     }
360     }
361     }
362    
363     function _loadRemote() {
364     logp(get_class($this) . "->_loadRemote()");
365    
366     // trace
367     //print Dumper($this->meta);
368    
369     // TODO: test backend for reachability first (eventually cache this information and "reset" it by another party)
370    
371     // 1. check backend-handle
372     if (!$this->backend) {
373     logp(get_class($this) . "->_loadRemote: no backend handle, please check argument 'rpcinfo'", PEAR_LOG_CRIT);
374     return;
375     }
376    
377     // determine backend action by metadata
378     // check for guid or oid
379     if ($this->meta[guid]) {
380     if (!$this->objectId) {
381     logp(get_class($this) . "->_loadRemote: argument 'guid' requires valid objectId", PEAR_LOG_WARNING);
382     return;
383     }
384     if (!$this->meta[classname]) {
385     logp(get_class($this) . "->_loadRemote: argument 'guid' requires 'classname'", PEAR_LOG_WARNING);
386     return;
387     }
388     $args = array( guid => $this->objectId, classname => $this->meta[classname] );
389     $result = $this->backend->send('getObjectByGuid', $args );
390    
391     } elseif ($this->meta[oid]) {
392     if (!$this->objectId) {
393     logp(get_class($this) . "->_loadRemote: argument 'oid' requires valid objectId", PEAR_LOG_WARNING);
394     return;
395     }
396     $result = $this->backend->send('getObject', $this->objectId);
397    
398     } elseif ($this->meta[key]) {
399     if (!$this->meta[command]) {
400     logp(get_class($this) . "->_loadRemote: argument 'key' requires 'command'", PEAR_LOG_WARNING);
401     return;
402     }
403     /*
404     if (!$this->meta[query]) {
405     logp(get_class($this) . "->_loadRemote: argument 'key' requires 'query'", PEAR_LOG_WARNING);
406     return;
407     }
408     */
409     $result = $this->backend->send($this->meta[command], $this->meta[query]);
410    
411     }
412    
413    
414    
415     if ($result) {
416     //print "result: " . dumpVar($result) . "<br>";
417     if (count($result) == 0) { return; }
418    
419     // FIXME: this is dangerous!
420     if ($_GET[debug]) {
421     print Dumper($result);
422     }
423    
424     $this->payload = serialize($result);
425     // ----- move this to _encode some times
426    
427     $this->_saveProxy();
428     //print "oid: $this->objectId<br>";
429     $this->flushState();
430     } else {
431     //print "Error in _loadRemote!!!<br>";
432     logp(get_class($this) . "->_loadRemote: error while trying to talk to remote side", PEAR_LOG_CRIT);
433     }
434    
435     }
436    
437     function _saveBackend($result) {
438     logp(get_class($this) . "->_saveBackend()");
439    
440     //$encoder = new TextEncode($result);
441     //$encoder->toUTF8();
442    
443     // check for guid or oid
444     if($this->meta[guid]) {
445     $args = array( 'guid' => $this->objectId, 'classname' => $this->meta[classname], 'data' => $result );
446     $response = $this->backend->send('saveObjectByGuid', $args, array( utf8 => 1) );
447     }
448     if($this->meta[oid]) {
449     $response = $this->backend->send('saveObject', array('oid' => $this->objectId, 'data' => $result), array( utf8 => 1) );
450     }
451     }
452    
453     function _decode() {
454     // fill attributes-hashtable from message-hashtable
455     if (!$this->payload) { return; }
456     //if ($this->attributes = $backend->decodeData($this->payload)) {
457     if ($this->attributes = unserialize($this->payload)) {
458     $this->meta[decoded] = 1;
459     }
460     }
461    
462     function store($struct) {
463     $this->payload = serialize($struct);
464     $this->_saveProxy();
465     }
466    
467     }
468    
469     ?>

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