/[cvs]/nfo/php/libs/com.newsblob.phphtmllib/widgets/data_source/AbstractDataSource.inc
ViewVC logotype

Contents of /nfo/php/libs/com.newsblob.phphtmllib/widgets/data_source/AbstractDataSource.inc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations)
Sat Mar 1 21:48:28 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +6 -2 lines
FILE REMOVED
renamed to GenericDataSource.inc

1 <?php
2 /**
3 * This file contains the AbstractDataSource child class
4 * that may use arbitrary code modules as database handlers.
5 * It's aims are to get together:
6 * o phpHtmlLibs "source-handlers"
7 * o PEAR's database handlers
8 * o custom ones (e.g. Data::Driver::Proxy object, which talks to a remote rpc server)
9 *
10 * @author Andreas Motl <andreas.motl@ilo.de>
11 * @package phpHtmlLib
12 * @module ProxyDataSource
13 *
14 */
15
16 /**
17 * $Id: AbstractDataSource.inc,v 1.1 2003/03/01 20:17:15 joko Exp $
18 *
19 * $Log: AbstractDataSource.inc,v $
20 * Revision 1.1 2003/03/01 20:17:15 joko
21 * renamed from ProxyDataSource.inc
22 * replaced '_proxy' through '_handler' to better associate the ability to act as a generic dispatcher handler
23 *
24 * Revision 1.3 2003/03/01 15:36:11 joko
25 * + debugging
26 * + renamed some methods regarding new proposal (build_handler_options, fetch_result, etc.)
27 *
28 * Revision 1.2 2003/03/01 04:50:27 joko
29 * encapsulated all output into tracing mode
30 * disabled tracing
31 *
32 * Revision 1.1 2003/03/01 03:10:40 joko
33 * + initial commit
34 *
35 *
36 */
37
38 /**
39 * This requires the MemoryDataSource base class
40 *
41 */
42 // V1: compile-time-include, stable since years ;-)
43 include_once($phphtmllib."/widgets/data_source/MemoryDataSource.inc");
44 // V2: runtime-load proposal, more flexible
45 // loadModule('MemoryDataSource', 'inc'); // doesn't work (would do if basepath of module is in libpath)
46 // loadModule($phphtmllib . '::widgets::data_source::MemoryDataSource', 'inc'); // works (by accident)
47 // loadModule($phphtmllib . "/widgets/data_source/MemoryDataSource", "inc"); // works (should be stable)
48 // loadModule($phphtmllib . "/widgets/data_source/MemoryDataSource.inc", null); // works (should be stable)
49
50
51
52 /**
53 * Have to have PEAR and DB included
54 * the pear dir must be in the
55 * include path.
56 */
57 // require_once("PEAR.php"); // FIXME: what about PEAR::XML::RPC?
58 // require_once("DB.php");
59
60 /**
61 * This ProxyDataSource child class is *completely* independent
62 * of a specific storage implementation and intended to be a wrapper
63 * class on the way from phpHtmlLib to Xyz.
64 * ("Yyz" gets represented by Data::Storage by now.....)
65 *
66 * ProxyDataSource interacts with an intermediate "proxy" object
67 * (e.g. Data::Driver::Proxy) when doing queries.
68 * Don't mix this up with a persistent database handle which gets
69 * reused each and every time for different queries.
70 * Here *is* a new instance of Data::Driver::Proxy for *each* query.
71 *
72 * But the point is: Caching! The actual *data* isn't read redundant!
73 *
74 *
75 * !!!!!! refactor this to Data::Driver::Proxy !!!!!! <-----------------
76 *
77 * Data::Driver::Proxy instantiates "handlers" below itself
78 * which act as encapsulated workers to actually do the stuff to do.
79 * It can cache data for "disconnected mode" using the
80 * php PEAR DB abstraction objects.
81 * One worker already implemented is Data::Driver::RPC::Remote, which
82 * talks to a RPC::XML server (todo: talk SOAP!) using PEAR::XML::RPC.
83 *
84 * --- refactored here, but: redundant somehow ---
85 * Data::Driver::Proxy uses a PEAR XML::RPC object to actually
86 * talk HTTP and serialize data chunks to and from XML,
87 * but adds some caching to this "process of fetching data from a remote side".
88 * It "proxies" arbitrary data chunks a) inside a native php4 session,
89 * b) by talking to a rdbms (single proxy-table) or c) [TODO] using PEAR::Cache.
90 * --- refactored here, but: redundant somehow ---
91 *
92 * !!!!!! refactor this to Data::Driver::Proxy !!!!!! <-----------------
93 *
94 *
95 * How to use?
96 *
97 * Pass an array holding "locator metadata" to the constructor.
98 * ProxyDataSource takes care of the rest.
99 *
100 * Pass an array to the constructor: (e.g.)
101 *
102 * 1. doing rpc-calls....
103 * $locator = array(
104 * type => 'rpc',
105 * metadata => array( Host => 'localhost', Port => '8765' ),
106 * );
107 * $source = new ProxyDataSource($locator);
108 * $this->set_data_source( &$source );
109 *
110 * 2. [proposal] common datahandles....
111 * $locator = array(
112 * type => 'mysql',
113 * dsn => 'known dsn markup',
114 * );
115 * $source = new ProxyDataSource($locator);
116 * $this->set_data_source( &$source );
117 *
118 * @author Andreas Motl <andreas.motl@ilo.de>
119 * @author Sebastian Utz <seut@tunemedia.de>
120 * @copyright (c) 2003 - All Rights reserved.
121 * @license GNU LGPL (GNU Lesser General Public License)
122 *
123 * @author-url http://www.netfrag.org/~joko/
124 * @author-url http://www.netfrag.org/~jonen/
125 * @license-url http://www.gnu.org/licenses/lgpl.txt
126 *
127 * @package phpHtmlLib
128 * @module ProxyDataSource
129 *
130 */
131
132 /**
133 * Todo:
134 *
135 * o mungle this to be able to be wrapped around phpHtmlLib's own storage-handles
136 * o implement another Data::Driver::Proxy container
137 *
138 */
139
140
141 class AbstractDataSource extends MemoryDataSource {
142
143 /**
144 * This var holds the locator metadata hash
145 * that is used to feed metadata to a per-query-instance
146 * of a Data::Driver::Proxy object.
147 *
148 */
149 var $_locator = NULL;
150
151
152 /**
153 * This var holds the query hash
154 * that is used to feed as query to a per-query-instance
155 * of a Data::Driver::Proxy object.
156 *
157 */
158 var $_query = NULL;
159
160
161 /**
162 * This var holds the Handler object
163 * that is used to do the work.
164 * It acts as a dispatcher combining result caching.
165 * It is assumed that this provides 4 methods:
166 * queryData() - execute a query against a data storage
167 * querySchema() - execute a query against underlying storage metadata
168 * sendCommand() - send a command against an arbitrary execution engine
169 * ... or others! (these are just proposals for convenience)
170 *
171 */
172 var $_handler = NULL;
173
174
175 /**
176 * This var holds options fed to the Proxy object
177 * These are built from locator metadata (_locator) and query arguments (_query)
178 * It's a simple structured hash:
179 * $proxy_options = array(
180 * method => '<remote-method-name>',
181 * args => array('list', 'of', 'arguments')
182 * );
183 *
184 */
185 var $_handler_options = NULL;
186
187
188 /**
189 * this holds the query result from the
190 * Data::Driver::Proxy->queryXyz() call
191 *
192 */
193 var $_result = NULL;
194
195 /**
196 * This holds some information about the tracing level.
197 *
198 */
199 var $_debug = array(
200 notice => 0,
201 trace => 0,
202 payload => 0,
203 );
204
205
206 /**
207 * The constructor is used to pass in the
208 * locator metadata hash.
209 *
210 * @param LocatorMetadataHash array - layout: array( type => '', metadata => '', dsn => '' )
211 * @param Query array - layout: array( type => '', metadata => '', dsn => '' )
212 */
213 function ProxyDataSource( &$locator, $query ) {
214
215 $this->set_locator( $locator );
216 $this->set_query( $query );
217 }
218
219 /**
220 * Set the locator metadata hash we will feed *partly*
221 * to an encapsulated Data::Driver::Proxy instance.
222 *
223 * @param LocatorMetadataHash array -
224 *
225 */
226 function set_locator( &$locator ) {
227 $this->_locator = &$locator;
228 }
229
230 /**
231 * Set the query metadata hash we will feed *completely*
232 * to an encapsulated Data::Driver::Proxy instance.
233 *
234 * @param QueryDeclaration array -
235 *
236 */
237 function set_query( $query ) {
238 $this->_query = $query;
239 }
240
241 /**
242 * Directly inject a Data::Driver::Proxy instance to use.
243 *
244 * @param Data::Driver::Proxy object - &$proxy
245 *
246 */
247 function set_handler( &$proxy ) {
248 $this->_handler = &$proxy;
249 }
250
251 /**
252 * Issue remote/proxy call
253 * Stolen from Application_AbstractBackend::_remote_method (RefactoringProposal?)
254 * Tweaked a bit: proxy package now taken from $this->_handler_name
255 *
256 * Create a new instance of a proxy and store it for later reuse.
257 * Read the locator metadata hash and create
258 * the proxy handler instance using passed-in name.
259 *
260 * @param string - $proxy_name (namespaced classname - perl syntax - e.g.: Data::Driver::Proxy)
261 *
262 */
263 function do_handler_call() {
264
265
266 // 1. read args
267
268 $arg_list = func_get_args();
269 $command = array_shift($arg_list);
270 $cache_key = join("-", array(session_id(), $command, join('_', $arg_list) ));
271 //print "cache_key: $cache_key<br>";
272
273 // FIXME: what if arg_list still contains more elements after doing this?
274 $query = array_shift($arg_list);
275
276
277 // 2. prepare proxy-options
278
279 // read from locator metadata
280 $proxy_name = $this->_locator[metadata][package];
281 $rpcinfo = array( Host => $this->_locator[metadata][Host], Port => $this->_locator[metadata][Port] );
282
283 // FIXME! implement this into Data::Driver::RPC::Remote!
284 //$rpcinfo[to_latin] = 1;
285
286 // FIXME! patch query
287 if (sizeof($query) == 1) {
288 $query = $query[0];
289 }
290
291 // -------------------- clone this & modify ----------
292 $proxy = mkObject($proxy_name, $cache_key, array( key => 1, command => $command, query => $query, remote => 1, rpcinfo => $rpcinfo, cache => array( db => 0, session => 1 ) ) );
293 $this->set_handler( $proxy );
294 //$result = $resultHandle->getAttributes();
295 //return $result;
296 //$this->_result = $resultHandle->getAttributes();
297 //$this->_result = $this->_handler->getAttributes();
298 // -------------------- clone this & modify ----------
299
300 }
301
302 function O_do_query() {
303 $this->_result = $this->_db->query($this->_query);
304 if (DB::isError($this->_result)) {
305 $msg = $this->_result->getMessage();
306 user_error("PEARSQLDataListSource::do_query() - query failed : ".$msg);
307 }
308 }
309
310 function build_handler_options() {
311
312 // make up a command from metadata
313 // FIXME: abstract this some more (e.g. via a CommandMapper|Registry)
314 switch ($this->_query[metatype]) {
315 case 'data':
316 //$command = 'queryData';
317 $command = 'getObjects'; // FIXME!!!
318 $args = array();
319 switch ($this->_query[vartype]) {
320 case 'object':
321 if (!$this->_query[classname]) {
322 $msg = "_query[vartype] == 'object' requires _query[classname]";
323 user_error("ProxyDataSource::do_query() - failed: " . $msg);
324 }
325 array_push($args, $this->_query[classname]);
326 break;
327 }
328 break;
329 case 'schema':
330 $command = 'querySchema';
331 break;
332 }
333
334 // trace
335 $this->debug(null, '<b>= = = = = = = = = = = = = = = = = = = = = =</b>');
336 $this->trace('build_handler_options', array(
337 "_locator" => $this->_locator,
338 "_query" => $this->_query,
339 "command" => '<b>' . $command . "</b>",
340 "args" => $args
341 ));
342
343 $this->_handler_options = array(
344 method => $command,
345 args => $args,
346 );
347
348 }
349
350 function fetch_result() {
351
352 $this->build_handler_options();
353 $method = $this->_handler_options[method];
354 $args = $this->_handler_options[args];
355
356 // pre-flight checks
357 if (!$method) {
358 $msg = "Remote command could not be resolved, please pass in or check configuration.";
359 user_error("ProxyDataSource::do_query() - failed: " . $msg);
360 return;
361 }
362
363 // do remote call here and get result
364 // FIXME: handle synchronous/asynchronous mode here!!!
365 $this->do_handler_call($method, $args);
366 // TODO: ... = $this->poll_handler_result and $this->get_handler_result
367 $this->_result = $this->_handler->getAttributes();
368
369 // trace
370 if ($this->_debug[notice]) {
371 //print "_result = " . Dumper($this->_result);
372 print "_result - count = " . sizeof($this->_result) . "<br/>";
373 }
374
375 }
376
377
378 function do_query() {
379 //print "query!<br/>";
380 $this->fetch_result();
381 $this->handle_result();
382 }
383
384 function get_header() {
385 $this->fetch_result();
386 $this->read_labels_from_result();
387 return $this->get_labels();
388 }
389
390
391 function O_do_prequery() {
392 //print "prequery!<br/>";
393 // HACK!!!
394 // modify behaviour here: for now it is needed to call for the schem
395 // eventually modify here to get schema from some registry component (already locally available)
396 $this->fetch_result();
397 //print Dumper($this->_result);
398 //print Dumper($this->_result[0]);
399 //exit;
400
401 //$this->_get_header();
402 }
403
404
405 function O_get_header() {
406 //$this->do_prequery();
407 // FIXME: prevent multi-calls by base class
408 $this->fetch_result();
409 foreach($this->_result[0] as $key => $value) {
410 array_push($this->_data_keys, $key);
411 }
412
413 $this->set_schema($this->_result[0]);
414
415 //$this->_get_header();
416 //return $this->_data_keys;
417
418 }
419
420
421
422
423
424
425
426
427
428
429 /**
430 * This function gets the next data row
431 * from the query()
432 *
433 * @return array()
434 */
435 function O_get_next_data_row() {
436 return $this->_result->fetchRow(DB_FETCHMODE_ASSOC);
437 }
438
439 /**
440 * This function builds the limit
441 * clause portion of a DB query.
442 *
443 * @return string - the limit portion of
444 * the query.
445 */
446 function O_build_limit_clause($offset, $limit) {
447 if ($this->get_limit() != -1 ) {
448 if ($offset == '' || $offset == "none") {
449 $offset = 0;
450 }
451 switch(get_class($this->_db)) {
452 case "db_mysql":
453 $clause = " LIMIT $offset, $limit ";
454 break;
455 case "db_pgsql":
456 $clause = " LIMIT $limit, $offset ";
457 break;
458 default:
459 $clause = " LIMIT $offset, $limit ";
460 break;
461 }
462 return $clause;
463 } else {
464 return NULL;
465 }
466 }
467
468 /**
469 * find the number of rows to be returned
470 * from a query from a table and where clause
471 *
472 * @param string $table - the table to count from
473 * @param string $where_clause - a where clause
474 *
475 * @return int the # of rows
476 */
477 function O_count($tables, $where_clause='', $count_clause='*') {
478 $query = "select count(".$count_clause.") as COUNT from ".$tables." ".$where_clause;
479 $result = $this->_db->query($query);
480 if (DB::isError($this->_result)) {
481 $msg = $result->getMessage();
482 user_error("PEARSQLDataListSource::count() - query failed : ".$msg);
483 }
484 $value = $result->fetchRow(DB_FETCHMODE_ASSOC);
485 return ($value ? (int)$value["COUNT"] : NULL);
486 }
487
488 }
489
490 ?>

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