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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide 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 joko 1.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 joko 1.2 * $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 joko 1.1 *
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