/[cvs]/nfo/php/libs/org.netfrag.glib/Data/Driver/Proxy.php
ViewVC logotype

Annotation of /nfo/php/libs/org.netfrag.glib/Data/Driver/Proxy.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations)
Sat Mar 1 04:56:38 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
Changes since 1.2: +158 -87 lines
new comment style for large blocks - stolen from phpHtmlLib
commit-log encapsulated into such a block
introduced some documentation
refactored todo (now also inside a stylish block)

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

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