/[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.1 - (hide annotations)
Sat Mar 1 20:17:15 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
renamed from ProxyDataSource.inc
replaced '_proxy' through '_handler' to better associate the ability to act as a generic dispatcher handler

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

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