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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Sat Mar 1 21:47:15 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
renamed from AbstractDataSource.inc

1 <?php
2 /**
3 * This file contains the GenericDataSource 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 GenericDataSource
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 GenericDataSource.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 GenericDataSource 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 * GenericDataSource 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 * GenericDataSource 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 GenericDataSource($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 GenericDataSource($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 GenericDataSource
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 GenericDataSource 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 GenericDataSource( &$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 //print Dumper($this->_query);
313 //exit;
314
315 // make up a command from metadata
316 // FIXME: abstract this some more (e.g. via a CommandMapper|Registry)
317 switch ($this->_query[metatype]) {
318 case 'data':
319 //$command = 'queryData';
320 $command = 'getObjects'; // FIXME!!!
321 $args = array();
322 switch ($this->_query[vartype]) {
323 case 'object':
324 if (!$this->_query[classname]) {
325 $msg = "_query[vartype] == 'object' requires _query[classname]";
326 user_error("GenericDataSource::do_query() - failed: " . $msg);
327 }
328 array_push($args, $this->_query[classname]);
329 break;
330 }
331 break;
332 case 'schema':
333 $command = 'querySchema';
334 break;
335 }
336
337 // trace
338 $this->debug(null, '<b>= = = = = = = = = = = = = = = = = = = = = =</b>');
339 $this->trace('build_handler_options', array(
340 "_locator" => $this->_locator,
341 "_query" => $this->_query,
342 "command" => '<b>' . $command . "</b>",
343 "args" => $args
344 ));
345
346 $this->_handler_options = array(
347 method => $command,
348 args => $args,
349 );
350
351 }
352
353 function fetch_result() {
354
355 $this->build_handler_options();
356 $method = $this->_handler_options[method];
357 $args = $this->_handler_options[args];
358
359 // pre-flight checks
360 if (!$method) {
361 $msg = "Remote command could not be resolved, please pass in or check configuration.";
362 user_error("GenericDataSource::do_query() - failed: " . $msg);
363 return;
364 }
365
366 // do remote call here and get result
367 // FIXME: handle synchronous/asynchronous mode here!!!
368 $this->do_handler_call($method, $args);
369 // TODO: ... = $this->poll_handler_result and $this->get_handler_result
370 $this->_result = $this->_handler->getAttributes();
371
372 // trace
373 if ($this->_debug[notice]) {
374 //print "_result = " . Dumper($this->_result);
375 print "_result - count = " . sizeof($this->_result) . "<br/>";
376 }
377
378 }
379
380
381 function do_query() {
382 //print "query!<br/>";
383 $this->fetch_result();
384 $this->handle_result();
385 }
386
387 function get_header() {
388 $this->fetch_result();
389 $this->read_labels_from_result();
390 return $this->get_labels();
391 }
392
393
394 function O_do_prequery() {
395 //print "prequery!<br/>";
396 // HACK!!!
397 // modify behaviour here: for now it is needed to call for the schem
398 // eventually modify here to get schema from some registry component (already locally available)
399 $this->fetch_result();
400 //print Dumper($this->_result);
401 //print Dumper($this->_result[0]);
402 //exit;
403
404 //$this->_get_header();
405 }
406
407
408 function O_get_header() {
409 //$this->do_prequery();
410 // FIXME: prevent multi-calls by base class
411 $this->fetch_result();
412 foreach($this->_result[0] as $key => $value) {
413 array_push($this->_data_keys, $key);
414 }
415
416 $this->set_schema($this->_result[0]);
417
418 //$this->_get_header();
419 //return $this->_data_keys;
420
421 }
422
423
424
425
426
427
428
429
430
431
432 /**
433 * This function gets the next data row
434 * from the query()
435 *
436 * @return array()
437 */
438 function O_get_next_data_row() {
439 return $this->_result->fetchRow(DB_FETCHMODE_ASSOC);
440 }
441
442 /**
443 * This function builds the limit
444 * clause portion of a DB query.
445 *
446 * @return string - the limit portion of
447 * the query.
448 */
449 function O_build_limit_clause($offset, $limit) {
450 if ($this->get_limit() != -1 ) {
451 if ($offset == '' || $offset == "none") {
452 $offset = 0;
453 }
454 switch(get_class($this->_db)) {
455 case "db_mysql":
456 $clause = " LIMIT $offset, $limit ";
457 break;
458 case "db_pgsql":
459 $clause = " LIMIT $limit, $offset ";
460 break;
461 default:
462 $clause = " LIMIT $offset, $limit ";
463 break;
464 }
465 return $clause;
466 } else {
467 return NULL;
468 }
469 }
470
471 /**
472 * find the number of rows to be returned
473 * from a query from a table and where clause
474 *
475 * @param string $table - the table to count from
476 * @param string $where_clause - a where clause
477 *
478 * @return int the # of rows
479 */
480 function O_count($tables, $where_clause='', $count_clause='*') {
481 $query = "select count(".$count_clause.") as COUNT from ".$tables." ".$where_clause;
482 $result = $this->_db->query($query);
483 if (DB::isError($this->_result)) {
484 $msg = $result->getMessage();
485 user_error("PEARSQLDataListSource::count() - query failed : ".$msg);
486 }
487 $value = $result->fetchRow(DB_FETCHMODE_ASSOC);
488 return ($value ? (int)$value["COUNT"] : NULL);
489 }
490
491 }
492
493 ?>

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