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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (show 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 <?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
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
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 }
183
184 function _init_meta_options( $objectId="", $options = array() ) {
185 $this->meta = $options;
186
187 if ($objectId) {
188 $this->objectId = $objectId;
189
190 // set default load mechanism
191 if ( $this->meta[remote] && ((!$this->meta[oid] && !$this->meta[guid]) || ($this->meta[oid] && $this->meta[guid])) && (!$this->meta[key]) ) {
192 $this->meta[oid] = 1;
193 }
194
195 }
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 $this->load();
212 //$this->_saveProxy();
213 }
214 }
215
216
217 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
290 // trace
291 //print Dumper($this);
292
293 // debug
294 logp(get_class($this) . "->_loadState()");
295
296 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
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 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
336 // FIXME!
337 if (!$this->meta[cache][db]) { return; }
338
339 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 // trace
355 //print Dumper($this->meta);
356
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 /*
392 if (!$this->meta[query]) {
393 logp(get_class($this) . "->_loadRemote: argument 'key' requires 'query'", PEAR_LOG_WARNING);
394 return;
395 }
396 */
397 $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