/[cvs]/nfo/php/libs/org.netfrag.glib/DesignPattern/RemoteProxy.php
ViewVC logotype

Contents of /nfo/php/libs/org.netfrag.glib/DesignPattern/RemoteProxy.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Mon Mar 3 22:06:46 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
refactored from Data::Driver::Proxy

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

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