BAOBAB
A_CO_Basalt_Plugin Class Reference
Inheritance diagram for A_CO_Basalt_Plugin:
Collaboration diagram for A_CO_Basalt_Plugin:

Public Member Functions

 plugin_name ()
 
 process_command ( $in_andisol_instance, $in_http_method, $in_response_type, $in_path=[], $in_query=[])
 

Static Public Member Functions

static classes_managed ()
 

Protected Member Functions

 _get_short_description ( $in_object)
 
 _get_long_description ( $in_object, $in_show_parents=false)
 
 _get_xml_header ()
 
 _get_xsd_header ()
 
 _process_xsd ( $in_schema_file_path)
 
 _condition_response ( $in_response_type, $in_response_as_associative_array=NULL)
 
 _get_child_ids ( $in_object)
 
 _get_child_handler_data ( $in_object)
 
 _process_parameters ( $in_andisol_instance, $in_query)
 
 _get_xsd ()
 

Static Protected Member Functions

static _get_handler ( $in_classname)
 
static _server_url ()
 
static _array2xml ( $in_array)
 

Static Protected Attributes

static $_s_cached_list = NULL
 This will contain caches of our handler list. More...
 

Detailed Description

Definition at line 32 of file a_co_basalt_plugin.class.php.

Member Function Documentation

◆ _array2xml()

static A_CO_Basalt_Plugin::_array2xml (   $in_array)
staticprotected
Returns
the input array, converted to XML.
Parameters
$in_arrayREQUIRED: The input associative array

Definition at line 97 of file a_co_basalt_plugin.class.php.

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  }
static _array2xml( $in_array)

◆ _condition_response()

A_CO_Basalt_Plugin::_condition_response (   $in_response_type,
  $in_response_as_associative_array = NULL 
)
protected

This conditions our response.

Returns
the HTTP response string, as either JSON or XML.
Parameters
$in_response_typeREQUIRED: 'json', 'xml' or 'xsd' -the response type.
$in_response_as_associative_arrayOPTIONAL (but required fon non-XSD): The response to be converted to JSON or XML, as an associative array. If XSD, then this can be an empty array.

Definition at line 326 of file a_co_basalt_plugin.class.php.

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  }

Referenced by CO_Basalt\process_command(), and CO_places_Basalt_Plugin\process_command().

Here is the caller graph for this function:

◆ _get_child_handler_data()

A_CO_Basalt_Plugin::_get_child_handler_data (   $in_object)
protected

This returns a list of handler plugins for each of the child IDs of a collection object.

Returns
an associative array, with the key being the handler, and each ID being part of a sub-array, under that key. NULL, if the object is not a collection, or has no children.
Parameters
$in_objectREQUIRED: This is the object we are testing.

Definition at line 368 of file a_co_basalt_plugin.class.php.

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  }
static _get_handler( $in_classname)

◆ _get_child_ids()

A_CO_Basalt_Plugin::_get_child_ids (   $in_object)
protected

This checks the provided object to see if it's a collection. If so, it queries the collection for its children IDs, and returns them as an array.

Returns
an empty array if no children (or the object is not a collection), or an array of integers (each being the Data database ID of a child object).
Parameters
$in_objectREQUIRED: This is the object we are testing.

Definition at line 351 of file a_co_basalt_plugin.class.php.

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  }

◆ _get_handler()

static A_CO_Basalt_Plugin::_get_handler (   $in_classname)
staticprotected

This returns any handler for the presented class.

Returns
a string, with the plugin name that handles the given class.
Parameters
$in_classnameREQUIRED: The name of the class we are querying for a handler.

Definition at line 41 of file a_co_basalt_plugin.class.php.

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  }

Referenced by CO_Basalt\_process_baseline_command().

Here is the caller graph for this function:

◆ _get_long_description()

A_CO_Basalt_Plugin::_get_long_description (   $in_object,
  $in_show_parents = false 
)
protected

This returns a fairly short summary of the given object.

Returns
an associative array of strings and integers.
Parameters
$in_objectREQUIRED: The object to parse.
$in_show_parentsOPTIONAL: (Default is false). If true, then the parents will be shown. This can be a time-consuming operation, so it needs to be explicitly requested.

Reimplemented in CO_people_Basalt_Plugin.

Definition at line 174 of file a_co_basalt_plugin.class.php.

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  }

◆ _get_short_description()

A_CO_Basalt_Plugin::_get_short_description (   $in_object)
protected

This returns a fairly short summary of the given object.

Returns
an associative array of strings and integers.
Parameters
$in_objectREQUIRED: The object to parse.

Reimplemented in CO_places_Basalt_Plugin.

Definition at line 132 of file a_co_basalt_plugin.class.php.

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  }

References $lang.

◆ _get_xml_header()

A_CO_Basalt_Plugin::_get_xml_header ( )
protected

This returns the appropriate XML header for our response.

Returns
a string, with the entire XML header (including the preamble).

Definition at line 279 of file a_co_basalt_plugin.class.php.

279  {
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  }

◆ _get_xsd()

A_CO_Basalt_Plugin::_get_xsd ( )
abstractprotected

This returns the schema for this plugin as XML XSD.

Returns
XML, containing the schema for this plugin's responses. The schema needs to be comprehensive.

Reimplemented in CO_things_Basalt_Plugin, CO_places_Basalt_Plugin, CO_people_Basalt_Plugin, and CO_Basalt.

◆ _get_xsd_header()

A_CO_Basalt_Plugin::_get_xsd_header ( )
protected

This returns the appropriate XML header for our schema file.

Returns
a string, with the entire XML header for the schema file (including the preamble).

Definition at line 293 of file a_co_basalt_plugin.class.php.

293  {
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  }

◆ _process_parameters()

A_CO_Basalt_Plugin::_process_parameters (   $in_andisol_instance,
  $in_query 
)
protected

Parses the query parameters and cleans them for the database.

Returns
an associative array of the parameters, parsed for submission to the database.
Parameters
$in_andisol_instanceREQUIRED: The ANDISOL instance to use as the connection to the RVP databases.
$in_queryREQUIRED: The query string to be parsed.

Reimplemented in CO_things_Basalt_Plugin, and CO_places_Basalt_Plugin.

Definition at line 394 of file a_co_basalt_plugin.class.php.

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  }

◆ _process_xsd()

A_CO_Basalt_Plugin::_process_xsd (   $in_schema_file_path)
protected

This processes the schema for this plugin as XML XSD.

Returns
XML, containing the schema for this plugin's responses. The schema needs to be comprehensive.
Parameters
$in_schema_file_pathREQUIRED: The file path (POSIX) to the schema file to process.

Definition at line 307 of file a_co_basalt_plugin.class.php.

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  }

Referenced by CO_Basalt\_get_xsd(), and CO_places_Basalt_Plugin\_get_xsd().

Here is the caller graph for this function:

◆ _server_url()

static A_CO_Basalt_Plugin::_server_url ( )
staticprotected
Returns
the server base URI, including any custom port and/or SSL prefix.

Definition at line 75 of file a_co_basalt_plugin.class.php.

75  {
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  }

◆ classes_managed()

static A_CO_Basalt_Plugin::classes_managed ( )
staticabstract

This returns an array of classnames, handled by this plugin.

Returns
an array of string, with the names of the classes handled by this plugin.

Reimplemented in CO_things_Basalt_Plugin, CO_places_Basalt_Plugin, CO_people_Basalt_Plugin, and CO_Basalt.

◆ plugin_name()

A_CO_Basalt_Plugin::plugin_name ( )
abstract

This returns our plugin name.

Returns
a string, with our plugin name.

Reimplemented in CO_things_Basalt_Plugin, CO_places_Basalt_Plugin, CO_people_Basalt_Plugin, and CO_Basalt.

◆ process_command()

A_CO_Basalt_Plugin::process_command (   $in_andisol_instance,
  $in_http_method,
  $in_response_type,
  $in_path = [],
  $in_query = [] 
)
abstract

This runs our plugin command.

Returns
the HTTP response string, as either JSON or XML.
Parameters
$in_andisol_instanceREQUIRED: The ANDISOL instance to use as the connection to the RVP databases.
$in_http_methodREQUIRED: 'GET', 'POST', 'PUT' or 'DELETE'
$in_response_typeREQUIRED: 'json', 'xml' or 'xsd' -the response type.
$in_pathOPTIONAL: The REST path, as an array of strings. For the baseline, this should be exactly one element.
$in_queryOPTIONAL: The query parameters, as an associative array.

Reimplemented in CO_things_Basalt_Plugin, CO_places_Basalt_Plugin, CO_people_Basalt_Plugin, and CO_Basalt.

Member Data Documentation

◆ $_s_cached_list

A_CO_Basalt_Plugin::$_s_cached_list = NULL
staticprotected

This will contain caches of our handler list.

Definition at line 33 of file a_co_basalt_plugin.class.php.