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

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