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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Sat Mar 1 03:10:40 2003 UTC (21 years, 6 months ago) by joko
Branch: MAIN
+ initial commit

1 <?php
2
3 /**
4 * This file contains the ProxyDataSource child class
5 * that uses the Data::Driver::Proxy object to talk to a remote rpc server.
6 *
7 * Data::Driver::Proxy uses a PEAR XML::RPC object to actually
8 * talk HTTP and serialize data chunks to and from XML,
9 * but adds some caching to this "process of fetching data from a remote side".
10 * It "proxies" arbitrary data chunks a) inside a native php4 session,
11 * b) by talking to a rdbms (single proxy-table) or c) [TODO] using PEAR::Cache.
12 *
13 * @author Andreas Motl <andreas.motl@ilo.de>
14 * @author Sebastian Utz <seut@tunemedia.de>
15 * @package phpHtmlLib
16 */
17
18 /**
19 * $Id$
20 *
21 * $Log$
22 *
23 */
24
25 /**
26 * This requires the MemoryDataSource base class
27 *
28 */
29 include_once($phphtmllib."/widgets/data_source/MemoryDataSource.inc");
30
31 /**
32 * Have to have PEAR and DB included
33 * the pear dir must be in the
34 * include path.
35 */
36 //require_once("PEAR.php"); // FIXME: what about PEAR::XML::RPC?
37 //require_once("DB.php");
38
39 /**
40 * This ProxyDataSource child class is *completely* independent
41 * of a specific storage implementation and intended to be a wrapper
42 * class on the way from phpHtmlLib to Xyz.
43 * ("Yyz" gets represented by Data::Storage by now.....)
44 *
45 * ProxyDataSource interacts with an intermediate "proxy" object
46 * (e.g. Data::Driver::Proxy) when doing queries.
47 * Don't mix this up with a persistent database handle which gets
48 * reused each and every time for different queries.
49 * Here *is* a new instance of Data::Driver::Proxy for *each* query.
50 *
51 * But the point is: Caching! The actual *data* isn't read redundant!
52 *
53 * Data::Driver::Proxy instantiates "handlers" below itself
54 * which act as encapsulated workers to actually do the stuff to do.
55 * It can cache data for "disconnected mode" using the
56 * php PEAR DB abstraction objects.
57 * One worker already implemented is Data::Driver::RPC::Remote, which
58 * talks to a RPC::XML server (todo: talk SOAP!) using PEAR::XML::RPC.
59 *
60 * How to use?
61 *
62 * Pass an array holding "locator metadata" to the constructor.
63 * ProxyDataSource takes care of the rest.
64 *
65 * Pass an array to the constructor: (e.g.)
66 *
67 * 1. doing rpc-calls....
68 * $locator = array(
69 * type => 'rpc',
70 * metadata => array( Host => 'localhost', Port => '8765' ),
71 * );
72 * $source = new ProxyDataSource($locator);
73 * $this->set_data_source( &$source );
74 *
75 * 2. [proposal] common datahandles....
76 * $locator = array(
77 * type => 'mysql',
78 * dsn => 'known dsn markup',
79 * );
80 * $source = new ProxyDataSource($locator);
81 * $this->set_data_source( &$source );
82 *
83 * @author Andreas Motl <andreas.motl@ilo.de>
84 * @author Sebastian Utz <seut@tunemedia.de>
85 * @package phpHtmlLib
86 */
87
88 /**
89 * Todo:
90 *
91 * o mungle this to be able to be wrapped around phpHtmlLib's own storage-handles
92 * o implement another Data::Driver::Proxy container
93 *
94 */
95
96 class ProxyDataSource extends MemoryDataSource {
97
98 /**
99 * This var holds the locator metadata hash
100 * that is used to feed metadata to a per-query-instance
101 * of a Data::Driver::Proxy object.
102 */
103 var $_locator = NULL;
104
105 /**
106 * This var holds the query hash
107 * that is used to feed as query to a per-query-instance
108 * of a Data::Driver::Proxy object.
109 */
110 var $_query = NULL;
111
112
113 /**
114 * This var holds the Proxy object
115 * that is used to do the work.
116 * It acts as a dispatcher combining result caching.
117 * It is assumed that this provides 4 methods:
118 * queryData() - execute a query against a data storage
119 * querySchema() - execute a query against underlying storage metadata
120 * sendCommand() - send a command against an arbitrary execution engine
121 */
122 var $_proxy = NULL;
123
124 /**
125 * this holds the query result from the
126 * Data::Driver::Proxy->queryXyz() call
127 *
128 */
129 var $_result = NULL;
130
131
132 /**
133 * The constructor is used to pass in the
134 * locator metadata hash.
135 *
136 * @param LocatorMetadataHash array - layout: array( type => '', metadata => '', dsn => '' )
137 * @param Query array - layout: array( type => '', metadata => '', dsn => '' )
138 */
139 function ProxyDataSource( &$locator, $query ) {
140 $this->set_locator( $locator );
141 $this->set_query( $query );
142 }
143
144 /**
145 * Set the locator metadata hash we will feed *partly*
146 * to an encapsulated Data::Driver::Proxy instance.
147 *
148 * @param LocatorMetadataHash array -
149 *
150 */
151 function set_locator( &$locator ) {
152 $this->_locator = &$locator;
153 }
154
155 /**
156 * Set the query metadata hash we will feed *completely*
157 * to an encapsulated Data::Driver::Proxy instance.
158 *
159 * @param QueryDeclaration array -
160 *
161 */
162 function set_query( $query ) {
163 $this->_query = $query;
164 }
165
166 /**
167 * Directly inject a Data::Driver::Proxy instance to use.
168 *
169 * @param Data::Driver::Proxy object - &$proxy
170 *
171 */
172 function set_proxy( &$proxy ) {
173 $this->_proxy = &$proxy;
174 }
175
176 /**
177 * Issue remote/proxy call
178 * Stolen from Application_AbstractBackend::_remote_method (RefactoringProposal?)
179 * Tweaked a bit: proxy package now taken from $this->_proxy_name
180 *
181 * Create a new instance of a proxy and store it for later reuse.
182 * Read the locator metadata hash and create
183 * the proxy handler instance using passed-in name.
184 *
185 * @param string - $proxy_name (namespaced classname - perl syntax - e.g.: Data::Driver::Proxy)
186 *
187 */
188 function call_proxy_method() {
189
190
191 // 1. read args
192
193 $arg_list = func_get_args();
194 $command = array_shift($arg_list);
195 $cache_key = join("-", array(session_id(), $command, join('_', $arg_list) ));
196 //print "cache_key: $cache_key<br>";
197
198 // FIXME: what if arg_list still contains more elements after doing this?
199 $query = array_shift($arg_list);
200
201
202 // 2. prepare proxy-options
203
204 // read from locator metadata
205 $proxy_name = $this->_locator[metadata][package];
206 $rpcinfo = array( Host => $this->_locator[metadata][Host], Port => $this->_locator[metadata][Port] );
207
208 // FIXME! implement this into Data::Driver::RPC::Remote!
209 //$rpcinfo[to_latin] = 1;
210
211 // FIXME! patch query
212 if (sizeof($query) == 1) {
213 $query = $query[0];
214 }
215
216 // -------------------- clone this & modify ----------
217 $proxy = mkObject($proxy_name, $cache_key, array( key => 1, command => $command, query => $query, remote => 1, rpcinfo => $rpcinfo, cache => array( db => 0, session => 1 ) ) );
218 $this->set_proxy( $proxy );
219 //$result = $resultHandle->getAttributes();
220 //return $result;
221 //$this->_result = $resultHandle->getAttributes();
222 //$this->_result = $this->_proxy->getAttributes();
223 // -------------------- clone this & modify ----------
224
225 }
226
227 function O_do_query() {
228 $this->_result = $this->_db->query($this->_query);
229 if (DB::isError($this->_result)) {
230 $msg = $this->_result->getMessage();
231 user_error("PEARSQLDataListSource::do_query() - query failed : ".$msg);
232 }
233 }
234
235 function call_proxy() {
236
237 // make up a command from metadata
238 // FIXME: abstract this some more (e.g. via a CommandMapper|Registry)
239 switch ($this->_query[metatype]) {
240 case 'data':
241 //$command = 'queryData';
242 $command = 'getObjects'; // FIXME!!!
243 $args = array();
244 switch ($this->_query[vartype]) {
245 case 'object':
246 if (!$this->_query[classname]) {
247 $msg = "_query[vartype] == 'object' requires _query[classname]";
248 user_error("ProxyDataSource::do_query() - failed: " . $msg);
249 }
250 array_push($args, $this->_query[classname]);
251 break;
252 }
253 break;
254 case 'schema':
255 $command = 'querySchema';
256 break;
257 }
258
259 // trace
260 if ($this->trace) {
261 print "ProxyDataSource->do_query()<br/>";
262 print "_locator = " . Dumper($this->_locator);
263 print "_query = " . Dumper($this->_query);
264 print "<b>\$command = " . $command . "</b><br/>";
265 print "<b>\$args = " . Dumper($args) . "</b><br/>";
266 }
267
268 // pre-flight checks
269 if (!$command) {
270 $msg = "Remote command could not be resolved, please pass in or check configuration.";
271 user_error("ProxyDataSource::do_query() - failed: " . $msg);
272 return;
273 }
274
275 // do remote call here and get result
276 // FIXME: handle synchronous/asynchronous mode here!!!
277 $this->call_proxy_method($command, $args);
278 // TODO: ... = $this->poll_proxy_result and $this->get_proxy_result
279 $this->_result = $this->_proxy->getAttributes();
280
281 // trace
282 //print "_result = " . Dumper($this->_result);
283 print "_result - count = " . sizeof($this->_result) . "<br/>";
284
285 // pass data to MemoryDataSource
286
287 // V1 - doesn't work!
288 //$this->_data_list = $this->_result;
289
290 // V2 - ???
291 //$this->MemoryDataSource();
292
293 // V3 - copy & paste
294 /*
295 foreach ($this->_result as $value) {
296 print Dumper($value);
297 if ($this->add_data_row($value)) {
298 $count++;
299 }
300 }
301 $this->set_total_rows( $count );
302 $this->sort();
303 */
304
305 }
306
307
308
309 function O_do_prequery() {
310 //print "prequery!<br/>";
311 // HACK!!!
312 // modify behaviour here: for now it is needed to call for the schem
313 // eventually modify here to get schema from some registry component (already locally available)
314 $this->call_proxy();
315 //print Dumper($this->_result);
316 //print Dumper($this->_result[0]);
317 //exit;
318
319 //$this->_get_header();
320 }
321
322 function do_query() {
323 //print "query!<br/>";
324 $this->handle_result();
325 }
326
327 function _get_header() {
328 //$this->do_prequery();
329 // FIXME: prevent multi-calls by base class
330 $this->call_proxy();
331 foreach($this->_result[0] as $key => $value) {
332 array_push($this->_data_keys, $key);
333 }
334
335 $this->set_schema($this->_result[0]);
336
337 //$this->_get_header();
338 //return $this->_data_keys;
339
340 }
341
342
343 /**
344 * This function gets the next data row
345 * from the query()
346 *
347 * @return array()
348 */
349 function O_get_next_data_row() {
350 return $this->_result->fetchRow(DB_FETCHMODE_ASSOC);
351 }
352
353 /**
354 * This function builds the limit
355 * clause portion of a DB query.
356 *
357 * @return string - the limit portion of
358 * the query.
359 */
360 function O_build_limit_clause($offset, $limit) {
361 if ($this->get_limit() != -1 ) {
362 if ($offset == '' || $offset == "none") {
363 $offset = 0;
364 }
365 switch(get_class($this->_db)) {
366 case "db_mysql":
367 $clause = " LIMIT $offset, $limit ";
368 break;
369 case "db_pgsql":
370 $clause = " LIMIT $limit, $offset ";
371 break;
372 default:
373 $clause = " LIMIT $offset, $limit ";
374 break;
375 }
376 return $clause;
377 } else {
378 return NULL;
379 }
380 }
381
382 /**
383 * find the number of rows to be returned
384 * from a query from a table and where clause
385 *
386 * @param string $table - the table to count from
387 * @param string $where_clause - a where clause
388 *
389 * @return int the # of rows
390 */
391 function O_count($tables, $where_clause='', $count_clause='*') {
392 $query = "select count(".$count_clause.") as COUNT from ".$tables." ".$where_clause;
393 $result = $this->_db->query($query);
394 if (DB::isError($this->_result)) {
395 $msg = $result->getMessage();
396 user_error("PEARSQLDataListSource::count() - query failed : ".$msg);
397 }
398 $value = $result->fetchRow(DB_FETCHMODE_ASSOC);
399 return ($value ? (int)$value["COUNT"] : NULL);
400 }
401
402 }
403
404 ?>

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