/[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.2 - (show annotations)
Wed Mar 5 12:14:02 2003 UTC (21 years, 4 months ago) by joko
Branch: MAIN
Changes since 1.1: +16 -4 lines
renamed method
constructor argument expansion

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

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