/[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.2 - (hide annotations)
Wed Mar 5 12:14:02 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
Changes since 1.1: +16 -4 lines
renamed method
constructor argument expansion

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

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