/[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.4 - (hide annotations)
Wed Mar 5 16:32:19 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.3: +28 -18 lines
updated docu (phpDocumentor testing....)

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

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