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

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