/[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.6 - (show annotations)
Wed Mar 5 17:28:43 2003 UTC (21 years, 5 months ago) by joko
Branch: MAIN
Changes since 1.5: +5 -1 lines
updated docu (phpDocumentor testing....)

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

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