BAOBAB
a_co_basalt_plugin.class.php
Go to the documentation of this file.
1 <?php
2 /***************************************************************************************************************************/
27 defined( 'LGV_BASALT_CATCHER' ) or die ( 'Cannot Execute Directly' ); // Makes sure that this file is in the correct context.
28 
29 /****************************************************************************************************************************/
32 abstract class A_CO_Basalt_Plugin {
33  static protected $_s_cached_list = NULL;
34 
35  /***********************/
41  static protected function _get_handler( $in_classname
42  ) {
43  // First time through, we build up a cached list of handlers.
44  if (!isset(self::$_s_cached_list) || !is_array(self::$_s_cached_list) || !count(self::$_s_cached_list)) {
45  self::$_s_cached_list = [];
46  $plugin_dirs = CO_Config::plugin_dirs();
47 
48  foreach ($plugin_dirs as $plugin_dir) {
49  if (isset($plugin_dir) && is_dir($plugin_dir)) {
50  $plugin_name = basename($plugin_dir);
51  $plugin_classname = 'CO_'.$plugin_name.'_Basalt_Plugin';
52  $plugin_filename = strtolower($plugin_classname).'.class.php';
53  $plugin_file = $plugin_dir.'/'.$plugin_filename;
54  include_once($plugin_file);
55  $class_list = $plugin_classname::classes_managed();
56  self::$_s_cached_list[$plugin_classname] = $class_list;
57  }
58  }
59  }
60 
61  foreach (self::$_s_cached_list as $plugin_name => $class_list) {
62  if (in_array($in_classname, $class_list)) {
63  $plugin_name = substr($plugin_name, 3, -14);
64  return $plugin_name;
65  }
66  }
67 
68  return NULL;
69  }
70 
71  /***********************/
75  protected static function _server_url() {
76  $port = intval ( $_SERVER['SERVER_PORT'] );
77 
78  // IIS puts "off" in the HTTPS field, so we need to test for that.
79  $https = (isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS'] && (($_SERVER['HTTPS'] !== 'off') || ($port == 443)))) ? true : false;
80 
81  $url_path = $_SERVER['SERVER_NAME'];
82 
83  // See if we need to add an explicit port to the URI.
84  if (!$https && ($port != 80)) {
85  $url_path .= ":$port";
86  } elseif ($https && ($port != 443)) {
87  $url_path .= ":$port";
88  }
89 
90  return 'http'.($https ? 's' : '').'://'.$url_path.$_SERVER['SCRIPT_NAME'];
91  }
92 
93  /***********************/
97  protected static function _array2xml( $in_array
98  ) {
99  $output = '';
100  $index = 0;
101 
102  foreach ($in_array as $name => $value) {
103  $plurality = is_int($name);
104  $name = $plurality ? 'value' : htmlspecialchars(trim($name));
105 
106  if ($value) {
107  if ($plurality) {
108  $output .= '<'.$name.' sequence_index="'.strval ( $index++ ).'">';
109  } else {
110  $output .= '<'.$name.'>';
111  }
112 
113  if (is_array($value)) {
114  $output .= self::_array2xml($value);
115  } else {
116  $output .= htmlspecialchars(strval($value));
117  }
118 
119  $output .= '</'.$name.'>';
120  }
121  }
122 
123  return $output;
124  }
125 
126  /***********************/
132  protected function _get_short_description( $in_object
133  ) {
134  $ret = Array('id' => $in_object->id());
135 
136  $name = $in_object->name;
137 
138  if (isset($name) && trim($name)) {
139  $ret ['name'] = $name;
140  }
141 
142  $lang = $in_object->get_lang();
143 
144  if (isset($lang) && trim($lang)) {
145  $ret ['lang'] = $lang;
146  }
147 
148  // Just to make sure that we're a valid long/lat object
149  if (method_exists($in_object, 'longitude')) {
150  $raw_lat = $in_object->raw_latitude();
151  $raw_lng = $in_object->raw_longitude();
152 
153  $latitude = $raw_lat ? $raw_lat : $in_object->latitude();
154  $longitude = $raw_lng ? : $in_object->longitude();
155 
156  if (isset($longitude) && is_float($longitude) && isset($latitude) && is_float($latitude)) {
157  $ret['coords'] = sprintf("%f,%f", $latitude, $longitude);
158  }
159 
160  if (isset($in_object->distance)) {
161  $ret['distance_in_km'] = floatval($in_object->distance);
162  }
163  }
164 
165  return $ret;
166  }
167 
168  /***********************/
174  protected function _get_long_description( $in_object,
175  $in_show_parents = false
176  ) {
177  $ret = $this->_get_short_description($in_object);
178 
179  // We only return tokens that we already know about. It's entirely possible for a record to have read or write token that is not in our set.
180  $my_ids = $in_object->get_access_object()->get_security_ids();
181  $read_item = intval($in_object->read_security_id);
182  $write_item = intval($in_object->write_security_id);
183 
184  // Checking for the availability of the Security DB is a quick login check. If not logged in, the DB will not be available.
185  if ((((2 > $read_item) || $in_object->get_access_object()->god_mode() || in_array($read_item, $my_ids)) && count($my_ids)) && $in_object->get_access_object()->security_db_available()) {
186  $ret['read_token'] = $read_item;
187  }
188 
189  if (((2 > $read_item) || $in_object->get_access_object()->god_mode() || in_array($write_item, $my_ids) && count($my_ids)) && $in_object->get_access_object()->security_db_available()) {
190  $ret['write_token'] = $write_item;
191  }
192 
193  if (isset($in_object->last_access)) {
194  $ret['last_access'] = date('Y-m-d H:i:s', $in_object->last_access);
195  }
196 
197  if ($in_object->user_can_write()) {
198  $ret['writeable'] = true;
199  }
200 
201  if (method_exists($in_object, 'owner_id')) { // Cheap test to figure out if we can look at these things.
202  if (0 < intval($in_object->owner_id())) {
203  $ret['owner_id'] = intval($in_object->owner_id());
204  }
205  }
206 
207  if (method_exists($in_object, 'longitude') && isset($ret['coords'])) { // Cheap test to figure out if we can look at these things.
208  // We do this little dance, because we want to make sure that our internal long/lat match the ones assigned to coords. If we ask again, we'll get different results (if fuzzy). Otherwise, it's just a wee bit faster.
209  $coords = array_map('floatval', explode(',', $ret['coords']));
210  $latitude = $coords[0];
211  $longitude = $coords[1];
212 
213  if (isset($longitude) && is_float($longitude) && isset($latitude) && is_float($latitude)) {
214  $ret['latitude'] = floatval($latitude);
215  $ret['longitude'] = floatval($longitude);
216  }
217 
218  if ($in_object->is_fuzzy()) {
219  $ret['fuzzy'] = true;
220 
221  $cansee = intval($in_object->can_see_through_the_fuzz());
222 
223  if ($cansee) {
224  $ret['can_see_through_the_fuzz'] = $cansee;
225  }
226 
227  // If this is a fuzzy location, but the logged-in user can see "the real," we show it to them.
228  if ($in_object->i_can_see_clearly_now()) {
229  $ret['raw_latitude'] = floatval($in_object->raw_latitude());
230  $ret['raw_longitude'] = floatval($in_object->raw_longitude());
231  $ret['fuzz_factor'] = $in_object->fuzz_factor();
232  }
233  }
234  }
235 
236  if (method_exists($in_object, 'children')) {
237  $child_objects = $this->_get_child_ids($in_object);
238  if (0 < count($child_objects)) {
239  $ret['children'] = $this->_get_child_handler_data($in_object);
240  }
241  }
242 
243  if ($in_show_parents && method_exists($in_object, 'who_are_my_parents')) {
244  $parent_objects = $in_object->who_are_my_parents();
245  if (isset($parent_objects) && is_array($parent_objects) && count($parent_objects)) {
246  foreach ($parent_objects as $instance) {
247  $class_name = get_class($instance);
248 
249  if ($class_name) {
250  $handler = self::_get_handler($class_name);
251  $ret['parents'][$handler][] = $instance->id();
252  }
253  }
254  }
255  }
256 
257  if (method_exists($in_object, 'get_payload')) {
258  $payload = $in_object->get_payload();
259 
260  if ($payload) {
261  $temp_file = tempnam(sys_get_temp_dir(), 'RVP');
262  file_put_contents($temp_file , $payload);
263  $finfo = finfo_open(FILEINFO_MIME_TYPE);
264  $content_type = finfo_file($finfo, $temp_file);
265  $ret['payload_type'] = $content_type.';base64';
266  $ret['payload'] = base64_encode($payload);
267  }
268  }
269 
270  return $ret;
271  }
272 
273  /***********************/
279  protected function _get_xml_header() {
280  $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
281  $xsd_uri = self::_server_url().'/xsd/'.$this->plugin_name();
282  $ret .= '<'.$this->plugin_name()." xsi:schemaLocation=\"".self::_server_url()." $xsd_uri\" xmlns=\"".self::_server_url()."\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">";
283 
284  return $ret;
285  }
286 
287  /***********************/
293  protected function _get_xsd_header() {
294  $ret = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
295  $xsd_uri = self::_server_url().'/xsd/'.$this->plugin_name();
296  $ret .= "<xs:schema xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:b='".self::_server_url()."' elementFormDefault='qualified' targetNamespace='".self::_server_url()."'>";
297 
298  return $ret;
299  }
300 
301  /***********************/
307  protected function _process_xsd( $in_schema_file_path
308  ) {
309  $ret = '';
310 
311  $schema_file = file_get_contents($in_schema_file_path);
312 
313  if ($schema_file) {
314  $ret = $this->_get_xsd_header()."$schema_file</xs:schema>";
315  }
316 
317  return $ret;
318  }
319 
320  /***********************/
326  protected function _condition_response( $in_response_type,
327  $in_response_as_associative_array = NULL
328  ) {
329  $ret = '';
330 
331  if ('xml' == $in_response_type) {
332  $header = $this->_get_xml_header();
333  $body = self::_array2xml($in_response_as_associative_array);
334  $footer = '</'.$this->plugin_name().'>';
335  $ret = "$header$body$footer";
336  } elseif ('xsd' == $in_response_type) {
337  $ret = $this->_get_xsd();
338  } else {
339  $ret = json_encode(Array($this->plugin_name() => $in_response_as_associative_array));
340  }
341  return $ret;
342  }
343 
344  /***********************/
351  protected function _get_child_ids( $in_object
352  ) {
353  $ret = [];
354 
355  if (method_exists($in_object, 'children') && (0 < $in_object->count())) {
356  $ret = $in_object->children_ids();
357  }
358 
359  return $ret;
360  }
361 
362  /***********************/
368  protected function _get_child_handler_data( $in_object
369  ) {
370  $ret = [];
371 
372  $id_list = $this->_get_child_ids($in_object);
373  $access_object = $in_object->get_access_object();
374 
375  if (isset($access_object) && is_array($id_list) && count($id_list)) {
376  foreach ($id_list as $id) {
377  $class_name = $access_object->get_data_access_class_by_id($id);
378  if ($class_name) {
379  $handler = self::_get_handler($class_name);
380  $ret[$handler][] = $id;
381  }
382  }
383  }
384 
385  return $ret;
386  }
387 
388  /***********************/
394  protected function _process_parameters( $in_andisol_instance,
395  $in_query
396  ) {
397  $ret = [];
398  if (isset($in_query) && is_array($in_query)) {
399  // See if they want to add new child data items to each user, or remove existing ones.
400  // We indicate adding ones via positive integers (the item IDs), and removing via negative integers (minus the item ID).
401  if (isset($in_query['child_ids']) && trim($in_query['child_ids'])) {
402  $child_item_list = []; // If we are adding new child items, their IDs go in this list.
403  $delete_child_item_list = []; // If we are removing items, we indicate that with negative IDs, and put those in a different list (absvaled).
404 
405  $child_id_list = array_map('intval', explode(',', trim($in_query['child_ids'])));
406 
407  // Child IDs are a CSV list of integers, with IDs of data records.
408  if (isset($child_id_list) && is_array($child_id_list) && count($child_id_list)) {
409  // Check for ones we can't see (we don't need write permission, but we do need read permission).
410  foreach ($child_id_list as $id) {
411  if (0 < $id) { // See if we are adding to the list
412  $item = $in_andisol_instance->get_single_data_record_by_id($id);
413  // If we got the item, then it exists, and we can see it. Add its ID to our list.
414  $child_item_list[] = $id;
415  } else { // If we are removing it, we still need read permission, but it goes in a different list.
416  $item = $in_andisol_instance->get_single_data_record_by_id(-$id);
417  $delete_child_item_list[] = -$id;
418  }
419  }
420 
421  // Make sure there's no repeats.
422  $child_item_list = array_unique($child_item_list);
423  $delete_child_item_list = array_unique($delete_child_item_list);
424 
425  // Because we're anal.
426  sort($child_item_list);
427  sort($delete_child_item_list);
428 
429  // At this point, we have a list of IDs that we want to add, and IDs that we want to remove, from the various (or single) users.
430  }
431 
432  // If we have items we want to add, we add them to our TO DO list.
433  if (isset($child_item_list) && is_array($child_item_list) && count($child_item_list)) {
434  if (!isset($ret['child_ids'])) {
435  $ret['child_ids'] = Array('add' => [], 'remove' => []);
436  }
437  $ret['child_ids']['add'] = $child_item_list;
438  }
439 
440  // If we have items we want to remove, we add those to our TO DO list.
441  if (isset($delete_child_item_list) && is_array($delete_child_item_list) && count($delete_child_item_list)) {
442  if (!isset($ret['child_ids'])) {
443  $ret['child_ids'] = Array('add' => [], 'remove' => []);
444  }
445  $ret['child_ids']['remove'] = $delete_child_item_list;
446  }
447  } elseif (isset($in_query['child_ids']) && !trim($in_query['child_ids'])) {
448  $ret['child_ids'] = 'DELETE-ALL'; // Remove everything.
449  }
450 
451  if (isset($in_query['name'])) {
452  $ret['name'] = trim($in_query['name']);
453  }
454 
455  if (isset($in_query['read_token'])) {
456  $token = intval($in_query['read_token']);
457  if ($in_andisol_instance->i_have_this_token($token)) {
458  $ret['read_token'] = intval($in_query['read_token']);
459  }
460  }
461 
462  if (isset($in_query['write_token'])) {
463  $token = intval($in_query['write_token']);
464  if ($in_andisol_instance->i_have_this_token($token)) {
465  $ret['write_token'] = intval($in_query['write_token']);
466  }
467  }
468 
469  if (isset($in_query['longitude'])) {
470  $ret['longitude'] = floatval($in_query['longitude']);
471  }
472 
473  if (isset($in_query['latitude'])) {
474  $ret['latitude'] = floatval($in_query['latitude']);
475  }
476 
477  if (isset($in_query['fuzz_factor'])) {
478  $ret['fuzz_factor'] = floatval($in_query['fuzz_factor']);
479  }
480 
481  if (isset($in_query['can_see_through_the_fuzz'])) {
482  $ret['can_see_through_the_fuzz'] = intval($in_query['can_see_through_the_fuzz']);
483  }
484 
485  // Next, we see if we want to change/set the "owner" object asociated with this. You can remove an associated owner object by passing in NULL or 0, here.
486  if (isset($in_query['owner_id'])) {
487  $ret['owner_id'] = abs(intval(trim($in_query['owner_id'])));
488  }
489 
490  // Next, look for the language.
491  if (isset($in_query['lang'])) {
492  $ret['lang'] = trim(strval($in_query['lang']));
493  }
494 
495  // Next, we see if we the user is supplying a payload to be stored, or removing the existing one.
496  if (isset($in_query['remove_payload'])) { // If they did not specify a payload, maybe they want one removed?
497  $ret['remove_payload'] = true;
498  } elseif (isset($in_query['payload'])) {
499  // See if the payload is already base64.
500  if (base64_encode(base64_decode($in_query['payload'])) == $in_query['payload']) {
501  $in_query['payload'] = base64_decode($in_query['payload']);
502  }
503  $ret['payload'] = $in_query['payload'];
504  }
505  }
506 
507  return $ret;
508  }
509 
510  /************************************************************************************************************************/
511  /*#################################################### ABSTRACT METHODS ################################################*/
512  /************************************************************************************************************************/
513  /***********************/
519  abstract protected function _get_xsd();
520 
521  /***********************/
527  abstract static public function classes_managed();
528 
529  /***********************/
535  abstract public function plugin_name();
536 
537  /***********************/
543  abstract public function process_command( $in_andisol_instance,
544  $in_http_method,
545  $in_response_type,
546  $in_path = [],
547  $in_query = []
548  );
549 }
_process_parameters( $in_andisol_instance, $in_query)
_condition_response( $in_response_type, $in_response_as_associative_array=NULL)
static _array2xml( $in_array)
static _get_handler( $in_classname)
_get_long_description( $in_object, $in_show_parents=false)
process_command( $in_andisol_instance, $in_http_method, $in_response_type, $in_path=[], $in_query=[])
_process_xsd( $in_schema_file_path)
static classes_managed()