BMLT Root Server
c_comdef_server.class.php
Go to the documentation of this file.
1 <?php
2 /**
3  \file c_comdef_server.class.php
4 
5  \brief The main server (Model) class for the Basic Meeting List Toolbox MVC system.
6 
7  The server is a SINGLETON. There can only be one. Upon instantiation, it creates a bunch of format objects, in its own
8  localization. The formats are all read in and kept local, but the meetings are supplied upon demand. The same goes for the
9  change tracking.
10 
11  This series of classes interfaces with the server, using PHP's PDO database abstraction layer} (http://us3.php.net/pdo),
12  so this system should work for multiple databases.
13 
14  This file is part of the Basic Meeting List Toolbox (BMLT).
15 
16  Find out more at: https://bmlt.app
17 
18  BMLT is free software: you can redistribute it and/or modify
19  it under the terms of the MIT License.
20 
21  BMLT is distributed in the hope that it will be useful,
22  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  MIT License for more details.
25 
26  You should have received a copy of the MIT License along with this code.
27  If not, see <https://opensource.org/licenses/MIT>.
28  */
29 defined('BMLT_EXEC') or die('Cannot Execute Directly'); // Makes sure that this file is in the correct context.
30 
31 require_once(dirname(__FILE__)."/classes/c_comdef_dbsingleton.class.php");
32 require_once(dirname(__FILE__)."/classes/c_comdef_formats.class.php");
33 require_once(dirname(__FILE__)."/classes/c_comdef_meetings.class.php");
34 require_once(dirname(__FILE__)."/classes/c_comdef_changes.class.php");
35 require_once(dirname(__FILE__)."/classes/c_comdef_users.class.php");
36 require_once(dirname(__FILE__)."/classes/c_comdef_service_bodies.class.php");
37 require_once(dirname(__FILE__)."/shared/classes/base_templates.inc.php");
38 
39 /******************************************************************/
40 
41 /** \brief This class is the main server class. It instantiates a
42  PDO database object, and is the starting point for everything
43  done and managed by the CoMDEF server system.
44 */
45 // phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
46 // phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
48 // phpcs:enable PSR1.Classes.ClassDeclaration.MissingNamespace
49 // phpcs:enable Squiz.Classes.ValidClassName.NotCamelCaps
50 {
51  ///This is the SINGLETON server instance. There can only be one...
52  public static $server_instance = null;
53  /// This contains a cache of the local strings.
54  public static $server_local_strings = null;
55 
56  /// This is the name of the Formats table in the database.
57  private $_format_table_name = null;
58  /// This is the name of the Meetings table in the database.
59  private $_meeting_table_name = null;
60  /// This is the name of the Changes table in the database.
61  private $_changes_table_name = null;
62  /// This is the name of the user table in the database.
63  private $_user_table_name = null;
64  /// This is the name of the database version table in the database.
65  private $_db_version_table_name = null;
66  /// This is the name of the Service Bodies table in the database.
67  private $_service_bodies_table_name = null;
68  /// This is the container for the loaded formats.
69  private $_formats_obj = null;
70  /// This is the container for the loaded formats that are actually used in the meetings. Each element is a format shared ID.
71  private $_used_format_ids = null;
72  /// This is the container for the loaded users.
73  private $_users_obj = null;
74  /// This has the IDs of all the Service entities that "own" meetings on the server.
75  private $_service_ids = null;
76  /// This contains the names of the server languages, in their languages. It is an associative array, based on the language enums.
77  private $_server_lang_names = null;
78  /// This contains the names of additional languages for which formats are defined, in the main language of the server. It is an associative array, based on the language enums.
79  private $_format_lang_names = null;
80  /// This contains the server namespace, which is used to uniquely identify data from this server. The default is the server URI, with "/CoMDEF" appended.
81  private $_server_namespace = null;
82  /// This contains the actual Service Body objects as a simple array.
83  private $_service_obj_array = null;
84 
85  /*******************************************************************/
86  /** \brief This is the factory for the server instantiation.
87  It makes sure that only one instance exists.
88 
89  \returns the Server instance. Either a new one, or the existing one.
90  */
91  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
92  public static function MakeServer()
93  {
94  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
95  if (!(self::$server_instance instanceof c_comdef_server)) {
96  self::$server_instance = new c_comdef_server;
97  }
98 
99  return self::$server_instance;
100  }
101 
102  /*******************************************************************/
103  /** \returns the Server instance.
104  */
105  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
106  public static function GetServer()
107  {
108  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
109  return self::$server_instance;
110  }
111 
112  /*******************************************************************/
113  /** \brief Sets the server instance.
114  */
115  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
116  public static function SetServer($in_server_instance)
117  {
118  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
119  if ($in_server_instance != self::GetServer()) {
120  if (null !== self::GetServer()) {
121  self::$server_instance = null;
122  }
123 
124  self::$server_instance = $in_server_instance;
125  }
126  }
127 
128  /*******************************************************************/
129  /** \brief The initial setup call for the class. Part of setting up
130  the server is establishing the database connection, and reading
131  in all of the formats, which will be available in the
132  GetFormatsObj() member function afterwards.
133  */
134  public function __construct(
135  $in_lang_enum = null ///< It is possible to force a different language via this parameter.
136  ) {
138 
139  try {
140  self::SetServer($this);
141  include(dirname(__FILE__)."/config/get-config.php");
142 
143  if (!isset($dbType)) {
144  $dbType = 'mysql';
145  }
146 
147  if (!isset($dbServer)) {
148  $dbServer = 'localhost';
149  }
150 
151  if (!isset($dbPrefix)) {
152  $dbPrefix = 'na';
153  }
154 
155  c_comdef_dbsingleton::init($dbType, $dbServer, $dbName, $dbUser, $dbPassword, 'utf8');
156 
157  // These are all the base names of the SQL tables.
158  $this->_format_table_name = $dbPrefix."_comdef_formats";
159  $this->_meeting_table_name = $dbPrefix."_comdef_meetings";
160  $this->_changes_table_name = $dbPrefix."_comdef_changes";
161  $this->_service_bodies_table_name = $dbPrefix."_comdef_service_bodies";
162  $this->_user_table_name = $dbPrefix."_comdef_users";
163  $this->_db_version_table_name = $dbPrefix."_comdef_db_version";
164 
165  if (isset($serverNamespace) && (null !== $serverNamespace)) {
166  $this->_server_namespace = $serverNamespace;
167  } else {
168  $this->_server_namespace = "http://".$_SERVER['SERVER_NAME']."/CoMDEF";
169  }
170 
171  // Brute-force protection against selecting a language that isn't supported by the resources at hand.
172  if (!file_exists(dirname(__FILE__)."/../local_server/server_admin/lang/".$comdef_global_language."/name.txt")) {
173  $comdef_global_language = "en";
174  }
175 
176  global $http_vars;
177 
178  if (isset($in_lang_enum) && $in_lang_enum) { // If a different language was specified, we force that into place now.
179  if (isset($http_vars) && is_array($http_vars)) {
180  $http_vars['lang_enum'] = $in_lang_enum;
181  }
182 
183  if (file_exists(dirname(__FILE__)."/../local_server/server_admin/lang/".$in_lang_enum."/name.txt")) {
184  $comdef_global_language = $in_lang_enum;
185  }
186  } elseif (isset($http_vars) && is_array($http_vars) && count($http_vars) && isset($http_vars['lang_enum'])) {
187  $lang_name = $http_vars['lang_enum'];
188 
189  if (file_exists(dirname(__FILE__)."/../local_server/server_admin/lang/".$lang_name."/name.txt")) {
190  $comdef_global_language = $lang_name;
191  }
192  } elseif (isset($_SESSION) && is_array($_SESSION) && isset($_SESSION['lang_enum'])) {
193  $lang_name = $_SESSION['lang_enum'];
194 
195  if (isset($http_vars) && is_array($http_vars)) {
196  $http_vars['lang_enum'] = $in_lang_enum;
197  }
198 
199  if (file_exists(dirname(__FILE__)."/../local_server/server_admin/lang/".$lang_name."/name.txt")) {
200  $comdef_global_language = $lang_name;
201  }
202  }
203 
204  if (isset($_SESSION) && is_array($_SESSION)) {
205  $_SESSION['lang_enum'] = $comdef_global_language;
206  }
207 
208  $this->_local_type_lang_enum = $comdef_global_language;
209 
210  $dh = opendir(dirname(__FILE__).'/../local_server/server_admin/lang/');
211  $server_lang_names = array();
212 
213  if ($dh) {
214  while (false !== ($enum = readdir($dh))) {
215  $file_path = dirname(dirname(__FILE__))."/local_server/server_admin/lang/$enum/name.txt";
216  if (file_exists($file_path)) {
217  $server_lang_names[$enum] = trim(file_get_contents($file_path));
218  }
219  }
220 
221  closedir($dh);
222  }
223 
224  uksort($server_lang_names, 'c_comdef_server::ServerLangSortCallback');
225 
226  $this->_server_lang_names = $server_lang_names;
227  if (isset($format_lang_names) && is_array($format_lang_names)) {
228  $this->_format_lang_names = $format_lang_names;
229  } else {
230  $this->_format_lang_names = [];
231  }
232  $this->Initialize();
233  } catch (Exception $err) {
234  throw ( $err );
235  }
236  }
237 
238  /*******************************************************************/
239  /** \brief This is a callback to sort the server languages.
240  The default server language will always be first, and
241  the rest will be sorted alphabetically.
242  \returns an integer. -1 if goes before b, 1 if otherwise, 0 if neither.
243  */
244  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
245  public static function ServerLangSortCallback(
246  $in_lang_a,
247  $in_lang_b
248  ) {
249  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
250  $server_lang = c_comdef_server::GetServer()->GetLocalLang();
251  $ret = 0;
252 
253  if ($in_lang_a == $server_lang) {
254  $ret = -1;
255  } elseif ($in_lang_b == $server_lang) {
256  $ret = 1;
257  } else {
258  $ret = strncasecmp($in_lang_a, $in_lang_b, 3);
259  }
260 
261  return $ret;
262  }
263 
264  /*******************************************************************/
265  /** \brief This reads the Formats, Meeting and Service Entity IDs.
266  */
267  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
268  public function Initialize()
269  {
270  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
271  $this->ReadUsers();
272  $this->ReadServiceBodies();
273  $this->ReadServiceIDs();
274  }
275 
276  /*******************************************************************/
277  /** \brief Returns the Server Local Language.
278 
279  \returns a string, with the language enum.
280  */
281  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
282  public function GetLocalLang()
283  {
284  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
285  $lang_enum = $this->_local_type_lang_enum;
286 
287  if (!$lang_enum) {
290  }
291 
292  // Should never happen.
293  if (!$lang_enum) {
294  $lang_enum = "en";
295  }
296 
297  return $lang_enum;
298  }
299 
300  /*******************************************************************/
301  /** \brief This is an internal function that reads in all of the
302  stored formats, in all provided languages, and instantiates
303  local objects for them.
304  Access them with the GetFormatsObj() member function afterwards.
305  */
306  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
307  public function ReadFormats()
308  {
309  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
310  $this->_used_format_ids = array ();
311  $sql = "SELECT * FROM `".self::GetFormatTableName_obj()."` ORDER BY shared_id_bigint, lang_enum";
312 
314 
315  if (is_array($rows) && count($rows)) {
316  $obj_array = array();
317  /// Read in all the formats, and instantiate an array of objects.
318  foreach ($rows as $rs) {
319  /// We aren't allowed to have two formats for the same language, and the same shared ID.
320  if (!isset($rs['lang_enum']) || !isset($obj_array[$rs['lang_enum']]) || !isset($obj_array[$rs['lang_enum']][$rs['shared_id_bigint']]) || !is_object($obj_array[$rs['lang_enum']][$rs['shared_id_bigint']])) {
321  /// We use a combination of the language and the shared ID as the keys, which allows us to sort better.
322  $obj_array[$rs['lang_enum']][$rs['shared_id_bigint']] = new c_comdef_format(
323  $this,
324  $rs['shared_id_bigint'],
325  $rs['format_type_enum'],
326  $rs['key_string'],
327  $rs['icon_blob'],
328  $rs['worldid_mixed'],
329  $rs['lang_enum'],
330  $rs['name_string'],
331  $rs['description_string']
332  );
333  }
334  }
335 
336  /// Create our internal container, and give it the array.
337  $this->_formats_obj = new c_comdef_formats($this, $obj_array);
338 
339  // Now that we have all our formats, we quickly read in the formats from all the meetings, and filter out just the ones that are actually used.
340  $sql = "SELECT `formats` FROM `".self::GetMeetingTableName_obj()."_main`";
341 
343 
344  if (is_array($rows) && count($rows)) {
345  $format_codes = array();
346  // Read each of the format CSV lists, split the list, and then check each one in our tracker.
347  foreach ($rows as $row) {
348  $codes = explode(',', $row['formats']);
349  foreach ($codes as $code) {
350  $index = "ID-$code"; // We do this, because some PHP processors refuse to allow pure ints to be associative properties.
351  if (!isset($format_codes[$index])) {
352  $format_codes[$index] = 1;
353  } else {
354  $format_codes[$index] = intval($format_codes[$index]) + 1; // Do it this way, just in case the PHP interpreter gets funny about interpreting as int.
355  }
356  }
357  }
358 
359  // At this point format_codes is an associative array with only the formats actually used. The format code is in the key. We sort them so that the most frequent ones are at the beginning.
360  // We go through that, and extract our codes.
361 
362  arsort($format_codes);
363  $format_codes = array_keys($format_codes);
364 
365  foreach ($format_codes as $format_id) {
366  $format_id_num = intval(preg_replace("|ID\-(.*)|", "$1", $format_id));
367  if ($format_id_num) {
368  array_push($this->_used_format_ids, $format_id_num);
369  }
370  }
371  }
372  }
373  }
374 
375  /*******************************************************************/
376  /** \brief This is an internal function that reads in all of the
377  stored users and instantiates local objects for them.
378  Access them with the GetUsersObj() member function afterwards.
379  */
380  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
381  public function ReadUsers()
382  {
383  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
384  // First, we make sure we explicitly delete any old ones.
385 
386  if ($this->_users_obj instanceof c_comdef_users) {
387  $ar = $this->_users_obj->GetUsersArray();
388 
389  foreach ($ar as &$u) {
390  $u = null;
391  }
392 
393  $this->_users_obj = null;
394  }
395 
396  $sql = "SELECT * FROM `".self::GetUserTableName_obj()."` ORDER BY id_bigint";
397 
399 
400  if (is_array($rows) && count($rows)) {
401  $obj_array = array();
402  /// Read in all the users, and instantiate an array of objects.
403  foreach ($rows as $row) {
404  $time = explode(" ", $row['last_access_datetime']);
405  $t0 = explode("-", $time[0]);
406  $t1 = explode(":", $time[1]);
407  $obj_array[$row['id_bigint']] = new c_comdef_user(
408  $this,
409  $row['id_bigint'],
410  $row['user_level_tinyint'],
411  $row['email_address_string'],
412  $row['login_string'],
413  $row['password_string'],
414  $row['lang_enum'],
415  $row['name_string'],
416  $row['description_string'],
417  $row['owner_id_bigint'],
418  mktime($t1[0], $t1[1], $t1[2], $t0[1], $t0[2], $t0[0])
419  );
420  }
421 
422  /// Create our internal container, and give it the array.
423  $this->_users_obj = new c_comdef_users($this, $obj_array);
424  }
425  }
426 
427  /*******************************************************************/
428  /** \brief This is an internal function that reads in all of the
429  stored service bodies and instantiates local objects for them.
430  Access them with the GetServiceObj() member function afterwards.
431  */
432  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
433  public function ReadServiceBodies()
434  {
435  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
436  $this->_service_obj_array = array();
437 
438  $sql = "SELECT * FROM `".self::GetServiceBodiesTableName_obj()."` ORDER BY id_bigint";
439 
441 
442  if (is_array($rows) && count($rows)) {
443  /// Read in all the service bodies, and instantiate an array of objects.
444  foreach ($rows as $row) {
445  array_push($this->_service_obj_array, new c_comdef_service_body(
446  $this,
447  $row['id_bigint'],
448  $row['principal_user_bigint'],
449  $row['editors_string'],
450  $row['kml_file_uri_string'],
451  $row['uri_string'],
452  $row['name_string'],
453  $row['description_string'],
454  $row['lang_enum'],
455  $row['worldid_mixed'],
456  $row['sb_type'],
457  $row['sb_owner'],
458  $row['sb_owner_2'],
459  $row['sb_meeting_email']
460  ));
461  }
462 
463  // What we do here, is look for orphans, and assign them a parent ID of 0.
464  for ($c = 0; $c < count($this->_service_obj_array); $c++) {
465  $parent_id = $this->_service_obj_array[$c]->GetOwnerID();
466  $found = false;
467  for ($i = 0; $i < count($this->_service_obj_array); $i++) {
468  $id = $this->_service_obj_array[$i]->GetID();
469  if ($id == $parent_id) {
470  $found = true;
471  break;
472  }
473  }
474 
475  if (!$found) {
476  $this->_service_obj_array[$c]->SetOwnerID(0);
477  }
478  }
479  }
480  }
481 
482  /*******************************************************************/
483  /** \brief This gathers the IDs of all the Service bodies that appear
484  in meeting records. It is NOT a dump of the Service Bodies table.
485  */
486  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
487  public function ReadServiceIDs()
488  {
489  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
490  $sql = "SELECT service_body_bigint FROM `".self::GetMeetingTableName_obj()."_main` ORDER BY service_body_bigint";
491 
493 
494  // Just makes sure that old allocations are explicitly gone.
495  $this->_service_ids = null;
496  $this->_service_ids = array();
497 
498  if (is_array($rows) && count($rows)) {
499  foreach ($rows as $rs) {
500  $key = $rs['service_body_bigint'];
501  $value = $key;
502  $obj = self::GetServiceBodyByIDObj($key);
503  if ($obj instanceof c_comdef_service_body) {
504  $name = trim($obj->GetLocalName());
505  if ($name) {
506  $key = $name;
507  }
508  }
509  $this->_service_ids[$key] = $value;
510  }
511  }
512  }
513 
514  /*******************************************************************/
515  /** \brief Simply returns a reference to the contained Service Body
516  array.
517 
518  \returns A reference to an array of c_comdef_service_body objects.
519  */
520  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
521  public function GetServiceBodyArray()
522  {
523  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
524  return $this->_service_obj_array;
525  }
526 
527  /*******************************************************************/
528  /** \brief Returns the Service Body objects in a nested, hierarchical
529  array, with "parents" containing "children."
530 
531  \returns A nested associative array of references to
532  c_comdef_service_body objects.
533  */
534  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
536  {
537  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
538  $ret_array = $this->GetNestedServiceBodyArray(0);
539  return $ret_array;
540  }
541 
542  /*******************************************************************/
543  /** \brief This reads the Service bodies in hierarchical order, and
544  returns them in a multi-dimensional array that reflects
545  the hierarchy.
546 
547  \returns A multidimensional associative array, containing the
548  Service bodies, as references, and structured in a manner
549  that reflects the hierarchical arrangement of the Service
550  bodies.
551  The 'object' element contains a reference to the object itself,
552  and the 'dependents' element (if it exists), reflects the
553  Service bodies that are "owned" by this one.
554  */
555  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
556  public function GetNestedServiceBodyArray( $in_id = 0 ///< The ID of the "top" Service body. If not supplied, we start at the top.
557  )
558  {
559  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
560  $ret_array = null;
561 
562  if ($in_id) {
563  $sb = $this->GetServiceBodyByIDObj($in_id);
564  if ($sb instanceof c_comdef_service_body) {
565  $id = $sb->GetID();
566  $ret_array['object'] = $sb;
567  }
568  }
569 
570  foreach ($this->_service_obj_array as &$sb) {
571  if ($sb instanceof c_comdef_service_body) {
572  $id = $sb->GetID();
573 
574  $sb_parent = intval($sb->GetOwnerID());
575 
576  if ($sb_parent == $in_id) {
577  $ret_array['dependents'][$id] = $this->GetNestedServiceBodyArray($id);
578  }
579  }
580  }
581 
582  return $ret_array;
583  }
584 
585  /*******************************************************************/
586  /** \brief Simply returns a reference to the formats container.
587 
588  \returns A reference to the formats container object.
589  */
590  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
591  public function GetFormatsObj()
592  {
593  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
594  if (!$this->_formats_obj) {
595  $this->ReadFormats();
596  }
597 
598  return $this->_formats_obj;
599  }
600 
601  /*******************************************************************/
602  /** \brief Simply returns an array of the format objects.
603 
604  \returns An array of c_comdef_format objects.
605  */
606  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
607  public function GetFormatsArray()
608  {
609  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
610  return ($this->GetFormatsObj() instanceof c_comdef_formats) ? $this->GetFormatsObj()->GetFormatsArray() : null;
611  }
612 
613  /*******************************************************************/
614  /** \brief Simply returns an array of the format objects used by the meetings (no unused ones).
615 
616  \returns An array of c_comdef_format objects.
617  */
618  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
619  public function GetUsedFormatsArray()
620  {
621  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
622  $ret = null;
623  $formats_array = $this->GetFormatsArray();
624  $all_formats = $formats_array[$this->GetLocalLang()];
625 
626  if (is_array($all_formats) && count($all_formats) && is_array($this->GetUsedFormatIDs()) && count($this->GetUsedFormatIDs())) {
627  $ret = array();
628 
629  foreach ($all_formats as $format) {
630  if (in_array($format->GetSharedID(), $this->GetUsedFormatIDs())) {
631  $ret[$format->GetSharedID()] = $format;
632  }
633  }
634  }
635 
636  return $ret;
637  }
638 
639  /*******************************************************************/
640  /** \brief Return the shared IDs of the formats actually used by the contained meetings.
641  This can be used to avoid showing format codes that are not relevant to the database.
642 
643  \returns an array of Int, with the ones most frequently represented at the top.
644  */
645  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
646  public function GetUsedFormatIDs()
647  {
648  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
649  if (!$this->_used_format_ids) {
650  $this->ReadFormats();
651  }
652 
653  return $this->_used_format_ids;
654  }
655 
656  /*******************************************************************/
657  /** \brief Simply returns the stored service IDs.
658 
659  \returns a reference to the array containing all the Service entity IDs.
660  NOTE: These are IDs that appear in meetings, and may not reflect those in the Server.
661  */
662  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
663  public function GetServiceIDs()
664  {
665  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
666  return $this->_service_ids;
667  }
668 
669  /*******************************************************************/
670  /** \brief Simply returns the stored service IDs for ALL Service Bodies.
671 
672  \returns a reference to the array containing all the Service entity IDs. Null if none.
673  NOTE: These are ALL IDs that appear (even ones not used for meetings).
674  */
675  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
676  public function GetAllServiceIDs()
677  {
678  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
679  $ret = null;
680 
681  $ar = $this->GetServiceBodyArray();
682 
683  if (is_array($ar) && count($ar)) {
684  foreach ($ar as &$sb) {
685  if ($sb instanceof c_comdef_service_body) {
686  $key = $sb->GetID();
687  $value = $key;
688  $name = trim($sb->GetLocalName());
689  if ($name) {
690  $key = $name;
691  }
692 
693  $ret[$key] = $value;
694  }
695  }
696  }
697 
698  return $ret;
699  }
700 
701  /*******************************************************************/
702  /** \brief This creates a new meeting that is an exact duplicate of
703  the object for the meeting whose ID is passed in. The new meeting
704  has a new ID, and is unpublished.
705 
706  \returns an integer, with the ID of the new meeting. 0 If it fails.
707  */
708  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
709  public static function DuplicateMeetingID( $in_meeting_id ///< The ID of the meeting to be copied.
710  )
711  {
712  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
713  $ret = 0;
714 
715  $meeting_to_copy = self::GetOneMeeting($in_meeting_id);
716 
717  if ($meeting_to_copy instanceof c_comdef_meeting) {
718  $copy = self::DuplicateMeetingObj($meeting_to_copy);
719 
720  if ($copy instanceof c_comdef_meeting) {
721  $ret = $copy->GetID();
722  }
723  }
724 
725  return $ret;
726  }
727 
728  /*******************************************************************/
729  /** \brief This creates a new meeting that is an exact duplicate of
730  the object passed in. The new meeting has a new ID, and is unpublished.
731 
732  \returns a reference to a c_comdef_meeting object, representing the new meeting. Null if it fails.
733  */
734  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
735  public static function DuplicateMeetingObj( $in_meeting_obj ///< A reference to the meeting object to be copied.
736  )
737  {
738  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
739  $new_meeting = null;
740 
741  if ($in_meeting_obj instanceof c_comdef_meeting) {
742  $meeting_data = $in_meeting_obj->GetMeetingData();
743  $meeting_data['id_bigint'] = 0;
744  $meeting_data['published'] = 0;
745  $meeting_data['copy'] = $in_meeting_obj->GetID();
746 
747  $new_meeting = new c_comdef_meeting(self::GetServer(), $meeting_data);
748 
749  if ($new_meeting instanceof c_comdef_meeting) {
750  $new_meeting->UpdateToDB();
751  }
752  }
753 
754  return $new_meeting;
755  }
756 
757  /*******************************************************************/
758  /** \brief Creates a new, relatively empty meeting in the database,
759  with no data fields and minimal information.
760 
761  \returns the ID of the meeting. Null is it failed.
762  */
763  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
764  public static function AddNewMeeting(
765  $in_service_body_bigint, ///< The ID of the Service Body that "owns" this meeting.
766  $in_weekday_tinyint, ///< The index of the weekday on which the meeting is held (0 = Sunday, 6 = Saturday).
767  $in_start_time_int, ///< The time, in standard PHP Epoch time, at which the meeting starts.
768  $in_lang_enum ///< The language for the meeting.
769  ) {
770  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
771  $id = null;
772 
773  if (!$in_lang_enum) {
774  $in_lang_enum = self::GetServer()->GetLocalLang();
775  }
776 
777  if (!$in_lang_enum) {
779  $in_lang_enum = $comdef_global_language;
780  }
781 
782  // Should never happen.
783  if (!$in_lang_enum) {
784  $in_lang_enum = "en";
785  }
786 
787  $meeting_data = array ( 'service_body_bigint'=>intval($in_service_body_bigint), 'weekday_tinyint'=>intval($in_weekday_tinyint), 'start_time'=>intval($in_start_time_int), 'lang_enum'=>$in_lang_enum );
788 
789  $new_meeting = new c_comdef_meeting(self::GetServer(), $meeting_data);
790 
791  if ($new_meeting instanceof c_comdef_meeting) {
792  $my_localized_strings = self::GetServer()->GetLocalStrings();
793  $data =& $new_meeting->GetMeetingData();
794  $data['longitude'] = floatval($my_localized_strings['search_spec_map_center']['longitude']);
795  $data['latitude'] = floatval($my_localized_strings['search_spec_map_center']['latitude']);
796 
797  $new_meeting->UpdateToDB();
798  $id = $new_meeting->GetID();
799  }
800 
801  return $id;
802  }
803 
804  /*******************************************************************/
805  /** \brief Creates a new Service Body in the Database.
806 
807  \returns the ID of the Service Body. Null is it failed.
808  */
809  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
810  public static function AddNewServiceBody(
811  $in_name_string, ///< The Service Body's Name
812  $in_lang_enum, ///< The language for the Service Body
813  $in_principal_user_bigint, ///< The ID of the principal Service Body Administrator
814  $in_description_string = null, ///< The description of the Service Body (Optional)
815  $in_editors_string = null, ///< The IDs of the editors, as a CSV string (Optional)
816  $in_uri_string = null, ///< The Service Body Web Site URI (Optional)
817  $in_kml_uri_string = null, ///< The URI of a KML file that contains the Service Boundaries of the Service Body (Optional)
818  $in_worldid_mixed = null, ///< The World ID (if one is available) (Optional)
819  $in_sb_type = null,
820  // An enum string, containing the Service Body type.
821  // It can be one of the following:
822  // - 'GR' Individual NA Group
823  // - 'AS' Area Service Committee
824  // - 'RS' Regional Service Committee
825  // - 'MA' Metro Area
826  // - 'ZF' Zonal Forum
827  // - 'WS' World Service Committee
828  $in_sb_owner = null ///< An integer. The ID of the Service Body that "owns" this Service Body.
829  ) {
830  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
831  $id = null;
832 
833  if (!$in_lang_enum) {
834  $in_lang_enum = self::GetServer()->GetLocalLang();
835  }
836 
837  if (!$in_lang_enum) {
839  $in_lang_enum = $comdef_global_language;
840  }
841 
842  // Should never happen.
843  if (!$in_lang_enum) {
844  $in_lang_enum = "en";
845  }
846 
847  $service_body = new c_comdef_service_body(self::GetServer(), null, $in_principal_user_bigint, $in_editors_string, $in_kml_uri_string, $in_uri_string, $in_name_string, $in_description_string, $in_lang_enum, $in_worldid_mixed, $in_sb_type, $in_sb_owner);
848 
849  if ($service_body instanceof c_comdef_service_body) {
850  try {
851  $service_body->UpdateToDB();
852  $id = $service_body->GetID();
853  $service_body = null;
854 
855  self::GetServer()->ReadServiceBodies();
856  } catch (Exception $e) { // We just eat the exception and return null.
857  $id = null;
858  }
859  }
860 
861  return $id;
862  }
863 
864  /*******************************************************************/
865  /** \brief Creates a new user in the Database.
866 
867  \returns the ID of the user. Null is it failed.
868  */
869  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
870  public static function AddNewUser(
871  $in_user_login, ///< The login for this user
872  $in_user_unencrypted_password, ///< The unencrypted password for this user
873  $in_user_level, ///< The level of this user
874  $in_user_email, ///< The email address for this user
875  $in_name_string = null, ///< The user's Name (Optional)
876  $in_description_string = null, ///< The description of the user (Optional)
877  $in_lang_enum = null, ///< The language for the user (Optional -If not supplied, the server default will be used)
878  $in_owner_id = -1 ///< The id of the user that owns this user
879  ) {
880  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
881  $id = null;
882 
883  if (!$in_lang_enum) {
884  $in_lang_enum = self::GetServer()->GetLocalLang();
885  }
886 
887  if (!$in_lang_enum) {
889  $in_lang_enum = $comdef_global_language;
890  }
891 
892  // Should never happen.
893  if (!$in_lang_enum) {
894  $in_lang_enum = "en";
895  }
896 
897  $encrypted_password = FullCrypt(trim($in_user_unencrypted_password));
898 
899  $user_obj = new c_comdef_user(self::GetServer(), null, $in_user_level, $in_user_email, $in_user_login, $encrypted_password, $in_lang_enum, $in_name_string, $in_description_string, $in_owner_id);
900 
901  if ($user_obj instanceof c_comdef_user) {
902  try {
903  $user_obj->UpdateToDB();
904  $id = $user_obj->GetID();
905  $user_obj = null;
906 
907  self::GetServer()->ReadUsers();
908  } catch (Exception $e) { // We just eat the exception and return null.
909  $id = null;
910  }
911  }
912 
913  return $id;
914  }
915 
916  /*******************************************************************/
917  /** \brief trims the changes for the given item.
918  */
919  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
920  public static function TrimChanges(
921  $in_type, //
922  // This is a string that contains the class of the change record.
923  // - It can be:
924  // - c_comdef_meeting
925  // - c_comdef_format
926  // - c_comdef_user
927  // - c_comdef_service_body
928  $in_id //< The ID (an integer) for the item to be "trimmed."
929  ) {
930  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
931  include(dirname(__FILE__)."/config/get-config.php");
932 
933  $change_limit = 0;
934 
935  if ($in_type == 'c_comdef_meeting') {
936  $change_limit = $change_depth_for_meetings;
937  }
938 
939  if ($change_limit) {
940  // Get rid of oldest change first.
941  $changes = self::GetChangesFromIDAndType($in_type, $in_id);
942 
943  if ($changes instanceof c_comdef_changes) {
944  $ch_objs = $changes->GetChangesObjects();
945 
946  if (is_array($ch_objs)) {
947  $counted = count($ch_objs);
948 
949  while ($counted-- > $change_limit) {
950  $ch_objs[$counted]->DeleteFromDB();
951  }
952  }
953 
954  $changes = null;
955  }
956  }
957  }
958 
959  /*******************************************************************/
960  /** \brief Creates a new change record in the Database.
961 
962  \returns the ID of the user. Null is it failed.
963  */
964  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
965  public static function AddNewChange(
966  $in_user_id_bigint, ///< Integer. The ID of the user making the change.
967  $in_change_type,
968  // Enum. The type of change.
969  // Can be:
970  // - 'comdef_change_type_new' - New object
971  // - 'comdef_change_type_delete' - Deleted the object
972  // - 'comdef_change_type_change' - Changed existing object
973  // - 'comdef_change_type_rollback' - Rolled existing object back to a previous version
974  $in_service_body_id_bigint, ///< Integer. The ID of the Service body for which the user was acting.
975  $in_before_string, ///< Serialized object string. The "before" object, in serialized form.
976  $in_after_string, ///< Serialized object string. The "after" object, in serialized form.
977  $in_object_class_string, ///< The class of the objects.
978  $in_before_obj_id_bigint, ///< Integer, The ID of the Before Object.
979  $in_after_obj_id_bigint, ///< Integer, The ID of the After Object.
980  $in_before_obj_lang_enum = null,///< Enum, the language of the Before Object.
981  $in_after_obj_lang_enum = null, ///< Enum. The language of the After Object.
982  $in_name_string = null, ///< The change's Name (Optional)
983  $in_description_string = null, ///< The description of the change (Optional)
984  $in_lang_enum = null ///< The language for the change (Optional -If not supplied, the server default will be used)
985  ) {
986  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
987  $id = null;
988 
989  if (!$in_lang_enum) {
990  $in_lang_enum = self::GetServer()->GetLocalLang();
991  }
992 
993  if (!$in_lang_enum) {
995  $in_lang_enum = $comdef_global_language;
996  }
997 
998  // Should never happen.
999  if (!$in_lang_enum) {
1000  $in_lang_enum = "en";
1001  }
1002 
1003  $change_obj = new c_comdef_change(self::GetServer(), $in_change_type, $in_user_id_bigint, $in_service_body_id_bigint, $in_before_string, $in_after_string, $in_object_class_string, $in_before_obj_id_bigint, $in_after_obj_id_bigint, $in_before_obj_lang_enum, $in_after_obj_lang_enum, null, $in_name_string, $in_description_string, $in_lang_enum);
1004 
1005  if ($change_obj instanceof c_comdef_change) {
1006  try {
1007  $change_obj->UpdateToDB();
1008 
1009  $id = $change_obj->GetID();
1010  } catch (Exception $e) { // We just eat the exception and return null.
1011  $id = null;
1012  }
1013  }
1014 
1015  $cid = $in_before_obj_id_bigint;
1016  if (!$cid) {
1017  $cid = $in_after_obj_id_bigint;
1018  }
1019 
1020  self::TrimChanges($in_object_class_string, $cid);
1021 
1022  return $id;
1023  }
1024 
1025  /*******************************************************************/
1026  /** \brief Simply returns the namespace of this server.
1027 
1028  \returns A string, with the namespace. The default is the server URI, with "/CoMDEF" appended.
1029  */
1030  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1031  public static function GetNamespace()
1032  {
1033  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1034  return self::$server_instance->_server_namespace;
1035  }
1036 
1037  /*******************************************************************/
1038  /** \brief Simply returns the name of the format table.
1039 
1040  \returns A string, containing the name of the format table.
1041  */
1042  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1043  public static function GetFormatTableName_obj()
1044  {
1045  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1046  return self::$server_instance->_format_table_name;
1047  }
1048 
1049  /*******************************************************************/
1050  /** \brief Simply returns the name of the meetings table.
1051 
1052  \returns A string, containing the name of the meetings table.
1053  */
1054  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1055  public static function GetMeetingTableName_obj()
1056  {
1057  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1058  return self::$server_instance->_meeting_table_name;
1059  }
1060 
1061  /*******************************************************************/
1062  /** \brief Simply returns the name of the changes table.
1063 
1064  \returns A string, containing the name of the changes table.
1065  */
1066  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1067  public static function GetChangesTableName_obj()
1068  {
1069  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1070  return self::$server_instance->_changes_table_name;
1071  }
1072 
1073  /*******************************************************************/
1074  /** \brief Simply returns the name of the service bodies table.
1075 
1076  \returns A string, containing the name of the table.
1077  */
1078  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1079  public static function GetServiceBodiesTableName_obj()
1080  {
1081  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1082  return self::$server_instance->_service_bodies_table_name;
1083  }
1084 
1085  /*******************************************************************/
1086  /** \brief Simply returns the name of the user table.
1087 
1088  \returns A string, containing the name of the table.
1089  */
1090  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1091  public static function GetUserTableName_obj()
1092  {
1093  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1094  return self::$server_instance->_user_table_name;
1095  }
1096 
1097  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1098  public static function GetDatabaseVersionTableName_obj()
1099  {
1100  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1101  return self::$server_instance->_db_version_table_name;
1102  }
1103 
1104  /*******************************************************************/
1105  /** \brief Get the local readable string for the server languages.
1106 
1107  \returns a reference to the array of strings, containing the server languages in human-readable, local form.
1108  */
1109  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1110  public static function GetServerLangs()
1111  {
1112  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1113  return self::GetServer()->_server_lang_names;
1114  }
1115  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1116  public static function GetFormatLangs()
1117  {
1118  return array_merge(self::GetServer()->_server_lang_names, self::GetServer()->_format_lang_names);
1119  }
1120  /*******************************************************************/
1121  /** \brief Get the object list for the server's registered users.
1122 
1123  \returns a reference to the internal c_comdef_users object.
1124  */
1125  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1126  public static function GetServerUsersObj()
1127  {
1128  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1129  return self::GetServer()->_users_obj;
1130  }
1131 
1132  /*******************************************************************/
1133  /** \brief Get the object for a single user, given an ID
1134 
1135  \returns a reference to the internal c_comdef_user object for the user. Null if not found.
1136  */
1137  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1138  public static function GetUserByIDObj(
1139  $in_user_id_bigint ///< An integer, containing the user ID.
1140  ) {
1141  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1142  $ret = null;
1143 
1144  if (0 < intval($in_user_id_bigint)) {
1145  $users_obj = self::GetServer()->_users_obj;
1146 
1147  if ($users_obj instanceof c_comdef_users) {
1148  $ret = $users_obj->GetUserByID($in_user_id_bigint);
1149  }
1150  }
1151 
1152  return $ret;
1153  }
1154 
1155  /*******************************************************************/
1156  /** \brief Given a login, looks up the user, and returns
1157  a reference to that user object.
1158 
1159  \returns a reference to a c_comdef_user object. Null if none.
1160  */
1161  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1162  public static function GetUserByLogin( $in_login ///< A string. The login ID.
1163  )
1164  {
1165  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1166  $ret = null;
1167 
1168  $users_obj = self::GetServer()->_users_obj;
1169 
1170  if ($users_obj instanceof c_comdef_users) {
1171  $ret = $users_obj->GetUserByLogin($in_login);
1172  }
1173 
1174  return $ret;
1175  }
1176 
1177  /*******************************************************************/
1178  /** \brief Given a login and password, looks up the user, and returns
1179  a reference to that user object.
1180 
1181  \returns a reference to a c_comdef_user object. Null if none.
1182  */
1183  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1184  public static function GetUserByLoginCredentials(
1185  $in_login, ///< A string. The login ID.
1186  $in_password ///< A string. the ENCRYPTED password for the user.
1187  ) {
1188  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1189  $ret = null;
1190 
1191  $users_obj = self::GetServer()->_users_obj;
1192 
1193  if ($users_obj instanceof c_comdef_users) {
1194  $ret = $users_obj->GetUserByLoginCredentials($in_login, $in_password);
1195  }
1196 
1197  return $ret;
1198  }
1199 
1200  /*******************************************************************/
1201  /** \brief Get the current logged-in user, as a c_comdef_user instance.
1202 
1203  \returns a reference to a c_comdef_user object, containing the user.
1204  Null if it failed.
1205  */
1206  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1207  public static function GetCurrentUserObj($in_is_ajax = false ///< If it's an AJAX handler, this is true.
1208  )
1209  {
1210  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1211  include(dirname(__FILE__).'/config/get-config.php');
1212 
1213  $ret = null;
1214 
1215  if (!isset($_SESSION)) {
1216  session_start();
1217  }
1218 
1219  if (isset($_SESSION[$admin_session_name])) {
1220  list ( $login_id, $encrypted_password ) = explode("\t", $_SESSION[$admin_session_name]);
1221  $ret = self::GetUserByLoginCredentials($login_id, $encrypted_password);
1222  }
1223 
1224  return $ret;
1225  }
1226 
1227  /*******************************************************************/
1228  /** \brief Find out if the user is a server admin.
1229 
1230  \returns a boolean. True if the user is a server admin.
1231  */
1232  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1233  public static function IsUserServerAdmin(
1234  $in_user_obj = null, ///< A reference to a c_comdef_user object instance. If null, the current user will be checked.
1235  $in_is_ajax = false ///< If it's an AJAX handler, we don't regenerate the session. Some browsers seem antsy about that.
1236  ) {
1237  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1238  $ret = false;
1239 
1240  if (!($in_user_obj instanceof c_comdef_user)) {
1241  $in_user_obj = self::GetCurrentUserObj($in_is_ajax);
1242  }
1243 
1244  if ($in_user_obj instanceof c_comdef_user) {
1245  $ret = ($in_user_obj->GetUserLevel() == _USER_LEVEL_SERVER_ADMIN);
1246  }
1247 
1248  return $ret;
1249  }
1250 
1251 
1252  /*******************************************************************/
1253  /** \brief Find out if the user is a service body admin.
1254 
1255  \returns a boolean. True if the user is a service body admin.
1256  */
1257  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1258  public static function IsUserServiceBodyAdmin(
1259  $in_user_obj = null, ///< A reference to a c_comdef_user object instance. If null, the current user will be checked.
1260  $in_is_ajax = false ///< If it's an AJAX handler, we don't regenerate the session. Some browsers seem antsy about that.
1261  ) {
1262  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1263  $ret = false;
1264 
1265  if (!($in_user_obj instanceof c_comdef_user)) {
1266  $in_user_obj = self::GetCurrentUserObj($in_is_ajax);
1267  }
1268 
1269  if ($in_user_obj instanceof c_comdef_user) {
1270  $ret = ($in_user_obj->GetUserLevel() == _USER_LEVEL_SERVICE_BODY_ADMIN);
1271  }
1272 
1273  return $ret;
1274  }
1275  /*******************************************************************/
1276  /** \brief Given a login and password, looks up the user, and returns
1277  an encrypted password for that user.
1278 
1279  \returns a string, with the encrypted password. Null if none.
1280  */
1281  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1282  public static function GetEncryptedPW(
1283  $in_login, ///< A string. The login ID.
1284  $in_password ///< A string. the UNENCRYPTED password for the user.
1285  ) {
1286  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1287  $ret = null;
1288 
1289  $users_obj = self::GetServer()->_users_obj;
1290 
1291  if ($users_obj instanceof c_comdef_users) {
1292  $ret = $users_obj->GetEncryptedPW($in_login, $in_password);
1293  }
1294 
1295  return $ret;
1296  }
1297 
1298  /*******************************************************************/
1299  /** \brief Get the objects for all users of a certain user level.
1300 
1301  \returns an associative array, with references to the c_comdef_user objects for the relevant users as values, and the user IDs as keys. Null if not found.
1302  */
1303  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1304  public static function GetUsersByLevelObj(
1305  $in_user_level_bigint, ///< An integer, containing the user level.
1306  $in_or_higher = false, ///< A Boolean. Set this to true to get all users of the given level or higher (numerically lower). Default is false, so only users of the exact level are given.
1307  $in_include_disabled = false ///< A Boolean. Set this to true to allow disabled users to be included.
1308  ) {
1309  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1310  $ret_array = null;
1311 
1312  $users_obj = self::GetServer()->_users_obj;
1313 
1314  if ($users_obj instanceof c_comdef_users) {
1315  $user_array = $users_obj->GetUsersArray();
1316 
1317  foreach ($user_array as &$user_obj) {
1318  if (($user_obj->GetUserLevel() > 0) && ($in_include_disabled || ($user_obj->GetUserLevel() != _USER_LEVEL_DISABLED)) && (($user_obj->GetUserLevel() == $in_user_level_bigint) || ($in_or_higher && ($user_obj->GetUserLevel() < $in_user_level_bigint)))) {
1319  $ret_array[$user_obj->GetID()] = $user_obj;
1320  }
1321  }
1322  }
1323 
1324  return $ret_array;
1325  }
1326 
1327  /*******************************************************************/
1328  /** \brief Get the object for a single service body, given an ID
1329 
1330  \returns a reference to the internal c_comdef_service_body object for the service body. Null if not found.
1331  */
1332  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1333  public static function GetServiceBodyByIDObj(
1334  $in_service_body_id_bigint ///< An integer, containing the service body ID.
1335  ) {
1336  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1337  $ret = null;
1338  $server = self::GetServer();
1339  if ($server instanceof c_comdef_server) {
1340  $array_obj = $server->GetServiceBodyArray();
1341  if (is_array($array_obj) && count($array_obj)) {
1342  foreach ($array_obj as &$sb) {
1343  if ($sb instanceof c_comdef_service_body) {
1344  $id = $sb->GetID();
1345  if (intval($in_service_body_id_bigint) == intval($id)) {
1346  $ret = $sb;
1347  }
1348  }
1349  }
1350  }
1351  }
1352 
1353  return $ret;
1354  }
1355 
1356  /*******************************************************************/
1357  /** \brief Return the IDs of an entire Service body hierarchy.
1358 
1359  \returns an array of integers. These are the Service body IDs.
1360  */
1361  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1362  public static function GetServiceBodyHierarchyIDs(
1363  $in_service_body_id_bigint ///< An integer, containing the service body ID.
1364  ) {
1365  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1366  $ret = array();
1367  $server = self::GetServer();
1368  if ($server instanceof c_comdef_server) {
1369  $array_obj = $server->GetServiceBodyArray();
1370  if (is_array($array_obj) && count($array_obj)) {
1371  foreach ($array_obj as &$sb) {
1372  if ($sb instanceof c_comdef_service_body) {
1373  $id = $sb->GetID();
1374  $parent_id = $sb->GetOwnerID();
1375  if (intval($in_service_body_id_bigint) == intval($id)) {
1376  array_push($ret, $id);
1377  } elseif (intval($in_service_body_id_bigint) == intval($parent_id)) {
1378  $ret = array_merge($ret, self::GetServiceBodyHierarchyIDs($id));
1379  }
1380  }
1381  }
1382  }
1383  }
1384 
1385  return $ret;
1386  }
1387 
1388  /*******************************************************************/
1389  /** \brief Given an ID and a language for a format, as well as a code,
1390  returns true if the code does NOT appear in the DB.
1391 
1392  \returns true, if the format key is unique for the language.
1393 
1394  \throws an exception if the SQL query fails.
1395  */
1396  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1397  public static function IsFormatKeyUnique(
1398  $in_key_string, ///< A string. The key for which to search.
1399  $in_lang_enum ///< The language for the format.
1400  ) {
1401  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1402  $sql = "SELECT * FROM `".self::GetFormatTableName_obj()."` WHERE key_string=? AND lang_enum=?";
1403 
1404  $rows = c_comdef_dbsingleton::preparedQuery($sql, array ( $in_key_string, $in_lang_enum ));
1405  if (is_array($rows) && count($rows)) {
1406  return false;
1407  }
1408 
1409  return true;
1410  }
1411 
1412  /*******************************************************************/
1413  /** \brief Given an ID and a language for a format, it returns one instance.
1414 
1415  This will return one c_comdef_format object, with the parent this server
1416  (Not a c_comdef_formats object).
1417 
1418  \returns a new c_comdef_format object.Null if it failed.
1419 
1420  \throws an exception if the SQL query fails.
1421  */
1422  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1423  public static function GetOneFormat(
1424  $in_id_bigint, ///< The ID of the formatShared (An integer)
1425  $in_lang_enum ///< The language for the format.
1426  ) {
1427  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1428  $sql = "SELECT * FROM `".self::GetFormatTableName_obj()."` WHERE shared_id_bigint=? AND lang_enum=? LIMIT 1";
1429 
1430  $rows = c_comdef_dbsingleton::preparedQuery($sql, array ( $in_id_bigint, $in_lang_enum ));
1431  if (is_array($rows) && count($rows)) {
1432  $rs = $rows[0];
1433  // We use the static function in the c_comdef_meeting class to process the data for the meeting.
1434  return new c_comdef_format(
1435  self::GetServer(),
1436  $rs['shared_id_bigint'],
1437  $rs['format_type_enum'],
1438  $rs['key_string'],
1439  $rs['icon_blob'],
1440  $rs['worldid_mixed'],
1441  $rs['lang_enum'],
1442  $rs['name_string'],
1443  $rs['description_string']
1444  );
1445  }
1446 
1447  return null;
1448  }
1449 
1450  /*******************************************************************/
1451  /** \brief Given an ID for a meeting, it returns true if the meeting currently exists.
1452 
1453  \returns true if the meeting exists; false, otherwise.
1454 
1455  \throws an exception if the SQL query fails.
1456  */
1457  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1458  public static function DoesMeetingExist(
1459  $in_id_bigint ///< The ID of the meeting (An integer)
1460  ) {
1461  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1462  $sql = "SELECT id_bigint FROM `".self::GetMeetingTableName_obj()."_main` WHERE ".self::GetMeetingTableName_obj()."_main.id_bigint=? LIMIT 1";
1463 
1464  $ret = false;
1465 
1466  $rows = c_comdef_dbsingleton::preparedQuery($sql, array ( $in_id_bigint ));
1467  if (is_array($rows) && count($rows)) {
1468  $ret = true;
1469  }
1470 
1471  return $ret;
1472  }
1473 
1474  /*******************************************************************/
1475  /** \brief Given an ID for a meeting, it returns one instance.
1476 
1477  This will return one c_comdef_meeting object, with the parent this server
1478  (Not a c_comdef_meetings object).
1479 
1480  \returns a new c_comdef_meeting object.Null if it failed.
1481 
1482  \throws an exception if the SQL query fails.
1483  */
1484  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1485  public static function GetOneMeeting(
1486  $in_id_bigint, ///< The ID of the meeting (An integer)
1487  $test_only = false ///< If true, then this function will only return Boolean true or false (true if the meeting exists)
1488  ) {
1489  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1490  $sql = "SELECT * FROM `".self::GetMeetingTableName_obj()."_main` WHERE ".self::GetMeetingTableName_obj()."_main.id_bigint=? LIMIT 1";
1491 
1492  $rows = c_comdef_dbsingleton::preparedQuery($sql, array ( $in_id_bigint ));
1493  if (is_array($rows) && count($rows)) {
1494  if ($test_only) {
1495  return true;
1496  }
1497 
1498  foreach ($rows as $row) {
1499  // We use the static function in the c_comdef_meeting class to process the data for the meeting.
1500  $meeting_row = c_comdef_meeting::process_meeting_row($row);
1501  // One difference between this type of meeting and others, is that the parent is the server, not a c_comdef_meetngs object.
1502  return new c_comdef_meeting(self::GetServer(), $meeting_row);
1503  }
1504  }
1505 
1506  if ($test_only) {
1507  return false;
1508  }
1509 
1510  return null;
1511  }
1512 
1513  /*******************************************************************/
1514  /** \brief Given an ID for a change, it returns one instance.
1515 
1516  This will return one c_comdef_change object, with the parent this server
1517  (Not a c_comdef_changes object).
1518 
1519  \returns a new c_comdef_change object.Null if it failed.
1520 
1521  \throws an exception if the SQL query fails.
1522  */
1523  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1524  public static function GetOneChange(
1525  $in_id_bigint ///< The ID of the change (An integer)
1526  ) {
1527  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1528  $ret = null;
1529 
1530  $sql = "SELECT * FROM `".self::GetChangesTableName_obj()."` WHERE id_bigint=? LIMIT 1";
1531 
1532  $changes = self::GetServer()->GetChangesFromSQL($sql, array ( $in_id_bigint ));
1533 
1534  if ($changes instanceof c_comdef_changes) {
1535  $c_array = $changes->GetChangesObjects();
1536 
1537  if (is_array($c_array) && count($c_array)) {
1538  // Just to spike an associative-only array. Silly, I know, but I've had problems in the past. PHP is wacky.
1539  foreach ($c_array as $change) {
1540  $ret = $change;
1541  break;
1542  }
1543  }
1544  }
1545 
1546  return $ret;
1547  }
1548 
1549  /*******************************************************************/
1550  /** \brief Given an ID for a user, it returns one instance.
1551 
1552  This will return one c_comdef_user object, with the parent this server
1553  (Not a c_comdef_users object).
1554 
1555  \returns a new c_comdef_user object.Null if it failed.
1556  */
1557  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1558  public static function GetOneUser(
1559  $in_id_bigint ///< The ID of the user (An integer)
1560  ) {
1561  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1562  $ret = null;
1563 
1564  $sql = "SELECT * FROM `".self::GetUserTableName_obj()."` WHERE id_bigint=? LIMIT 1";
1565 
1566  $rows = c_comdef_dbsingleton::preparedQuery($sql, array ( $in_id_bigint ));
1567  if (is_array($rows) && count($rows)) {
1568  foreach ($rows as $row) {
1569  $ret = new c_comdef_user(
1571  $row['id_bigint'],
1572  $row['user_level_tinyint'],
1573  $row['email_address_string'],
1574  $row['login_string'],
1575  $row['password_string'],
1576  $row['lang_enum'],
1577  $row['name_string'],
1578  $row['description_string'],
1579  $row['owner_id_bigint'],
1580  $row['last_access_datetime']
1581  );
1582  }
1583  }
1584 
1585  return $ret;
1586  }
1587 
1588  /*******************************************************************/
1589  /** \brief Get a series of meetings, each identified by an ID. This does
1590  not filter by any of the other major criteria. It is designed to
1591  facilitate direct access to meeting objects.
1592 
1593  \returns a new c_comdef_meetings object, containing the meetings. Null if it failed.
1594  */
1595  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1596  public static function GetMeetingsByID(
1597  $in_id_bigint_array ///< The ID of the meetings (An array of integers)
1598  ) {
1599  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1600  $sql = "SELECT * FROM `".self::GetMeetingTableName_obj()."_main` WHERE ";
1601 
1602  $first = true;
1603 
1604  // We don't actually care what the array contains. We're just counting them out.
1605  foreach ($in_id_bigint_array as $in_id_bigint) {
1606  if (!$first) {
1607  $sql .= " OR ";
1608  } else {
1609  $first = false;
1610  }
1611 
1612  $sql .= "(".self::GetMeetingTableName_obj()."_main.id_bigint=?)";
1613  }
1614 
1615  return self::GetMeetingsFromSQL($sql, $in_id_bigint_array);
1616  }
1617 
1618  /*******************************************************************/
1619  /** \brief Given a set of one or more main criteria, returns a new
1620  c_comdef_meetings object with instances of those meetings, loaded
1621  from the database.
1622 
1623  This is the big kahuna. Meeting searches will all use this function
1624  as a fulcrum for their searches.
1625 
1626  NOTE TO UPTIGHT PROGRAMMERS: Yeah, it's a big, massive function
1627  with a gazillion multi-purpose parameters.
1628 
1629  Learn to live with it. It works fine, and makes sense for the context.
1630  I could break it into a bunch of smaller functions, but that would
1631  increase the complexity and reduce performance.
1632 
1633  \returns a new c_comdef_meetings object, containing the meetings.
1634  Null if it failed.
1635 
1636  \throws an exception if the SQL query fails.
1637  */
1638  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1639  public static function GetMeetings(
1640  $in_service_body_id_bigint_array = null,
1641  // An array of integers. Unlike the formats criteria, these do an OR function, as each record only has
1642  // one Service Body ID field, so each selection broadens the search. If there are no IDs selected, or
1643  // only NOT IDs have been selected, then all the Service bodies will be searched, with the exception
1644  // of any that are selected as NOT (Negative value).
1645  $in_lang_filter_array = null,
1646  // If an element of this array is set to a language enum ("en", "es", etc.), it will only return meetings whose
1647  // 'lang_enum' field is of that value. If the array is null, all languages are searched. If the enum is preceded
1648  // by a minus sign (-), then the language is filtered against in the search.
1649  $in_weekday_tinyint_array = null, // The weekday (An array of integer 1-Sunday, 7-Saturday). Optional. If null, all days will be returned.
1650  // Each day chosen widens the search. If the weekday is negative, then that is specifically filtered against in
1651  // the search.
1652  $in_formats = null,
1653  // An array of integers. These are formats. The filtering will be an "AND" filtering, so qualified meetings
1654  // must have all of the given formats. If a format is given as a negative number, it is a NOT. Make sure that
1655  // you don't have two versions of the same format code, as nothing will be returned.
1656  $in_start_after = null, ///< An epoch time (seconds, as returned by time()), that denotes the earliest starting time allowed.
1657  $in_start_before = null, ///< An epoch time (seconds, as returned by time()), that denotes the latest starting time allowed.
1658  $in_end_before = null, ///< An epoch time (seconds, as returned by time()), that denotes the latest ending time allowed.
1659  $in_min_duration = null, ///< The number of seconds a meeting should last as a minimum.
1660  $in_max_duration = null, ///< The number of seconds a meeting can last, at most.
1661  $in_search_rect_array = null,
1662  // An array of floating-point numbers, representing longitude and latitude for a rectangle. This is used
1663  // to restrict the search to a certain geographic area. It is an associative array:
1664  // - ['east'] = longitude of the Eastern side of the rectangle
1665  // - ['west'] = longitude of the Western side of the rectangle
1666  // - ['north'] = latitude of the Northern side of the rectangle
1667  // - ['south'] = latitude of the Southern side of the rectangle
1668  $in_first = null,
1669  // A positive integer. This is for paged results. This is the index (0-based) of the first result to be returned.
1670  // If $in_num is specified, and this is null, then it is assumed to be 0. If $in_num is null, then this is ignored.
1671  &$in_num = null,
1672  // A reference to a positive integer. This is the maximum number of results to return. If null, then there will be
1673  // limits placed on the query.
1674  // If less than the maximum are returned, this is adjusted to reflect how many were returned.
1675  //
1676  // NOTE: For non-MySQL and non-Oracle DBs, this may not equal the number of meetings returned in the function
1677  // result! This is because, for those databases, filtering by format code needs to be done after the actual
1678  // database query.
1679  //
1680  // This will have the actual value of the number of results in the database query, so you can use this to
1681  // walk through the database. If you need the actual number of meetings returned, the best way to do this is
1682  // to do a c_comdef_meetings::GetNumMeetings() function on the returned object.
1683  $in_published = 0,
1684  // Indicates whether or not to search for published meetings. This only counts if the user is logged in.
1685  // - -1 Search for ONLY unpublished meetings
1686  // - 0 Search for published and unpublished meetings.
1687  // - 1 Search for ONLY published meetings.
1688  $formats_comparison_operator = "AND"
1689  // Indicates whether formats should be searched using AND or OR logic
1690  ) {
1691  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
1692  $previous = false; // This is used to tell subsequent tests to use AND instead of WHERE
1693 
1694  $sql = "SELECT * FROM `".self::GetMeetingTableName_obj()."_main`";
1695  $ar = array ( );
1696 
1697  if (is_array($in_service_body_id_bigint_array) && count($in_service_body_id_bigint_array)) {
1698  $sql .= " WHERE (";
1699  $previous = true;
1700  $first = true;
1701  foreach ($in_service_body_id_bigint_array as $service_body_id) {
1702  $service_body_id = intval($service_body_id);
1703  $sql_x = "";
1704  if ($service_body_id < 0) {
1705  $service_body_id = abs($service_body_id);
1706  $sql_x = " NOT ";
1707 
1708  if (!$first) {
1709  $sql_x = " AND $sql_x";
1710  }
1711 
1712  $first = true; // This makes the OR get skipped.
1713  }
1714 
1715  if (!$first) {
1716  $sql_x .= " OR ";
1717  } else {
1718  $first = false;
1719  }
1720 
1721  $sql .= "$sql_x(".self::GetMeetingTableName_obj()."_main.service_body_bigint=?)";
1722  array_push($ar, $service_body_id);
1723  }
1724  $sql .= ")";
1725  }
1726 
1727  if (is_array($in_lang_filter_array) && count($in_lang_filter_array)) {
1728  if ($previous) {
1729  $sql .= " AND ";
1730  } else {
1731  $sql .= " WHERE ";
1732  $previous = true;
1733  }
1734 
1735  $sql .= "(";
1736 
1737  $first = true;
1738  foreach ($in_lang_filter_array as $lang) {
1739  $not = preg_match("|^\-(.*)|", $lang, $matches);
1740 
1741  $sql_x = "";
1742  if ($not) {
1743  $lang = $matches[1];
1744  $sql_x = " NOT ";
1745 
1746  if (!$first) {
1747  $sql_x = " AND $sql_x";
1748  }
1749 
1750  $first = true; // This makes the OR get skipped.
1751  }
1752 
1753  if (!$first) {
1754  $sql_x .= " OR ";
1755  } else {
1756  $first = false;
1757  }
1758 
1759  $sql .= "$sql_x(".self::GetMeetingTableName_obj()."_main.lang_enum=?)";
1760 
1761  array_push($ar, $lang);
1762  }
1763  $sql .= ")";
1764  }
1765 
1766  if (is_array($in_weekday_tinyint_array) && count($in_weekday_tinyint_array)) {
1767  $valid = false;
1768 
1769  foreach ($in_weekday_tinyint_array as $weekday) {
1770  if (abs(intval($weekday)) > 0 && abs(intval($weekday)) < 8) {
1771  $valid = true;
1772  }
1773  }
1774 
1775  if ($valid) {
1776  if ($previous) {
1777  $sql .= " AND ";
1778  } else {
1779  $sql .= " WHERE ";
1780  $previous = true;
1781  }
1782 
1783  $sql .= "(";
1784 
1785  $first = true;
1786  foreach ($in_weekday_tinyint_array as $weekday) {
1787  $weekday = intval($weekday);
1788  $sql_x = "";
1789  if ($weekday < 0) {
1790  $weekday = abs($weekday);
1791  $sql_x = " NOT ";
1792 
1793  if (!$first) {
1794  $sql_x = " AND $sql_x";
1795  }
1796 
1797  $first = true; // This makes the OR get skipped.
1798  }
1799 
1800  if (!$first) {
1801  $sql_x .= " OR ";
1802  } else {
1803  $first = false;
1804  }
1805 
1806  $sql .= "$sql_x(".self::GetMeetingTableName_obj()."_main.weekday_tinyint=?)";
1807  array_push($ar, $weekday-1);
1808  }
1809  $sql .= ")";
1810  }
1811  }
1812 
1813  // We explicitly set null entries, because we've seen problems with using nulls.
1814  if (null != $in_start_after) {
1815  $in_start_after = date("H:i:00", intval($in_start_after));
1816  } else {
1817  $in_start_after = "00:00:00";
1818  }
1819 
1820  if (null != $in_start_before) {
1821  $in_start_before = date("H:i:00", intval($in_start_before));
1822  } else {
1823  $in_start_before = "00:00:00";
1824  }
1825 
1826  if (null != $in_end_before) {
1827  $in_end_before = intval($in_end_before);
1828  } else {
1829  $in_end_before = null;
1830  }
1831 
1832  if (null != $in_min_duration) {
1833  $in_min_duration = date("H:i:00", intval($in_min_duration));
1834  } else {
1835  $in_min_duration = "00:00:00";
1836  }
1837 
1838  if (null != $in_max_duration) {
1839  $in_max_duration = date("H:i:00", intval($in_max_duration));
1840  } else {
1841  $in_max_duration = "00:00:00";
1842  }
1843 
1844  if ($in_start_after != "00:00:00") {
1845  if ($previous) {
1846  $sql .= " AND ";
1847  } else {
1848  $sql .= " WHERE ";
1849  $previous = true;
1850  }
1851  $sql .= self::GetMeetingTableName_obj()."_main.start_time>?";
1852 
1853  array_push($ar, $in_start_after);
1854  }
1855 
1856  if ($in_start_before != "00:00:00") {
1857  if ($previous) {
1858  $sql .= " AND ";
1859  } else {
1860  $sql .= " WHERE ";
1861  $previous = true;
1862  }
1863  $sql .= self::GetMeetingTableName_obj()."_main.start_time<?";
1864 
1865  array_push($ar, $in_start_before);
1866  }
1867 
1868  if ($in_end_before != null) {
1869  if ($previous) {
1870  $sql .= " AND ";
1871  } else {
1872  $sql .= " WHERE ";
1873  $previous = true;
1874  }
1875 
1876  $sql .= "TIME_TO_SEC(".self::GetMeetingTableName_obj()."_main.start_time+".self::GetMeetingTableName_obj()."_main.duration_time)<=?";
1877 
1878  array_push($ar, $in_end_before);
1879  }
1880 
1881  if ($in_min_duration != "00:00:00") {
1882  if ($previous) {
1883  $sql .= " AND ";
1884  } else {
1885  $sql .= " WHERE ";
1886  $previous = true;
1887  }
1888  $sql .= self::GetMeetingTableName_obj()."_main.duration_time>=?";
1889 
1890  array_push($ar, $in_min_duration);
1891  }
1892 
1893  if ($in_max_duration != "00:00:00") {
1894  if ($previous) {
1895  $sql .= " AND ";
1896  } else {
1897  $sql .= " WHERE ";
1898  $previous = true;
1899  }
1900  $sql .= self::GetMeetingTableName_obj()."_main.duration_time<=?";
1901 
1902  array_push($ar, $in_max_duration);
1903  }
1904 
1905  if (is_array($in_search_rect_array) && isset($in_search_rect_array['east']) && isset($in_search_rect_array['west']) && isset($in_search_rect_array['north']) && isset($in_search_rect_array['south'])) {
1906  if ($previous) {
1907  $sql .= " AND ";
1908  } else {
1909  $sql .= " WHERE ";
1910  $previous = true;
1911  }
1912 
1913  $east = floatval($in_search_rect_array['east']);
1914  $west = floatval($in_search_rect_array['west']);
1915  $north = floatval($in_search_rect_array['north']);
1916  $south = floatval($in_search_rect_array['south']);
1917  $sql .= "(";
1918  if ($east > $west) {
1919  $sql .= "(longitude >= $west) AND (longitude <= $east)";
1920  } else {
1921  $sql .= "(longitude <= $west) AND (longitude >= $east)";
1922  }
1923 
1924  $sql .= " AND (latitude <= $north) AND (latitude >= $south)";
1925  $sql .= ")";
1926  }
1927 
1928  // Logged-in users can see both published and unpublished meetings.
1929  if ($in_published != 0) {
1930  if ($previous) {
1931  $sql .= " AND ";
1932  } else {
1933  $sql .= " WHERE ";
1934  $previous = true;
1935  }
1936 
1937  if ($in_published == -1) {
1938  $sql .= "(published=0)";
1939  } else {
1940  $sql .= "(published=1)";
1941  }
1942  }
1943 
1944  $ret = null;
1945 
1946  if (is_array($in_formats) && count($in_formats)) {
1947  $column = self::GetMeetingTableName_obj()."_main.formats";
1948 
1949  $formats_include = array();
1950  $formats_exclude = array();
1951  foreach ($in_formats as $format) {
1952  if ($format > 0) {
1953  array_push($formats_include, $format);
1954  } else {
1955  array_push($formats_exclude, abs($format));
1956  }
1957  }
1958 
1959  if (count($formats_include)) {
1960  if ($previous) {
1961  $sql .= " AND (";
1962  } else {
1963  $sql .= " WHERE (";
1964  $previous = true;
1965  }
1966 
1967  $first = true;
1968  foreach ($formats_include as $format) {
1969  if (!$first) {
1970  if ($formats_comparison_operator == "OR") {
1971  $sql .= " OR ";
1972  } else {
1973  $sql .= " AND ";
1974  }
1975  } else {
1976  $first = false;
1977  }
1978 
1979  $sql .= "($column REGEXP '(^|,)$format(,|\$)')";
1980  }
1981 
1982  $sql .= ")";
1983  }
1984 
1985  if (count($formats_exclude)) {
1986  if ($previous) {
1987  $sql .= " AND (";
1988  } else {
1989  $sql .= " WHERE (";
1990  $previous = true;
1991  }
1992 
1993  $first = true;
1994  foreach ($formats_exclude as $format) {
1995  if (!$first) {
1996  $sql .= " AND ";
1997  } else {
1998  $first = false;
1999  }
2000 
2001  $sql .= "NOT ($column REGEXP '(^|,)$format(,|\$)')";
2002  }
2003 
2004  $sql .= ")";
2005  }
2006  }
2007 
2008  if (!$ret) {
2009  $sql .= " ORDER BY service_body_bigint, id_bigint";
2010 
2011  if (intval($in_num)) {
2012  $in_first = intval($in_first);
2013  $in_num = intval($in_num);
2014  $sql .= " LIMIT $in_first, $in_num";
2015  }
2016 
2017  $ret = self::GetMeetingsFromSQL($sql, $ar);
2018 
2019  if (intval($in_num)) {
2020  $in_num = count($ret->GetMeetingObjects());
2021  }
2022 
2023  if ($ret && isset($east) && isset($west) && isset($north) && isset($south)) {
2024  $center_lat = ($north + $south) / 2.0;
2025  $center_long = ($east + $west) / 2.0;
2026  $meetings = $ret->GetMeetingObjects();
2027  foreach ($meetings as &$meeting) {
2028  $dist = floatval(c_comdef_meetings::GetDistance($center_lat, $center_long, $meeting->GetMeetingDataValue('latitude'), $meeting->GetMeetingDataValue('longitude')));
2029  $meeting->_distance_in_km = $dist;
2030  $meeting->_distance_in_miles = $dist / 1.609344;
2031  $meeting->AddDataField('distance_in_km', 'distance_in_km', $meeting->_distance_in_km, null, 0, true);
2032  $meeting->AddDataField('distance_in_miles', 'distance_in_miles', $meeting->_distance_in_miles, null, 0, true);
2033  }
2034  }
2035  }
2036  return $ret;
2037  }
2038 
2039  /*******************************************************************/
2040  /** \brief Returns a c_comdef_meetings_object, containing all the meetings
2041  directly "owned" by the Service Body whose ID is submitted.
2042 
2043  \returns a new c_comdef_meetings object, containing the meetings.
2044  Null if it failed.
2045 
2046  \throws an exception if the SQL query fails.
2047  */
2048  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2049  public static function GetMeetingsForAServiceBody(
2050  $in_sb_id ///< An integer. The ID of the Service Body.
2051  ) {
2052  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2053  $sql = "SELECT * FROM `".self::GetMeetingTableName_obj()."_main` WHERE ".self::GetMeetingTableName_obj()."_main.service_body_bigint=? ORDER BY id_bigint";
2054 
2055  return self::GetMeetingsFromSQL($sql, array ( $in_sb_id ));
2056  }
2057 
2058  /*******************************************************************/
2059  /** \brief Returns a c_comdef_meetings_object, containing all the meetings (Published and unpublished).
2060 
2061  \returns a new c_comdef_meetings object, containing the meetings.
2062  Null if it failed.
2063 
2064  \throws an exception if the SQL query fails.
2065  */
2066  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2067  public static function GetAllMeetings(
2068  &$in_out_numResults, ///< This must be supplied. It is a pass-by-reference that indicates how many meetings are being returned.
2069  $in_numResults = null, ///< This is how many results we want in this call.
2070  $in_startIndex = null ///< This is the 0-based starting index
2071  ) {
2072  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2073  $in_out_numResults = 0;
2074 
2075  if (!isset($in_startIndex)) {
2076  $in_startIndex = 0;
2077  }
2078 
2079  if (isset($in_numResults)) {
2080  $in_numResults += $in_startIndex;
2081  } else {
2082  $in_startIndex = null;
2083  }
2084 
2085  $sql = "SELECT * FROM `".self::GetMeetingTableName_obj()."_main`";
2086 
2087  if ($in_startIndex || $in_numResults) {
2088  $sql .= ' LIMIT ';
2089 
2090  $sql .= $in_startIndex.', '.$in_numResults;
2091  }
2092 
2093  $ret = self::GetMeetingsFromSQL($sql);
2094 
2095  if ($ret instanceof c_comdef_meetings) {
2096  $in_out_numResults = $ret->GetNumMeetings();
2097  }
2098 
2099  return $ret;
2100  }
2101 
2102  /*******************************************************************/
2103  /** \brief This is an alternative to the MySQL REGEXP test. It will
2104  go through all the meetings returned by a broad query, and remove
2105  any that do not contain all of the given formats.
2106 
2107  \returns the passed-in c_comdef_meetings object, containing the remaining meetings. Null if it failed.
2108  */
2109  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2110  private static function ParseMeetingsByFormats(
2111  $in_meetings, ///< The result of c_comdef_server::GetMeetingsFromSQL()
2112  $in_formats ///< An array of integers. These are formats. The filtering will be an "AND" filtering, so qualified meetings must have all of the given formats.
2113  ) {
2114  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2115  $meetings = $in_meetings->GetMeetingObjects();
2116  foreach ($meetings as &$meeting) {
2117  $data = $meeting->GetMeetingData();
2118  $formats = $data['formats'];
2119  $found = 0;
2120  foreach ($formats as $key => $value) {
2121  if (false !== array_search(intval($key), $in_formats)) {
2122  $found++;
2123  }
2124  }
2125 
2126  // If we didn't find them all, we nuke the meeting.
2127  if ($found != count($in_formats)) {
2128  $in_meetings->RemoveMeeting($meeting->GetID());
2129  }
2130  }
2131 
2132  return ( $in_meetings );
2133  }
2134 
2135  /*******************************************************************/
2136  /** \brief Returns a set of two coordinates that define a rectangle
2137  that encloses all of the meetings.
2138 
2139  \returns a dictionary, with the two coordinates.
2140  */
2141  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2142  public static function GetCoverageArea()
2143  {
2144  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2145  $sql = "SELECT longitude, latitude FROM `".self::GetMeetingTableName_obj()."_main` WHERE `published`='1'";
2146 
2147  $ret = null;
2148 
2149  try {
2150  $arr = array();
2151  $rows = c_comdef_dbsingleton::preparedQuery($sql, $arr);
2152  if (is_array($rows) && count($rows)) {
2153  $nw_corner = array ( "longitude" => false, "latitude" => false );
2154  $se_corner = array ( "longitude" => false, "latitude" => false );
2155 
2156  foreach ($rows as $row) {
2157  $lon = max(-180.0, min(180.0, floatval($row["longitude"])));
2158  $lat = max(-90.0, min(90.0, floatval($row["latitude"])));
2159  if (!(($lon == 0) && ($lat == 0)) && (abs($lat) < 90)) {
2160  if ($nw_corner["longitude"] === false) {
2161  $nw_corner["longitude"] = $lon;
2162  } else {
2163  // OK. The IDL (International Date Line) gives us gas. We need to see if the two values are on either side of it.
2164  // If so, then we'll need to reverse the longitude checks.
2165  if ((abs($lon) > 90) && (0 <= $lon) && (0 > $nw_corner["longitude"])) {
2166  $nw_corner["longitude"] = $lon;
2167  } else if ((abs($lon) > 90) && (0 > $lon) && (0 <= $nw_corner["longitude"])) {
2168  continue;
2169  } else {
2170  $nw_corner["longitude"] = min($lon, $nw_corner["longitude"]);
2171  }
2172  }
2173 
2174  if ($se_corner["longitude"] === false) {
2175  $se_corner["longitude"] = $lon;
2176  } else {
2177  if ((abs($lon) > 90) && (0 > $lon) && (0 <= $se_corner["longitude"])) {
2178  $se_corner["longitude"] = $lon;
2179  } else if ((abs($lon) > 90) && (0 <= $lon) && (0 > $se_corner["longitude"])) {
2180  continue;
2181  } else {
2182  $se_corner["longitude"] = max($lon, $se_corner["longitude"]);
2183  }
2184  }
2185 
2186  if ($nw_corner["latitude"] === false) {
2187  $nw_corner["latitude"] = $lat;
2188  } else {
2189  $nw_corner["latitude"] = max($lat, $nw_corner["latitude"]);
2190  }
2191 
2192  if ($se_corner["latitude"] === false) {
2193  $se_corner["latitude"] = $lat;
2194  } else {
2195  $se_corner["latitude"] = min($lat, $se_corner["latitude"]);
2196  }
2197  }
2198  }
2199  }
2200 
2201  $ret["nw_corner"] = $nw_corner;
2202  $ret["se_corner"] = $se_corner;
2203  } catch (Exception $e) {
2204  $ret = null;
2205  }
2206 
2207  return $ret;
2208  }
2209 
2210  /*******************************************************************/
2211  /** \brief Given an SQL statement and a value array (for PDO prepared
2212  statements), return a new c_comdef_meetings object, loaded with the
2213  instances of the meetings that were returned from the query.
2214 
2215  \returns a new c_comdef_meetings object, containing the meetings. Null if it failed.
2216 
2217  \throws an exception if the SQL query fails.
2218  */
2219  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2220  private static function GetMeetingsFromSQL(
2221  $in_sql, ///< The prepared statement SQL query
2222  $in_value_array = null ///< An array of values for the prepared statement.
2223  ) {
2224  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2225  $rows = c_comdef_dbsingleton::preparedQuery($in_sql, $in_value_array);
2226 
2227  $meeting_data = array();
2228  $this_meetings_object = null;
2229 
2230  if (is_array($rows) && count($rows)) {
2231  foreach ($rows as $row) {
2232  // We use the static function in the c_comdef_meeting class to process the data for the meeting.
2233  $meeting_row = c_comdef_meeting::process_meeting_row($row);
2234  // At this point, we have all the data for this one meeting, culled from its three tables and aggregated into an array.
2235  // Add this to our aggregator array.
2236  $meeting_data[$row['id_bigint']] = $meeting_row;
2237  }
2238 
2239  // We now instantiate a c_comdef_meetings object, and create our c_comdef_meeting objects.
2240  $this_meetings_object = new c_comdef_meetings(self::GetServer(), $meeting_data);
2241  }
2242 
2243  return $this_meetings_object;
2244  }
2245 
2246  /*******************************************************************/
2247  /** \brief Gets a list of all change objects of a certain type, or
2248  only one, if the change affects a certain class, and an ID is
2249  given for that class (not the change ID -the ID of the changed
2250  object).
2251 
2252  \returns a new c_comdef_changes object, containing the changes. Null if it failed.
2253 
2254  \throws an exception if the SQL query fails.
2255  */
2256  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2257  public static function GetChangesFromIDAndType(
2258  $in_type,
2259  // The class type for the changes
2260  // One of these values:
2261  // - c_comdef_meeting
2262  // - c_comdef_service_body
2263  // - c_comdef_user
2264  // - c_comdef_format
2265  $in_id = null, ///< The ID for the object. If not specified, all changes for the given type will be returned (WARNING: Could be a great many).
2266  $in_start_date = null, ///< If you specify a start date (In PHP time() format), then only changes on, or after this date will be returned.
2267  $in_end_date = null ///< If you specify an end date (In PHP time() format), then only changes that occurred on, or before this date will be returned.
2268  ) {
2269  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2270  $sql = "SELECT * FROM `".self::GetChangesTableName_obj()."` WHERE";
2271 
2272  if (null != $in_id) {
2273  $in_id = intval($in_id);
2274  $sql .= " ((before_id_bigint=$in_id) OR (after_id_bigint=$in_id)) AND";
2275  }
2276 
2277  if (intval($in_start_date)) {
2278  $start_date = date('Y-m-d 00:00:00', intval($in_start_date));
2279  $sql .= " (change_date>='$start_date') AND";
2280  }
2281 
2282  if (intval($in_end_date)) {
2283  $end_date = date('Y-m-d 23:59:59', intval($in_end_date));
2284  $sql .= " (change_date<='$end_date') AND";
2285  }
2286 
2287  $sql .= " (object_class_string=?) ORDER BY change_date DESC";
2288 
2289  return self::GetServer()->GetChangesFromSQL($sql, array ( $in_type ));
2290  }
2291 
2292  /*******************************************************************/
2293  /** \brief This function allows you to get a list of changes by object
2294  type, and change type (such as all deleted meetings, or all rolled-back
2295  formats).
2296 
2297  \returns a new c_comdef_changes object, containing the changes. Null if it failed.
2298 
2299  \throws an exception if the SQL query fails.
2300  */
2301  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2302  public static function GetChangesFromOTypeAndCType(
2303  $in_o_type,
2304  // The class type for the changes
2305  // One of these values:
2306  // - c_comdef_meeting
2307  // - c_comdef_service_body
2308  // - c_comdef_user
2309  // - c_comdef_format
2310  $in_change_type
2311  // The change type.
2312  // Can be:
2313  // - 'comdef_change_type_new' - New object
2314  // - 'comdef_change_type_delete' - Deleted the object
2315  // - 'comdef_change_type_change' - Changed existing object
2316  // - 'comdef_change_type_rollback' - Rolled existing object back to a previous version
2317  ) {
2318  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2319  $sql = "SELECT * FROM `".self::GetChangesTableName_obj()."` WHERE (object_class_string=?) AND (change_type_enum=?) ORDER BY change_date DESC";
2320 
2321  return self::GetServer()->GetChangesFromSQL($sql, array ( $in_o_type, $in_change_type ));
2322  }
2323 
2324  /*******************************************************************/
2325  /** \brief Returns the number of Km per degree of longitude, adjusted for Latitude.
2326 
2327  \returns a floating point number, with the number of Km per degree longitude at the given latitude..
2328  */
2329  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2330  public static function getKmPerLonAtLat($dLatitude ///< The latitude (in degrees).
2331  )
2332  {
2333  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2334  return 111.321 * cos(deg2rad($dLatitude));
2335  }
2336 
2337  /*******************************************************************/
2338  /** \brief This is a static utility function that takes a specified
2339  radius and center point and calculates a square, in longitude and
2340  latitude points, that encompasses that radius. This greatly narrows
2341  the scope of the search, so the radius calculation will simply eliminate
2342  any meetings that are "in the corners."
2343 
2344  \returns an array of floating-point values, in the following form:
2345  - ['east'] = longitude of the Eastern side of the rectangle
2346  - ['west'] = longitude of the Western side of the rectangle
2347  - ['north'] = latitude of the Northern side of the rectangle
2348  - ['south'] = latitude of the Southern side of the rectangle
2349  */
2350  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2351  public static function GetSquareForRadius(
2352  $in_radius, ///< A positive floating-point number. The radius, in kilometers.
2353  $in_long_in_degrees, ///< The longitude needs to be specified in degrees.
2354  $in_lat_in_degrees ///< The latitude needs to be specified in degrees.
2355  ) {
2356  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2357  $loc = null;
2358  $vert_radius = $in_radius / 111.000;
2359  $horiz_radius = $in_radius / (111.321 * cos(deg2rad($in_lat_in_degrees)));
2360 
2361  $loc['east'] = $in_long_in_degrees - $horiz_radius;
2362  $loc['west'] = $in_long_in_degrees + $horiz_radius;
2363  $loc['north'] = $in_lat_in_degrees + $vert_radius;
2364  $loc['south'] = $in_lat_in_degrees - $vert_radius;
2365 
2366  return $loc;
2367  }
2368 
2369  /*******************************************************************/
2370  /** \brief Return SQL for a radius circle around the given coordinates.
2371  This is a special function for MySQL.
2372 
2373  \returns a string, containing the SQL clause.
2374  This will be a prepared statement, with variable slots for:
2375  latitude of the centerpoint, in degrees (floating-point)
2376  longitude of the centerpoint, in degrees (floating point)
2377  radius, in kilometers (floating point)
2378  if $in_published is TRUE, then there will be an additional placeholder for published (0 not published, 1, published)
2379  There will be an additional 'distance' slot in the response, with the distance from the centerpoint.
2380  A limit. This should be 10 more than what we are looking for. This speeds up the query.
2381  */
2382  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2383  public static function MySQLGetRadiusSQLClause(
2384  $in_published = false, ///< If TRUE, then we will have a slot for published status.
2385  $in_weekday = null, ///< This is an array of weekdays we are looking for (integers).
2386  $in_service_bodies = null ///< This is an array of service body ids we are looking for
2387  ) {
2388  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2389  // I adapted this from here: http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/ Thanks, Ollie!
2390  $sql = "SELECT COUNT(*) FROM ( SELECT *,
2391  p.distance_unit
2392  * DEGREES(ACOS(COS(RADIANS(p.latpoint))
2393  * COS(RADIANS(z.latitude))
2394  * COS(RADIANS(p.longpoint) - RADIANS(z.longitude))
2395  + SIN(RADIANS(p.latpoint))
2396  * SIN(RADIANS(z.latitude)))) AS distance
2397  FROM `".self::GetMeetingTableName_obj()."_main` AS z
2398  JOIN ( /* these are the query parameters */
2399  SELECT ? AS latpoint, ? AS longpoint,
2400  ? AS radius, 111.045 AS distance_unit
2401  ) AS p ON 1=1
2402  WHERE z.latitude
2403  BETWEEN p.latpoint - (p.radius / p.distance_unit)
2404  AND p.latpoint + (p.radius / p.distance_unit)
2405  AND z.longitude
2406  BETWEEN p.longpoint - (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
2407  AND p.longpoint + (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
2408  ) AS d
2409  WHERE (distance <= radius)";
2410 
2411  if ($in_published) {
2412  $sql .= " AND (published = ?)";
2413  }
2414 
2415  // Belt and suspenders...
2416  if (isset($in_weekday) && (null != $in_weekday) && is_array($in_weekday) && count($in_weekday)) {
2417  $wd_yes_array = array();
2418  $wd_no_array = array();
2419 
2420  $sql .= " AND (";
2421  foreach ($in_weekday as $weekday) {
2422  if (0 > intval($weekday)) {
2423  $wd_no_array[] = "(weekday_tinyInt <> ".abs(intval($weekday)).")";
2424  } else {
2425  $wd_yes_array[] = "(weekday_tinyInt = ".intval($weekday).")";
2426  }
2427  }
2428 
2429  if (count($wd_yes_array)) {
2430  $sql .= implode(" OR ", $wd_yes_array);
2431  }
2432 
2433  if (count($wd_no_array)) {
2434  $sql .= implode(" AND ", $wd_no_array);
2435  }
2436 
2437  $sql .= ")";
2438  }
2439 
2440  $include_service_body_ids = array();
2441  $exclude_service_body_ids = array();
2442  if (is_array($in_service_bodies)) {
2443  foreach ($in_service_bodies as $service_body_id) {
2444  if ($service_body_id > 0) {
2445  array_push($include_service_body_ids, intval($service_body_id));
2446  } else {
2447  array_push($exclude_service_body_ids, abs(intval($service_body_id)));
2448  }
2449  }
2450  }
2451  $service_bodies_clause = array();
2452  if (count($include_service_body_ids)) {
2453  $include_service_body_ids = implode(",", $include_service_body_ids);
2454  array_push($service_bodies_clause, "service_body_bigint IN ($include_service_body_ids)");
2455  }
2456  if (count($exclude_service_body_ids)) {
2457  $exclude_service_body_ids = implode(",", $exclude_service_body_ids);
2458  array_push($service_bodies_clause, "service_body_bigint NOT IN ($exclude_service_body_ids)");
2459  }
2460  if (count($service_bodies_clause)) {
2461  $sql .= " AND " . implode(" AND ", $service_bodies_clause) . "\n";
2462  }
2463 
2464  $sql .= "\nORDER BY distance;";
2465 
2466  return $sql;
2467  }
2468 
2469  /*******************************************************************/
2470  /** \brief Find the smallest radius that contains at least the given number of meetings.
2471  The way this works is that the center is set, and the optimal
2472  radius is selected in kilometers to deliver that many meetings.
2473  The radius starts at 25 Km (about 10 miles), and goes up or
2474  down in 5Km "clicks." Under 5Km, it reduces to 0.5Km "clicks."
2475  It will not go out more than 100Km.
2476 
2477  When it passes the threshold for the number of meetings in the
2478  square, the radius is selected, and the _search_radius is set
2479  to the number of Kilometers.
2480 
2481  We are not looking for an exact meeting count. It should select the
2482  first radius that contains AT LEAST the number of meetings requested.
2483 
2484  If not enough meetings are found, the radius ends up at 0.
2485 
2486  \returns a radius, in Km, for a result. Null if none found.
2487 
2488  \throws an exception if the SQL query fails.
2489  */
2490  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2491  public static function HuntForRadius(
2492  $in_search_result_count, ///< A positive integer. It specifies the number of meetings to find.
2493  $in_long_in_degrees, ///< The longitude needs to be specified in degrees.
2494  $in_lat_in_degrees, ///< The latitude needs to be specified in degrees.
2495  $in_weekday_tinyint_array, ///< An array of weekdays in which to filter for.
2496  $in_service_bodies_array = null ///< An array of service bodies in which ot filter for.
2497  ) {
2498  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2499  $ret = null;
2500 
2501  $localized_strings = self::GetLocalStrings();
2502  $sql1 = "SELECT COUNT(*) FROM `".self::GetMeetingTableName_obj()."_main` WHERE";
2503  $sql3 = '';
2504 
2505  if (is_array($in_weekday_tinyint_array) && count($in_weekday_tinyint_array)) {
2506  $sql1 .= " (";
2507 
2508  $first = true;
2509  foreach ($in_weekday_tinyint_array as $weekday) {
2510  $weekday = intval($weekday);
2511  $sql_x = "";
2512  if ($weekday < 0) {
2513  $weekday = abs($weekday);
2514  $sql_x = " NOT ";
2515 
2516  if (!$first) {
2517  $sql_x = " AND $sql_x";
2518  }
2519 
2520  $first = true; // This makes the OR get skipped.
2521  }
2522 
2523  if (!$first) {
2524  $sql_x .= " OR ";
2525  } else {
2526  $first = false;
2527  }
2528 
2529  $sql1 .= "$sql_x(".self::GetMeetingTableName_obj()."_main.weekday_tinyint=".strval($weekday - 1).")";
2530  }
2531  $sql1 .= ") AND (";
2532  $sql3 = ")";
2533  }
2534 
2535  $ranges = $localized_strings['comdef_map_radius_ranges'];
2536  $current_radius = 0.0;
2537 
2538  foreach ($ranges as $radius) {
2539  $radius = floatval($radius) * (($localized_strings['dist_units'] == 'mi') ? 1.609344 : 1.0);
2540  $current_radius = $radius;
2541  $arr = array ();
2542 
2543  $show_published_only = (c_comdef_server::GetServer()->GetCurrentUserObj() == null); // We only show published meetings to regular users.
2544  $arr = array ( $in_lat_in_degrees, $in_long_in_degrees, $radius );
2545 
2546  if ($show_published_only) {
2547  $arr[] = true;
2548  }
2549 
2550  $sql = c_comdef_server::MySQLGetRadiusSQLClause($show_published_only, $in_weekday_tinyint_array, $in_service_bodies_array);
2551 
2552  try {
2553  $rows = c_comdef_dbsingleton::preparedQuery($sql, $arr);
2554  } catch (Exception $e) {
2555  break;
2556  }
2557 
2558  $count = 0;
2559 
2560  if (is_array($rows) && count($rows)) {
2561  $count = intval($rows[0]["count(*)"]);
2562 
2563  if ($count > $in_search_result_count) {
2564  break;
2565  }
2566  }
2567  }
2568  return $current_radius;
2569  }
2570 
2571  /*******************************************************************/
2572  /** \brief Given an SQL statement and a value array (for DBO prepared
2573  statements), return a new c_comdef_changes object, loaded with the
2574  instances of the changes that were returned from the query.
2575 
2576  \returns a new c_comdef_changes object, containing the changes. Null if it failed.
2577 
2578  \throws an exception if the SQL query fails.
2579  */
2580  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2581  public function GetChangesFromSQL(
2582  $in_sql, ///< The prepared statement SQL query
2583  $in_value_array = null ///< An array of values for the prepared statement.
2584  ) {
2585  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2586  $rows = c_comdef_dbsingleton::preparedQuery($in_sql, $in_value_array);
2587 
2588  $this_changes_object = null;
2589 
2590  if (is_array($rows) && count($rows)) {
2591  // We now instantiate a c_comdef_changes object, and create our c_comdef_change objects.
2592  $this_changes_object = new c_comdef_changes($this, $rows);
2593  }
2594 
2595  return $this_changes_object;
2596  }
2597 
2598  /*******************************************************************/
2599  /** \brief This gets the appropriate language files, and puts all the
2600  the strings into an associative array. If a language enum is passed in,
2601  and the language directory exists, then the strings are loaded from
2602  that directory. If nothing is passed in, the first place we look is
2603  in the HTTP query, to see if a 'lang_enum' query is present. If it is there,
2604  we use that. If not, we use the base server language.
2605 
2606  \returns an associative array of local strings. Null if it failed.
2607  - 'name' The name of the language, in the language itself.
2608  - 'enum' The code for the language.
2609  - 'weekdays' An array of weekday names. 0 -> Sunday, 6 -> Saturday
2610  - 'prompt_delimiter' The character used to delimit prompts (usually a colon ':').
2611  - 'comdef_map_radius_ranges' An array of floating point numbers that indicate the choices for the radius selector (in miles).
2612  - 'comdef_search_admin_strings' An associative array, with strings used only in administration.
2613  - 'comdef_format_types' An associative array that maps format classes to their descriptions.
2614  - 'change_type_strings' An associative array that maps the types of changes to their descriptions.
2615  - 'detailed_change_strings' An associative array that maps detailed descriptions of itemized changes.
2616  - 'end_change_report' The character used to end a change report (usually a period '.').
2617  - 'time_zone_strings' An array of time zone strings.
2618  */
2619  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2620  public static function GetLocalStrings( $in_lang_enum = null ///< An enumeration string, indicating the language desired. If provided, it overrides all else.
2621  )
2622  {
2623  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
2625  // This will create the SINGLETON server if one does not yet exist.
2626  $server = self::MakeServer();
2627 
2628  if ($server instanceof c_comdef_server) {
2629  $lang_enum = $server->GetLocalLang();
2630 
2631  if (isset($_GET['lang_enum']) && $_GET['lang_enum']) {
2632  $lang_enum = $_GET['lang_enum'];
2633  }
2634 
2635  if (isset($_POST['lang_enum']) && $_POST['lang_enum']) {
2636  $lang_enum = $_POST['lang_enum'];
2637  }
2638 
2639  if (is_array($lang_enum) && count($lang_enum)) {
2640  $langs = array();
2641  foreach ($lang_enum as $lang) {
2642  if (file_exists(dirname(dirname(__FILE__)).'/local_server/server_admin/lang/'.$lang)) {
2643  array_push($langs, $lang);
2644  }
2645  }
2646  $lang_enum = implode(",", $langs);
2647  } elseif ($in_lang_enum && file_exists(dirname(dirname(__FILE__)).'/local_server/server_admin/lang/'.$in_lang_enum)) {
2648  $lang_enum = $in_lang_enum;
2649  }
2650 
2651  include(dirname(__FILE__)."/config/comdef-config.inc.php");
2652  include(dirname(dirname(__FILE__)).'/local_server/server_admin/lang/'.$lang_enum.'/server_admin_strings.inc.php');
2653 
2654  global $comdef_global_more_details_address, ///< This is a format string for the way the address line is displayed in the "more details" screen.
2655  $comdef_global_list_address; ///< The same, but for the list.
2656 
2657  c_comdef_server::$server_local_strings['default_meeting_published'] = isset($default_meeting_published) ? $default_meeting_published : true;
2658  c_comdef_server::$server_local_strings['week_starts_on'] = (isset($week_starts_on) && (-1 < $week_starts_on) && (7 > $week_starts_on)) ? $week_starts_on : 0;
2659  c_comdef_server::$server_local_strings['name'] = file_get_contents(dirname(dirname(__FILE__)).'/local_server/server_admin/lang/'.$lang_enum.'/name.txt');
2663  array ( 0.1, 100.0 ); ///< The default range (min, max), in Km.
2664  c_comdef_server::$server_local_strings['include_service_body_email_in_semantic'] = false;
2665  if (isset($g_include_service_body_email_in_semantic)) {
2666  c_comdef_server::$server_local_strings['include_service_body_email_in_semantic'] = $g_include_service_body_email_in_semantic;
2667  }
2668 
2669  c_comdef_server::$server_local_strings['auto_geocoding_enabled'] = isset($auto_geocoding_enabled) ? $auto_geocoding_enabled : true;
2670  c_comdef_server::$server_local_strings['zip_auto_geocoding_enabled'] = isset($zip_auto_geocoding_enabled) ? $zip_auto_geocoding_enabled : false;
2671  c_comdef_server::$server_local_strings['county_auto_geocoding_enabled'] = isset($county_auto_geocoding_enabled) ? $county_auto_geocoding_enabled : false;
2672  c_comdef_server::$server_local_strings['sort_formats'] = isset($sort_formats) ? $sort_formats : true;
2673  c_comdef_server::$server_local_strings['meeting_counties_and_sub_provinces'] = isset($meeting_counties_and_sub_provinces) ? $meeting_counties_and_sub_provinces : array();
2674  c_comdef_server::$server_local_strings['meeting_states_and_provinces'] = isset($meeting_states_and_provinces) ? $meeting_states_and_provinces : array();
2675  c_comdef_server::$server_local_strings['google_api_key'] = isset($gkey) ? $gkey : '';
2676  c_comdef_server::$server_local_strings['dbPrefix'] = $dbPrefix;
2677  c_comdef_server::$server_local_strings['region_bias'] = isset($region_bias) ? $region_bias : 'us';
2678  c_comdef_server::$server_local_strings['default_duration_time'] = isset($default_duration_time) ? $default_duration_time : '01:00:00';
2679  c_comdef_server::$server_local_strings['default_minute_interval'] = isset($default_minute_interval) ? $default_minute_interval : 5;
2680  c_comdef_server::$server_local_strings['search_spec_map_center'] = $search_spec_map_center;
2684  c_comdef_server::$server_local_strings['prompt_delimiter'] = defined('__PROMPT_DELIMITER__') ? __PROMPT_DELIMITER__ : ':';
2685  c_comdef_server::$server_local_strings['end_change_report'] = defined('_END_CHANGE_REPORT') ? _END_CHANGE_REPORT : '.';
2686  c_comdef_server::$server_local_strings['time_zone_strings'] = array(
2687  "Acre Time (Rio Branco)" => "America/Rio_Branco",
2688  "Afghanistan Time (Kabul)" => "Asia/Kabul",
2689  "Alaska Time (Anchorage)" => "America/Anchorage",
2690  "Amazon Time (Manaus)" => "America/Manaus",
2691  "Apia Time (Apia)" => "Pacific/Apia",
2692  "Arabian Time (Al Aḩmadī)" => "Asia/Kuwait",
2693  "Arabian Time (Baghdad)" => "Asia/Baghdad",
2694  "Arabian Time (Doha)" => "Asia/Qatar",
2695  "Arabian Time (Manama)" => "Asia/Bahrain",
2696  "Arabian Time (Riyadh)" => "Asia/Riyadh",
2697  "Arabian Time (Sanaa)" => "Asia/Aden",
2698  "Argentina Time (Buenos Aires)" => "America/Argentina/Buenos_Aires",
2699  "Armenia Time (Yerevan)" => "Asia/Yerevan",
2700  "Atlantic Time (Basseterre)" => "America/St_Kitts",
2701  "Atlantic Time (Brades)" => "America/Montserrat",
2702  "Atlantic Time (Bridgetown)" => "America/Barbados",
2703  "Atlantic Time (Castries)" => "America/St_Lucia",
2704  "Atlantic Time (Chaguanas)" => "America/Port_of_Spain",
2705  "Atlantic Time (Fort-de-France)" => "America/Martinique",
2706  "Atlantic Time (Gustavia)" => "America/St_Barthelemy",
2707  "Atlantic Time (Kingstown)" => "America/St_Vincent",
2708  "Atlantic Time (Kralendijk)" => "America/Kralendijk",
2709  "Atlantic Time (Les Abymes)" => "America/Guadeloupe",
2710  "Atlantic Time (Lévis)" => "America/Blanc-Sablon",
2711  "Atlantic Time (Marigot)" => "America/Marigot",
2712  "Atlantic Time (Oranjestad)" => "America/Aruba",
2713  "Atlantic Time (Philipsburg)" => "America/Lower_Princes",
2714  "Atlantic Time (Road Town)" => "America/Tortola",
2715  "Atlantic Time (Roseau)" => "America/Dominica",
2716  "Atlantic Time (Saint Croix)" => "America/St_Thomas",
2717  "Atlantic Time (Saint George's)" => "America/Grenada",
2718  "Atlantic Time (Saint John’s)" => "America/Antigua",
2719  "Atlantic Time (San Juan)" => "America/Puerto_Rico",
2720  "Atlantic Time (Santo Domingo)" => "America/Santo_Domingo",
2721  "Atlantic Time (The Valley)" => "America/Anguilla",
2722  "Atlantic Time (Willemstad)" => "America/Curacao",
2723  "Atlantic Time (Halifax)" => "America/Halifax",
2724  "Atlantic Time (Hamilton)" => "Atlantic/Bermuda",
2725  "Atlantic Time (Thule)" => "America/Thule",
2726  "Australian Central Time (Adelaide)" => "Australia/Adelaide",
2727  "Australian Central Time (Darwin)" => "Australia/Darwin",
2728  "Australian Central Western Time (Eucla)" => "Australia/Eucla",
2729  "Australian Eastern Time (Brisbane)" => "Australia/Brisbane",
2730  "Australian Eastern Time (Sydney)" => "Australia/Sydney",
2731  "Australian Western Time (Casey)" => "Antarctica/Casey",
2732  "Australian Western Time (Perth)" => "Australia/Perth",
2733  "Azerbaijan Time (Baku)" => "Asia/Baku",
2734  "Azores Time (Ponta Delgada)" => "Atlantic/Azores",
2735  "Bangladesh Time (Dhaka)" => "Asia/Dhaka",
2736  "Bhutan Time (Thimphu)" => "Asia/Thimphu",
2737  "Bolivia Time (Santa Cruz de la Sierra)" => "America/La_Paz",
2738  "Bougainville Time (Arawa)" => "Pacific/Bougainville",
2739  "Brasilia Time (São Paulo)" => "America/Sao_Paulo",
2740  "Brunei Darussalam Time (Bandar Seri Begawan)" => "Asia/Brunei",
2741  "Cape Verde Time (Praia)" => "Atlantic/Cape_Verde",
2742  "Central Africa Time (Bujumbura)" => "Africa/Bujumbura",
2743  "Central Africa Time (Gaborone)" => "Africa/Gaborone",
2744  "Central Africa Time (Harare)" => "Africa/Harare",
2745  "Central Africa Time (Khartoum)" => "Africa/Khartoum",
2746  "Central Africa Time (Kigali)" => "Africa/Kigali",
2747  "Central Africa Time (Lilongwe)" => "Africa/Blantyre",
2748  "Central Africa Time (Lubumbashi)" => "Africa/Lubumbashi",
2749  "Central Africa Time (Lusaka)" => "Africa/Lusaka",
2750  "Central Africa Time (Maputo)" => "Africa/Maputo",
2751  "Central Africa Time (Windhoek)" => "Africa/Windhoek",
2752  "Central European Time (Algiers)" => "Africa/Algiers",
2753  "Central European Time (Tunis)" => "Africa/Tunis",
2754  "Central European Time (Amsterdam)" => "Europe/Amsterdam",
2755  "Central European Time (Andorra la Vella)" => "Europe/Andorra",
2756  "Central European Time (Belgrade)" => "Europe/Belgrade",
2757  "Central European Time (Berlin)" => "Europe/Berlin",
2758  "Central European Time (Birkirkara)" => "Europe/Malta",
2759  "Central European Time (Bratislava)" => "Europe/Bratislava",
2760  "Central European Time (Brussels)" => "Europe/Brussels",
2761  "Central European Time (Budapest)" => "Europe/Budapest",
2762  "Central European Time (Copenhagen)" => "Europe/Copenhagen",
2763  "Central European Time (Gibraltar)" => "Europe/Gibraltar",
2764  "Central European Time (Ljubljana)" => "Europe/Ljubljana",
2765  "Central European Time (Longyearbyen)" => "Arctic/Longyearbyen",
2766  "Central European Time (Luxembourg)" => "Europe/Luxembourg",
2767  "Central European Time (Madrid)" => "Europe/Madrid",
2768  "Central European Time (Monaco)" => "Europe/Monaco",
2769  "Central European Time (Oslo)" => "Europe/Oslo",
2770  "Central European Time (Paris)" => "Europe/Paris",
2771  "Central European Time (Podgorica)" => "Europe/Podgorica",
2772  "Central European Time (Prague)" => "Europe/Prague",
2773  "Central European Time (Rome)" => "Europe/Rome",
2774  "Central European Time (San Marino)" => "Europe/San_Marino",
2775  "Central European Time (Sarajevo)" => "Europe/Sarajevo",
2776  "Central European Time (Skopje)" => "Europe/Skopje",
2777  "Central European Time (Stockholm)" => "Europe/Stockholm",
2778  "Central European Time (Tirana)" => "Europe/Tirane",
2779  "Central European Time (Vaduz)" => "Europe/Vaduz",
2780  "Central European Time (Vatican City)" => "Europe/Vatican",
2781  "Central European Time (Vienna)" => "Europe/Vienna",
2782  "Central European Time (Warsaw)" => "Europe/Warsaw",
2783  "Central European Time (Zagreb)" => "Europe/Zagreb",
2784  "Central European Time (Zürich)" => "Europe/Zurich",
2785  "Central Indonesia Time (Makassar)" => "Asia/Makassar",
2786  "Central Time (Belize City)" => "America/Belize",
2787  "Central Time (Guatemala City)" => "America/Guatemala",
2788  "Central Time (Managua)" => "America/Managua",
2789  "Central Time (San José)" => "America/Costa_Rica",
2790  "Central Time (San Salvador)" => "America/El_Salvador",
2791  "Central Time (Saskatoon)" => "America/Regina",
2792  "Central Time (Tegucigalpa)" => "America/Tegucigalpa",
2793  "Central Time (Chicago)" => "America/Chicago",
2794  "Central Time (Mexico City)" => "America/Mexico_City",
2795  "Central Time (Winnipeg)" => "America/Winnipeg",
2796  "Chamorro Time (Dededo Village)" => "Pacific/Guam",
2797  "Chamorro Time (Saipan)" => "Pacific/Saipan",
2798  "Chatham Time (Chatham)" => "Pacific/Chatham",
2799  "Chile Time (Santiago)" => "America/Santiago",
2800  "Chile Time (Palmer)" => "Antarctica/Palmer",
2801  "Chile Time (Punta Arenas)" => "America/Punta_Arenas",
2802  "China Time (Zhongshan)" => "Asia/Urumqi",
2803  "China Time (Macau)" => "Asia/Macau",
2804  "China Time (Shanghai)" => "Asia/Shanghai",
2805  "Christmas Island Time (Flying Fish Cove)" => "Indian/Christmas",
2806  "Chuuk Time (Chuuk)" => "Pacific/Chuuk",
2807  "Cocos Islands Time (West Island)" => "Indian/Cocos",
2808  "Colombia Time (Bogotá)" => "America/Bogota",
2809  "Cook Islands Time (Avarua)" => "Pacific/Rarotonga",
2810  "Cuba Time (Havana)" => "America/Havana",
2811  "Davis Time (Davis)" => "Antarctica/Davis",
2812  "Dumont-d’Urville Time (DumontDUrville)" => "Antarctica/DumontDUrville",
2813  "East Africa Time (Addis Ababa)" => "Africa/Addis_Ababa",
2814  "East Africa Time (Antananarivo)" => "Indian/Antananarivo",
2815  "East Africa Time (Asmara)" => "Africa/Asmara",
2816  "East Africa Time (Dar es Salaam)" => "Africa/Dar_es_Salaam",
2817  "East Africa Time (Djibouti)" => "Africa/Djibouti",
2818  "East Africa Time (Juba)" => "Africa/Juba",
2819  "East Africa Time (Kampala)" => "Africa/Kampala",
2820  "East Africa Time (Mamoudzou)" => "Indian/Mayotte",
2821  "East Africa Time (Mogadishu)" => "Africa/Mogadishu",
2822  "East Africa Time (Moroni)" => "Indian/Comoro",
2823  "East Africa Time (Nairobi)" => "Africa/Nairobi",
2824  "East Greenland Time (Scoresbysund)" => "America/Scoresbysund",
2825  "East Kazakhstan Time (Almaty)" => "Asia/Almaty",
2826  "East Timor Time (Dili)" => "Asia/Dili",
2827  "Easter Island Time (Easter)" => "Pacific/Easter",
2828  "Eastern European Time (Cairo)" => "Africa/Cairo",
2829  "Eastern European Time (Kaliningrad)" => "Europe/Kaliningrad",
2830  "Eastern European Time (Tripoli)" => "Africa/Tripoli",
2831  "Eastern European Time (Aleppo)" => "Asia/Damascus",
2832  "Eastern European Time (Amman)" => "Asia/Amman",
2833  "Eastern European Time (Athens)" => "Europe/Athens",
2834  "Eastern European Time (Beirut)" => "Asia/Beirut",
2835  "Eastern European Time (Bucharest)" => "Europe/Bucharest",
2836  "Eastern European Time (Chisinau)" => "Europe/Chisinau",
2837  "Eastern European Time (East Jerusalem)" => "Asia/Hebron",
2838  "Eastern European Time (Helsinki)" => "Europe/Helsinki",
2839  "Eastern European Time (Kyiv)" => "Europe/Kiev",
2840  "Eastern European Time (Mariehamn)" => "Europe/Mariehamn",
2841  "Eastern European Time (Nicosia)" => "Asia/Nicosia",
2842  "Eastern European Time (Riga)" => "Europe/Riga",
2843  "Eastern European Time (Sofia)" => "Europe/Sofia",
2844  "Eastern European Time (Tallinn)" => "Europe/Tallinn",
2845  "Eastern European Time (Vilnius)" => "Europe/Vilnius",
2846  "Eastern Indonesia Time (Ambon)" => "Asia/Jayapura",
2847  "Eastern Time (Atikokan)" => "America/Atikokan",
2848  "Eastern Time (Cancún)" => "America/Cancun",
2849  "Eastern Time (George Town)" => "America/Cayman",
2850  "Eastern Time (Kingston)" => "America/Jamaica",
2851  "Eastern Time (Panamá)" => "America/Panama",
2852  "Eastern Time (Cockburn Town)" => "America/Grand_Turk",
2853  "Eastern Time (Nassau)" => "America/Nassau",
2854  "Eastern Time (New York City)" => "America/New_York",
2855  "Eastern Time (Port-au-Prince)" => "America/Port-au-Prince",
2856  "Eastern Time (Toronto)" => "America/Toronto",
2857  "Ecuador Time (Guayaquil)" => "America/Guayaquil",
2858  "Falkland Islands Time (Stanley)" => "Atlantic/Stanley",
2859  "Fernando de Noronha Time (Noronha)" => "America/Noronha",
2860  "Fiji Time (Suva)" => "Pacific/Fiji",
2861  "French Guiana Time (Cayenne)" => "America/Cayenne",
2862  "French Southern & Antarctic Time (Port-aux-Français)" => "Indian/Kerguelen",
2863  "Galapagos Time (Galapagos)" => "Pacific/Galapagos",
2864  "Gambier Time (Gambier)" => "Pacific/Gambier",
2865  "Georgia Time (Tbilisi)" => "Asia/Tbilisi",
2866  "Gilbert Islands Time (Tarawa)" => "Pacific/Tarawa",
2867  "Greenwich Mean Time (Abidjan)" => "Africa/Abidjan",
2868  "Greenwich Mean Time (Accra)" => "Africa/Accra",
2869  "Greenwich Mean Time (Bamako)" => "Africa/Bamako",
2870  "Greenwich Mean Time (Bissau)" => "Africa/Bissau",
2871  "Greenwich Mean Time (Camayenne)" => "Africa/Conakry",
2872  "Greenwich Mean Time (Dakar)" => "Africa/Dakar",
2873  "Greenwich Mean Time (Danmarkshavn)" => "America/Danmarkshavn",
2874  "Greenwich Mean Time (Freetown)" => "Africa/Freetown",
2875  "Greenwich Mean Time (Jamestown)" => "Atlantic/St_Helena",
2876  "Greenwich Mean Time (Lomé)" => "Africa/Lome",
2877  "Greenwich Mean Time (Monrovia)" => "Africa/Monrovia",
2878  "Greenwich Mean Time (Nouakchott)" => "Africa/Nouakchott",
2879  "Greenwich Mean Time (Ouagadougou)" => "Africa/Ouagadougou",
2880  "Greenwich Mean Time (Reykjavík)" => "Atlantic/Reykjavik",
2881  "Greenwich Mean Time (Serekunda)" => "Africa/Banjul",
2882  "Greenwich Mean Time (São Tomé)" => "Africa/Sao_Tome",
2883  "Greenwich Mean Time (Douglas)" => "Europe/Isle_of_Man",
2884  "Greenwich Mean Time (London)" => "Europe/London",
2885  "Greenwich Mean Time (Saint Helier)" => "Europe/Jersey",
2886  "Greenwich Mean Time (Saint Peter Port)" => "Europe/Guernsey",
2887  "Greenwich Mean Time (Dublin)" => "Europe/Dublin",
2888  "Greenwich Mean Time (Troll)" => "Antarctica/Troll",
2889  "Gulf Time (Dubai)" => "Asia/Dubai",
2890  "Gulf Time (Muscat)" => "Asia/Muscat",
2891  "Guyana Time (Georgetown)" => "America/Guyana",
2892  "Hawaii-Aleutian Time (Honolulu)" => "Pacific/Honolulu",
2893  "Hawaii-Aleutian Time (Adak)" => "America/Adak",
2894  "Hong Kong Time (Hong Kong)" => "Asia/Hong_Kong",
2895  "Hovd Time (Khovd)" => "Asia/Hovd",
2896  "India Time (Colombo)" => "Asia/Colombo",
2897  "India Time (Mumbai)" => "Asia/Kolkata",
2898  "Indian Ocean Time (Chagos)" => "Indian/Chagos",
2899  "Indochina Time (Bangkok)" => "Asia/Bangkok",
2900  "Indochina Time (Ho Chi Minh City)" => "Asia/Ho_Chi_Minh",
2901  "Indochina Time (Phnom Penh)" => "Asia/Phnom_Penh",
2902  "Indochina Time (Vientiane)" => "Asia/Vientiane",
2903  "Iran Time (Tehran)" => "Asia/Tehran",
2904  "Irkutsk Time (Irkutsk)" => "Asia/Irkutsk",
2905  "Israel Time (Jerusalem)" => "Asia/Jerusalem",
2906  "Japan Time (Tokyo)" => "Asia/Tokyo",
2907  "Korean Time (Pyongyang)" => "Asia/Pyongyang",
2908  "Korean Time (Seoul)" => "Asia/Seoul",
2909  "Kosrae Time (Kosrae)" => "Pacific/Kosrae",
2910  "Kyrgyzstan Time (Bishkek)" => "Asia/Bishkek",
2911  "Line Islands Time (Kiritimati)" => "Pacific/Kiritimati",
2912  "Lord Howe Time (Lord Howe)" => "Australia/Lord_Howe",
2913  "Macquarie Island Time (Macquarie)" => "Antarctica/Macquarie",
2914  "Malaysia Time (Kota Bharu)" => "Asia/Kuala_Lumpur",
2915  "Maldives Time (Male)" => "Indian/Maldives",
2916  "Marquesas Time (Marquesas)" => "Pacific/Marquesas",
2917  "Marshall Islands Time (Majuro)" => "Pacific/Majuro",
2918  "Mauritius Time (Port Louis)" => "Indian/Mauritius",
2919  "Mawson Time (Mawson)" => "Antarctica/Mawson",
2920  "Mexican Pacific Time (Hermosillo)" => "America/Hermosillo",
2921  "Moscow Time (Minsk)" => "Europe/Minsk",
2922  "Moscow Time (Moscow)" => "Europe/Moscow",
2923  "Mountain Time (Fort St. John)" => "America/Dawson_Creek",
2924  "Mountain Time (Phoenix)" => "America/Phoenix",
2925  "Mountain Time (Calgary)" => "America/Edmonton",
2926  "Mountain Time (Ciudad Juárez)" => "America/Ojinaga",
2927  "Mountain Time (Denver)" => "America/Denver",
2928  "Myanmar Time (Yangon)" => "Asia/Yangon",
2929  "Nauru Time (Yaren)" => "Pacific/Nauru",
2930  "Nepal Time (Kathmandu)" => "Asia/Kathmandu",
2931  "New Caledonia Time (Nouméa)" => "Pacific/Noumea",
2932  "New Zealand Time (Auckland)" => "Pacific/Auckland",
2933  "New Zealand Time (McMurdo)" => "Antarctica/McMurdo",
2934  "Newfoundland Time (St. John's)" => "America/St_Johns",
2935  "Niue Time (Alofi)" => "Pacific/Niue",
2936  "Norfolk Island Time (Kingston)" => "Pacific/Norfolk",
2937  "Novosibirsk Time (Novosibirsk)" => "Asia/Novosibirsk",
2938  "Omsk Time (Omsk)" => "Asia/Omsk",
2939  "Pacific Time (Los Angeles)" => "America/Los_Angeles",
2940  "Pacific Time (Tijuana)" => "America/Tijuana",
2941  "Pacific Time (Vancouver)" => "America/Vancouver",
2942  "Pacific Time (Whitehorse)" => "America/Whitehorse",
2943  "Pakistan Time (Karachi)" => "Asia/Karachi",
2944  "Palau Time (Ngerulmud)" => "Pacific/Palau",
2945  "Papua New Guinea Time (Port Moresby)" => "Pacific/Port_Moresby",
2946  "Paraguay Time (Asunción)" => "America/Asuncion",
2947  "Peru Time (Lima)" => "America/Lima",
2948  "Petropavlovsk-Kamchatski Time (Petropavlovsk-Kamchatsky)" => "Asia/Kamchatka",
2949  "Philippine Time (Quezon City)" => "Asia/Manila",
2950  "Phoenix Islands Time (Enderbury)" => "Pacific/Enderbury",
2951  "Pitcairn Time (Adamstown)" => "Pacific/Pitcairn",
2952  "Réunion Time (Saint-Denis)" => "Indian/Reunion",
2953  "Sakhalin Time (Yuzhno-Sakhalinsk)" => "Asia/Sakhalin",
2954  "Samara Time (Samara)" => "Europe/Samara",
2955  "Samoa Time (Midway)" => "Pacific/Midway",
2956  "Samoa Time (Pago Pago)" => "Pacific/Pago_Pago",
2957  "Seychelles Time (Victoria)" => "Indian/Mahe",
2958  "Singapore Time (Singapore)" => "Asia/Singapore",
2959  "Solomon Islands Time (Honiara)" => "Pacific/Guadalcanal",
2960  "South Africa Time (Cape Town)" => "Africa/Johannesburg",
2961  "South Africa Time (Manzini)" => "Africa/Mbabane",
2962  "South Africa Time (Maseru)" => "Africa/Maseru",
2963  "South Georgia Time (Grytviken)" => "Atlantic/South_Georgia",
2964  "St. Pierre & Miquelon Time (Saint-Pierre)" => "America/Miquelon",
2965  "Suriname Time (Paramaribo)" => "America/Paramaribo",
2966  "Syowa Time (Syowa)" => "Antarctica/Syowa",
2967  "Tahiti Time (Faaa)" => "Pacific/Tahiti",
2968  "Taipei Time (Taipei)" => "Asia/Taipei",
2969  "Tajikistan Time (Dushanbe)" => "Asia/Dushanbe",
2970  "Tokelau Time (Fakaofo)" => "Pacific/Fakaofo",
2971  "Tonga Time (Nuku‘alofa)" => "Pacific/Tongatapu",
2972  "Turkey Time (Istanbul)" => "Europe/Istanbul",
2973  "Turkmenistan Time (Ashgabat)" => "Asia/Ashgabat",
2974  "Tuvalu Time (Funafuti)" => "Pacific/Funafuti",
2975  "Ulaanbaatar Time (Ulan Bator)" => "Asia/Ulaanbaatar",
2976  "Uruguay Time (Montevideo)" => "America/Montevideo",
2977  "Uzbekistan Time (Tashkent)" => "Asia/Tashkent",
2978  "Vanuatu Time (Port-Vila)" => "Pacific/Efate",
2979  "Venezuela Time (Caracas)" => "America/Caracas",
2980  "Vladivostok Time (Vladivostok)" => "Asia/Vladivostok",
2981  "Vostok Time (Vostok)" => "Antarctica/Vostok",
2982  "Wake Island Time (Wake)" => "Pacific/Wake",
2983  "Wallis & Futuna Time (Mata-Utu)" => "Pacific/Wallis",
2984  "West Africa Time (Bangui)" => "Africa/Bangui",
2985  "West Africa Time (Bata)" => "Africa/Malabo",
2986  "West Africa Time (Brazzaville)" => "Africa/Brazzaville",
2987  "West Africa Time (Cotonou)" => "Africa/Porto-Novo",
2988  "West Africa Time (Douala)" => "Africa/Douala",
2989  "West Africa Time (Kinshasa)" => "Africa/Kinshasa",
2990  "West Africa Time (Lagos)" => "Africa/Lagos",
2991  "West Africa Time (Libreville)" => "Africa/Libreville",
2992  "West Africa Time (Luanda)" => "Africa/Luanda",
2993  "West Africa Time (N'Djamena)" => "Africa/Ndjamena",
2994  "West Africa Time (Niamey)" => "Africa/Niamey",
2995  "West Greenland Time (Nuuk)" => "America/Godthab",
2996  "West Kazakhstan Time (Kyzylorda)" => "Asia/Qyzylorda",
2997  "Western European Time (Las Palmas de Gran Canaria)" => "Atlantic/Canary",
2998  "Western European Time (Lisbon)" => "Europe/Lisbon",
2999  "Western European Time (Tórshavn)" => "Atlantic/Faroe",
3000  "Western European Time (Casablanca)" => "Africa/Casablanca",
3001  "Western European Time (Laayoune)" => "Africa/El_Aaiun",
3002  "Western Indonesia Time (Jakarta)" => "Asia/Jakarta",
3003  "Yakutsk Time (Chita)" => "Asia/Chita",
3004  "Yekaterinburg Time (Yekaterinburg)" => "Asia/Yekaterinburg"
3005  );
3006  c_comdef_server::$server_local_strings['charset'] = defined('__HTML_DISPLAY_CHARSET__') ? __HTML_DISPLAY_CHARSET__ : 'UTF-8';
3007  c_comdef_server::$server_local_strings['time_format'] = $time_format;
3008  c_comdef_server::$server_local_strings['min_pw_len'] = intval($min_pw_len);
3009  c_comdef_server::$server_local_strings['number_of_meetings_for_auto'] = $number_of_meetings_for_auto;
3010  c_comdef_server::$server_local_strings['comdef_global_more_details_address'] = $comdef_global_more_details_address;
3013  c_comdef_server::$server_local_strings['default_sorts'] = array ( 'weekday' => array('weekday_tinyint','location_municipality','location_city_subsection','start_time','location_neighborhood'),
3014  'time' => array('weekday_tinyint','start_time','location_municipality','location_city_subsection','location_neighborhood'),
3015  'town' => array('location_municipality','location_city_subsection','location_neighborhood','weekday_tinyint','start_time'),
3016  'state' => array('location_province','location_municipality','location_city_subsection','weekday_tinyint','start_time'),
3017  'weekday_state' => array('weekday_tinyint','location_province','location_municipality','start_time','location_city_subsection')
3018  );
3019 
3020  c_comdef_server::$server_local_strings['weekdays'] = $comdef_server_admin_strings['meeting_search_weekdays_names'];
3021  c_comdef_server::$server_local_strings['service_body_types'] = array ( c_comdef_service_body__GRP__ => $comdef_server_admin_strings['service_body_editor_type_c_comdef_service_body__GRP__'],
3022  c_comdef_service_body__COP__ => $comdef_server_admin_strings['service_body_editor_type_c_comdef_service_body__COP__'],
3023  c_comdef_service_body__ASC__ => $comdef_server_admin_strings['service_body_editor_type_c_comdef_service_body__ASC__'],
3024  c_comdef_service_body__RSC__ => $comdef_server_admin_strings['service_body_editor_type_c_comdef_service_body__RSC__'],
3025  c_comdef_service_body__WSC__ => $comdef_server_admin_strings['service_body_editor_type_c_comdef_service_body__WSC__'],
3026  c_comdef_service_body__MAS__ => $comdef_server_admin_strings['service_body_editor_type_c_comdef_service_body__MAS__'],
3027  c_comdef_service_body__ZFM__ => $comdef_server_admin_strings['service_body_editor_type_c_comdef_service_body__ZFM__']
3028  );
3029 
3030  c_comdef_server::$server_local_strings['default_closed_status'] = (!isset($g_defaultClosedStatus) || $g_defaultClosedStatus) ? 1 : ((isset($g_defaultClosedStatus) && !$g_defaultClosedStatus) ? 0 : 1);
3031  c_comdef_server::$server_local_strings['meeting_browser_theme'] = isset($meeting_browser_theme) ? $meeting_browser_theme : "asheboro";
3032  if (trim($comdef_distance_units)) {
3033  c_comdef_server::$server_local_strings['dist_units'] = strtolower(trim($comdef_distance_units));
3034  } else {
3035  c_comdef_server::$server_local_strings['dist_units'] = 'mi';
3036  }
3037  c_comdef_server::$server_local_strings['meeting_time_zones_enabled'] = isset($meeting_time_zones_enabled) ? $meeting_time_zones_enabled : false;
3038  if (isset($default_timezone) && $default_timezone) {
3039  date_default_timezone_set($default_timezone);
3040  }
3041  // Due to NAWS database limitations, only 5 formats at most can be exported. auto-config.inc.php can specify an optional variable $naws_export_formats_at_front
3042  // that is an array of formats that should be exported first, to make sure they are included. This is particularly important for VM (Virtual Meeting),
3043  // TC (Temporarily Closed) and HYBR (Hybrid), since these are essential and we don't want them falling off the end. If this variable isn't set in
3044  // auto-config.inc.php, give it a default value that includes those plus a few others. If the meeting has any of these formats, they are exported
3045  // first, in the order they appear in naws_export_formats_at_front.
3046  c_comdef_server::$server_local_strings['naws_export_formats_at_front'] = isset($naws_export_formats_at_front) ? $naws_export_formats_at_front : ['VM', 'TC', 'HYBR', 'W', 'M', 'GL'];
3047  ini_set('default_charset', '');
3048  }
3049  }
3050 
3052  }
3053 
3054  /*******************************************************************/
3055  /** \brief Return all the Service Bodies this user is authorized with
3056 
3057  \returns an associative array. The key is the ID of the Service Body, and the value is:
3058  - 'principal' If the user is a principal admin
3059  - 'editor' If the user is a secondary editor.
3060  Returns null if the user is not cleared for any Service Body.
3061  */
3062  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
3063  public static function GetUserServiceBodies( $in_user_id = null ///< The ID of the user. If not provided, the current user is checked.
3064  )
3065  {
3066  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
3067  $ret = null;
3068 
3069  if (!$in_user_id) {
3070  $in_user_id = self::GetCurrentUserObj()->GetID();
3071  }
3072 
3073  $service_bodies = c_comdef_server::GetServer()->GetServiceBodyArray();
3074 
3075  if (is_array($service_bodies) && count($service_bodies)) {
3076  foreach ($service_bodies as &$service_body) {
3077  $is_editor = null;
3078  if ($service_body instanceof c_comdef_service_body) {
3079  $editors = $service_body->GetEditors();
3080 
3081  if (is_array($editors) && count($editors)) {
3082  if (in_array($in_user_id, $editors)) {
3083  $is_editor = 'editor';
3084  }
3085  }
3086 
3087  if ($service_body->GetPrincipalUserID() == $in_user_id) {
3088  $is_editor = 'principal';
3089  }
3090  }
3091 
3092  if ($is_editor) {
3093  $ret[$service_body->GetID()] = $is_editor;
3094  }
3095  }
3096  }
3097 
3098  return $ret;
3099  }
3100 
3101  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
3102  public static function GetDatabaseVersion()
3103  {
3104  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
3105  $sql = "SELECT version FROM `".self::GetDatabaseVersionTableName_obj()."`";
3107  if (!is_array($rows) || !count($rows)) {
3108  return 0;
3109  }
3110  $row = $rows[0];
3111  return intval($row['version']);
3112  }
3113 }
static GetLocalStrings($in_lang_enum=null)
This gets the appropriate language files, and puts all the the strings into an associative array...
static DuplicateMeetingObj($in_meeting_obj)
This creates a new meeting that is an exact duplicate of the object passed in. The new meeting has a ...
static GetServerLangs()
Get the local readable string for the server languages.
static process_meeting_row($row, $data_rows=null, $longdata_rows=null)
This processes the data retrieved from a single main table meeting. It will look up the corollary dat...
static GetMeetingsForAServiceBody($in_sb_id)
Returns a c_comdef_meetings_object, containing all the meetings directly "owned" by the Service Body ...
A Class for Service Body Objects.
static AddNewChange($in_user_id_bigint, $in_change_type, $in_service_body_id_bigint, $in_before_string, $in_after_string, $in_object_class_string, $in_before_obj_id_bigint, $in_after_obj_id_bigint, $in_before_obj_lang_enum=null, $in_after_obj_lang_enum=null, $in_name_string=null, $in_description_string=null, $in_lang_enum=null)
Creates a new change record in the Database.
static GetOneUser($in_id_bigint)
Given an ID for a user, it returns one instance.
static GetDistance($lat1, $lon1, $lat2, $lon2)
Uses the Vincenty calculation to estimate a distance between the two given lat/long pairs...
A class to hold a single meeting object.
global $comdef_map_radius_ranges
GetFormatsArray()
Simply returns an array of the format objects.
GetChangesFromSQL($in_sql, $in_value_array=null)
Given an SQL statement and a value array (for DBO prepared statements), return a new c_comdef_changes...
static MySQLGetRadiusSQLClause($in_published=false, $in_weekday=null, $in_service_bodies=null)
Return SQL for a radius circle around the given coordinates. This is a special function for MySQL...
static GetUserByLogin($in_login)
Given a login, looks up the user, and returns a reference to that user object.
const c_comdef_service_body__COP__
static GetOneChange($in_id_bigint)
Given an ID for a change, it returns one instance.
static AddNewMeeting($in_service_body_bigint, $in_weekday_tinyint, $in_start_time_int, $in_lang_enum)
Creates a new, relatively empty meeting in the database, with no data fields and minimal information...
static GetAllMeetings(&$in_out_numResults, $in_numResults=null, $in_startIndex=null)
Returns a c_comdef_meetings_object, containing all the meetings (Published and unpublished).
static GetServiceBodyHierarchyIDs($in_service_body_id_bigint)
Return the IDs of an entire Service body hierarchy.
This class handles BMLT users. One instance is created for each user on the server.
static GetChangesTableName_obj()
Simply returns the name of the changes table.
GetUsedFormatsArray()
Simply returns an array of the format objects used by the meetings (no unused ones).
GetNestedServiceBodyArray($in_id=0)
This reads the Service bodies in hierarchical order, and returns them in a multi-dimensional array th...
static GetMeetingTableName_obj()
Simply returns the name of the meetings table.
$ret
Definition: contact.php:226
static GetServiceBodiesTableName_obj()
Simply returns the name of the service bodies table.
const c_comdef_service_body__WSC__
global $comdef_global_language
The local server language enum (Will default to English)
static GetOneFormat($in_id_bigint, $in_lang_enum)
Given an ID and a language for a format, it returns one instance.
static DoesMeetingExist($in_id_bigint)
Given an ID for a meeting, it returns true if the meeting currently exists.
const _USER_LEVEL_SERVICE_BODY_ADMIN
static preparedQuery($sql, $params=array(), $fetchKeyPair=false)
Wrapper for preparing and executing a PDOStatement that returns a resultset e.g. SELECT SQL statement...
FullCrypt($in_string, $in_salt=null, &$crypt_method=null)
Encrypts a string, using the most effective encryption.
static GetChangesFromOTypeAndCType($in_o_type, $in_change_type)
This function allows you to get a list of changes by object type, and change type (such as all delete...
static getKmPerLonAtLat($dLatitude)
Returns the number of Km per degree of longitude, adjusted for Latitude.
static ParseMeetingsByFormats($in_meetings, $in_formats)
This is an alternative to the MySQL REGEXP test. It will go through all the meetings returned by a br...
static GetUserTableName_obj()
Simply returns the name of the user table.
const _USER_LEVEL_DISABLED
static GetUserByLoginCredentials($in_login, $in_password)
Given a login and password, looks up the user, and returns a reference to that user object...
static GetEncryptedPW($in_login, $in_password)
Given a login and password, looks up the user, and returns an encrypted password for that user...
ReadServiceBodies()
This is an internal function that reads in all of the stored service bodies and instantiates local ob...
static GetDatabaseVersionTableName_obj()
const _USER_LEVEL_SERVER_ADMIN
GetFormatsObj()
Simply returns a reference to the formats container.
A Class for Format Codes.
const c_comdef_service_body__RSC__
static GetCoverageArea()
Returns a set of two coordinates that define a rectangle that encloses all of the meetings...
$lang_enum
Definition: index.php:23
global $comdef_global_more_details_address
This is a format string for the way the address line is displayed in the "more details" screen...
Include the format class.
global $http_vars
Definition: index.php:21
static GetUserByIDObj($in_user_id_bigint)
Get the object for a single user, given an ID.
static GetSquareForRadius($in_radius, $in_long_in_degrees, $in_lat_in_degrees)
This is a static utility function that takes a specified radius and center point and calculates a squ...
GetServiceBodyArrayHierarchical()
Returns the Service Body objects in a nested, hierarchical array, with "parents" containing "children...
ReadServiceIDs()
This gathers the IDs of all the Service bodies that appear in meeting records. It is NOT a dump of th...
const c_comdef_service_body__ZFM__
A class to hold a collection of c_comdef_users objects.
const c_comdef_service_body__ASC__
static IsUserServiceBodyAdmin($in_user_obj=null, $in_is_ajax=false)
Find out if the user is a service body admin.
static GetMeetingsByID($in_id_bigint_array)
Get a series of meetings, each identified by an ID. This does not filter by any of the other major cr...
GetAllServiceIDs()
Simply returns the stored service IDs for ALL Service Bodies.
GetServiceBodyArray()
Simply returns a reference to the contained Service Body array.
This class provides a genericized interface to the PHP PDO toolkit. It is a completely static class...
$server
Definition: GetLangs.php:25
A Class for Change Record Objects.
static GetServerUsersObj()
Get the object list for the server&#39;s registered users.
static IsFormatKeyUnique($in_key_string, $in_lang_enum)
Given an ID and a language for a format, as well as a code, returns true if the code does NOT appear ...
A class to hold a collection of c_comdef_change objects.
static GetServiceBodyByIDObj($in_service_body_id_bigint)
Get the object for a single service body, given an ID.
static $server_local_strings
This contains a cache of the local strings.
static HuntForRadius($in_search_result_count, $in_long_in_degrees, $in_lat_in_degrees, $in_weekday_tinyint_array, $in_service_bodies_array=null)
Find the smallest radius that contains at least the given number of meetings. The way this works is t...
Initialize()
This reads the Formats, Meeting and Service Entity IDs.
GetUsedFormatIDs()
Return the shared IDs of the formats actually used by the contained meetings. This can be used to avo...
static MakeServer()
This is the factory for the server instantiation. It makes sure that only one instance exists...
This class is the main server class. It instantiates a PDO database object, and is the starting point...
static GetNamespace()
Simply returns the namespace of this server.
static init($driver, $host, $database, $user=null, $password=null, $charset=null)
Initializes connection param class members.
static GetMeetingsFromSQL($in_sql, $in_value_array=null)
Given an SQL statement and a value array (for PDO prepared statements), return a new c_comdef_meeting...
GetServiceIDs()
Simply returns the stored service IDs.
defined('BMLT_EXEC') or define('BMLT_EXEC'
Definition: index.php:3
const c_comdef_service_body__GRP__
const c_comdef_service_body__MAS__
static AddNewUser($in_user_login, $in_user_unencrypted_password, $in_user_level, $in_user_email, $in_name_string=null, $in_description_string=null, $in_lang_enum=null, $in_owner_id=-1)
Creates a new user in the Database.
static GetChangesFromIDAndType($in_type, $in_id=null, $in_start_date=null, $in_end_date=null)
Gets a list of all change objects of a certain type, or only one, if the change affects a certain cla...
ReadUsers()
This is an internal function that reads in all of the stored users and instantiates local objects for...
static GetFormatTableName_obj()
Simply returns the name of the format table.
static DuplicateMeetingID($in_meeting_id)
This creates a new meeting that is an exact duplicate of the object for the meeting whose ID is passe...
A class to hold a collection of c_comdef_meeting objects.
GetLocalLang()
Returns the Server Local Language.
static GetCurrentUserObj($in_is_ajax=false)
Get the current logged-in user, as a c_comdef_user instance.
static GetUsersByLevelObj($in_user_level_bigint, $in_or_higher=false, $in_include_disabled=false)
Get the objects for all users of a certain user level.
ReadFormats()
This is an internal function that reads in all of the stored formats, in all provided languages...
$user_obj
Definition: index.php:7
A class to hold a collection of c_comdef_service_body objects.
static ServerLangSortCallback($in_lang_a, $in_lang_b)
This is a callback to sort the server languages. The default server language will always be first...
static TrimChanges($in_type, $in_id)
trims the changes for the given item.
__construct($in_lang_enum=null)
The initial setup call for the class. Part of setting up the server is establishing the database conn...
static AddNewServiceBody($in_name_string, $in_lang_enum, $in_principal_user_bigint, $in_description_string=null, $in_editors_string=null, $in_uri_string=null, $in_kml_uri_string=null, $in_worldid_mixed=null, $in_sb_type=null, $in_sb_owner=null)
Creates a new Service Body in the Database.
static GetOneMeeting($in_id_bigint, $test_only=false)
Given an ID for a meeting, it returns one instance.
static IsUserServerAdmin($in_user_obj=null, $in_is_ajax=false)
Find out if the user is a server admin.
static GetMeetings($in_service_body_id_bigint_array=null, $in_lang_filter_array=null, $in_weekday_tinyint_array=null, $in_formats=null, $in_start_after=null, $in_start_before=null, $in_end_before=null, $in_min_duration=null, $in_max_duration=null, $in_search_rect_array=null, $in_first=null, &$in_num=null, $in_published=0, $formats_comparison_operator="AND")
Given a set of one or more main criteria, returns a new c_comdef_meetings object with instances of th...
global $comdef_global_list_address
The same, but for the list.
static GetUserServiceBodies($in_user_id=null)
Return all the Service Bodies this user is authorized with.
$comdef_server_admin_strings
static SetServer($in_server_instance)
Sets the server instance.
$_GET['switcher']