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

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