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

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