BMLT Root Server
c_comdef_change.class.php
Go to the documentation of this file.
1 <?php
2 /***********************************************************************/
3 /** \file c_comdef_change.class.php
4  \brief The class file for the c_comdef_change class.
5 
6  This file is part of the Basic Meeting List Toolbox (BMLT).
7 
8  Find out more at: https://bmlt.app
9 
10  BMLT is free software: you can redistribute it and/or modify
11  it under the terms of the MIT License.
12 
13  BMLT is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  MIT License for more details.
17 
18  You should have received a copy of the MIT License along with this code.
19  If not, see <https://opensource.org/licenses/MIT>.
20 */
21 
22 defined('BMLT_EXEC') or die('Cannot Execute Directly'); // Makes sure that this file is in the correct context.
23 
24 require_once(dirname(__FILE__)."/../shared/classes/base_templates.inc.php");
25 require_once(dirname(__FILE__)."/c_comdef_user.class.php");
26 require_once(dirname(__FILE__)."/c_comdef_format.class.php");
27 require_once(dirname(__FILE__)."/c_comdef_meeting.class.php");
28 require_once(dirname(__FILE__)."/c_comdef_service_body.class.php");
29 
30 /***********************************************************************/
31 /** \class c_comdef_change
32  \brief A Class for Change Record Objects
33 
34  This class handles the Model for the way we record changes in the CoMDEF
35  architecture.
36  A change record has a record of who made the change, when it was made,
37  notes on the change, and a "before" and "after" snapshot of the changed
38  entity. Meetings, Users, Service bodies or formats can have changes recorded. If a new
39  entity is created, the "before" is null. If an entity is deleted, then
40  the "after" snapshot is null. Snapshots are serialized objects.
41 ***********************************************************************/
42 // phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
43 // phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
45 // phpcs:enable PSR1.Classes.ClassDeclaration.MissingNamespace
46 // phpcs:enable Squiz.Classes.ValidClassName.NotCamelCaps
47 {
48  /// An integer, containing the unique ID of this change record.
49  private $change_id_bigint = null;
50  /// A serialized object (either c_comdef_format or c_comdef_meeting) before the change
51  private $before_object_string = null;
52  /// The same object, serialized after the change
53  private $after_object_string = null;
54  /// The ID of the Before Object
55  private $before_object_id_bigint = null;
56  /// The ID of the After Object
57  private $after_object_id_bigint = null;
58  /// The Language of the Before Object
59  private $before_object_lang_enum = null;
60  /// The Language of the After Object
61  private $after_object_lang_enum = null;
62  /// The ID of the user making the change.
63  private $change_user_int = null;
64  /// The ID of the Service Body on behalf of which the user is acting.
65  private $change_service_body_int = null;
66  /// The date and time (as a time() seconds value) when the change was made.
67  private $change_datetime_int = null;
68  /// The name of the object class that has been serialized.
69  private $object_class_string = null;
70  /** The type of change this was
71  Can be:
72  - 'comdef_change_type_new' - New object
73  - 'comdef_change_type_delete' - Deleted the object
74  - 'comdef_change_type_change' - Changed existing object
75  - 'comdef_change_type_rollback' - Rolled existing object back to a previous version
76  */
77  private $change_type_enum = null;
78 
79  /*******************************************************************/
80  /** \brief Updates or adds this instance to the database.
81 
82  \throws a PDOException if there is a problem.
83  */
84  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
85  public function UpdateToDB()
86  {
87  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
88  $ar = array();
89  try {
90  // We will delete any previous entries.
91  $this->DeleteFromDB();
92 
93  $sql = "INSERT INTO `".c_comdef_server::GetChangesTableName_obj()."` (";
94  if ($this->change_id_bigint) {
95  $sql .= "`id_bigint`,";
96  }
97  $sql .= "`user_id_bigint`,`service_body_id_bigint`,`lang_enum`,`object_class_string`,`change_name_string`,`change_description_text`,`before_object`,`after_object`, `before_id_bigint`, `before_lang_enum`, `after_id_bigint`, `after_lang_enum`, `change_type_enum`) VALUES (";
98  if ($this->change_id_bigint) {
99  $sql .= "?,";
100  array_push($ar, $this->change_id_bigint);
101  }
102  $sql .= "?,?,?,?,?,?,?,?,?,?,?,?,?)";
103  array_push($ar, $this->change_user_int);
104  array_push($ar, $this->change_service_body_int);
105  array_push($ar, $this->GetLocalLang());
106  array_push($ar, $this->object_class_string);
107  array_push($ar, $this->GetLocalName());
108  array_push($ar, $this->GetLocalDescription());
109  array_push($ar, $this->before_object_string);
110  array_push($ar, $this->after_object_string);
111  array_push($ar, $this->before_object_id_bigint);
112  array_push($ar, $this->before_object_lang_enum);
113  array_push($ar, $this->after_object_id_bigint);
114  array_push($ar, $this->after_object_lang_enum);
115  array_push($ar, $this->change_type_enum);
116 
118  // If this is a new user, then we'll need to fetch the ID.
119  if (!$this->change_id_bigint) {
120  $sql = "SELECT LAST_INSERT_ID()";
122  if (is_array($rows) && count($rows)) {
123  $this->change_id_bigint = intval($rows[0]['last_insert_id()']);
124  }
125  }
126  } catch (Exception $ex) {
127  global $_COMDEF_DEBUG;
128 
129  if ($_COMDEF_DEBUG) {
130  echo "Exception Thrown in c_comdef_change::UpdateToDB()!<br />";
131  var_dump($ex);
132  }
133  throw ( $ex );
134  }
135  }
136 
137  /*******************************************************************/
138  /** \brief Deletes this instance from the database.
139 
140  \throws a PDOException if there is a problem.
141  */
142  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
143  public function DeleteFromDB()
144  {
145  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
146  try {
147  $sql = "DELETE FROM `".c_comdef_server::GetChangesTableName_obj()."` WHERE id_bigint=?";
148  c_comdef_dbsingleton::preparedExec($sql, array ( $this->GetID() ));
149  } catch (Exception $ex) {
150  global $_COMDEF_DEBUG;
151 
152  if ($_COMDEF_DEBUG) {
153  echo "Exception Thrown in c_comdef_change::DeleteFromDB()!<br />";
154  var_dump($ex);
155  }
156  throw ( $ex );
157  }
158  }
159 
160  /*******************************************************************/
161  /** \brief Updates this instance to the current values in the DB
162  (replacing current values of the instance).
163 
164  \throws a PDOException if there is a problem.
165  */
166  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
167  public function RestoreFromDB()
168  {
169  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
170  try {
171  $sql = "SELECT * FROM `".c_comdef_server::GetChangesTableName_obj()."` WHERE id_bigint=? LIMIT 1";
172 
173  $rows = c_comdef_dbsingleton::preparedQuery($sql, array ( $this->change_id_bigint ));
174 
175  if (is_array($rows) && count($rows)) {
176  $this->change_user_int = $rows[0]['user_id_bigint'];
177  $this->change_service_body_int = $rows[0]['service_body_id_bigint'];
178  $this->change_datetime_int = $rows[0]['change_date'];
179  $this->object_class_string = $rows[0]['object_class_string'];
180  $this->before_object_string = $rows[0]['before_object'];
181  $this->after_object_string = $rows[0]['after_object'];
182  $this->SetLocalName($rows[0]['change_name_string']);
183  $this->SetLocalDescription($rows[0]['change_description_text']);
184  $this->SetLocalLang($rows[0]['lang_enum']);
185  $this->before_object_id_bigint = $rows[0]['before_id_bigint'];
186  $this->before_object_lang_enum = $rows[0]['before_lang_enum'];
187  $this->after_object_id_bigint = $rows[0]['after_id_bigint'];
188  $this->after_object_lang_enum = $rows[0]['after_lang_enum'];
189  $this->change_type_enum = $rows[0]['change_type_enum'];
190  }
191  } catch (Exception $ex) {
192  global $_COMDEF_DEBUG;
193 
194  if ($_COMDEF_DEBUG) {
195  echo "Exception Thrown in c_comdef_change::RestoreFromDB()!<br />";
196  var_dump($ex);
197  }
198  throw ( $ex );
199  }
200  }
201 
202  /*******************************************************************/
203  /** \brief The initial setup call for the class. If you send in values,
204  the object will set itself up to use them.
205 
206  */
207  public function __construct(
208  $in_parent_obj, ///< A reference to the parent object for this change object (usually an instance of c_comdef_changes)
209  $in_change_type_enum,
210  // Enum. The type of change.
211  // Can be:
212  // - 'comdef_change_type_new' - New object
213  // - 'comdef_change_type_delete' - Deleted the object
214  // - 'comdef_change_type_change' - Changed existing object
215  // - 'comdef_change_type_rollback' - Rolled existing object back to a previous version
216  $in_user_id_int, ///< Integer. The ID of the user that made this change.
217  $in_service_body_id_bigint, ///< Integer. The Service Body the user was acting for.
218  $in_before_string, ///< String (serialized object of either c_comdef_format or c_comdef_meeting). The object as it was immediately BEFORE the change.
219  $in_after_string, ///< String (serialized object of either c_comdef_format or c_comdef_meeting). The object as it was immediately AFTER the change.
220  $in_object_class_string, ///< A string, containing the class of the object[s] being passed in as serialized.
221  $in_before_obj_id_bigint, ///< Integer, The ID of the Before Object.
222  $in_after_obj_id_bigint, ///< Integer, The ID of the After Object.
223  $in_before_obj_lang_enum = null, ///< Enum, the language of the Before Object.
224  $in_after_obj_lang_enum = null, ///< Enum. The language of the After Object.
225  $in_change_id_int = null, ///< Integer. The unique ID of this change record. If left null, the DB interaction will assign one.
226  $in_change_name_string = null, ///< String. A brief header (1-line description) of the change (optional).
227  $in_change_description_string = null, ///< String. A more detailed description of the change (optional).
228  $in_lang_enum = null, ///< Enum. The language to record the change as. If null, the server or global language will be used.
229  $in_datetime_int = null ///< Integer containing the UNIX epoch (time() value) of the datetime the change was made. If null, the current time will be used.
230  ) {
231  /// This is the server language.
232  if (null == $in_lang_enum) {
233  $in_lang_enum = c_comdef_server::GetServer()->GetLocalLang();
234  }
235 
236  /// This is the global language.
237  if (null == $in_lang_enum) {
239 
240  $in_lang_enum = $comdef_global_language;
241  }
242 
243  /// Should never be necessary.
244  if (null == $in_lang_enum) {
245  $in_lang_enum = "en";
246  }
247 
248  if (null == $in_datetime_int) {
249  $in_datetime_int = time();
250  }
251 
252  /// If no languages are given for the input objects, we use the main language.
253  if (null == $in_before_obj_lang_enum) {
254  $in_before_obj_lang_enum = $in_lang_enum;
255  }
256 
257  if (null == $in_after_obj_lang_enum) {
258  $in_after_obj_lang_enum = $in_before_obj_lang_enum;
259  }
260 
261  $this->change_id_bigint = $in_change_id_int;
262  $this->change_user_int = $in_user_id_int;
263  $this->change_service_body_int = $in_service_body_id_bigint;
264  $this->change_datetime_int = $in_datetime_int;
265  $this->object_class_string = $in_object_class_string;
266  $this->before_object_string = $in_before_string;
267  $this->after_object_string = $in_after_string;
268  $this->SetLocalName($in_change_name_string);
269  $this->SetLocalDescription($in_change_description_string);
270  $this->SetLocalLang($in_lang_enum);
271  $this->before_object_id_bigint = $in_before_obj_id_bigint;
272  $this->before_object_lang_enum = $in_before_obj_lang_enum;
273  $this->after_object_id_bigint = $in_after_obj_id_bigint;
274  $this->after_object_lang_enum = $in_after_obj_lang_enum;
275  $this->change_type_enum = $in_change_type_enum;
276  }
277 
278  /*******************************************************************/
279  /** \brief Accessor. Get the Object Class of this change record.
280 
281  \returns a string. The object classname.
282  */
283  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
284  public function GetObjectClass()
285  {
286  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
287  return $this->object_class_string;
288  }
289 
290  /*******************************************************************/
291  /** \brief Accessor. Get the ID of this change record.
292 
293  \returns an integer. The ID of the change record.
294  */
295  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
296  public function GetID()
297  {
298  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
299  return $this->change_id_bigint;
300  }
301 
302  /*******************************************************************/
303  /** \brief Accessor. Get the type of this change record.
304 
305  \returns an enum. The type of change.
306  Can be:
307  - 'comdef_change_type_new' - New object
308  - 'comdef_change_type_delete' - Deleted the object
309  - 'comdef_change_type_change' - Changed existing object
310  - 'comdef_change_type_rollback' - Rolled existing object back to a previous version
311  */
312  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
313  public function GetChangeType()
314  {
315  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
316  return $this->change_type_enum;
317  }
318 
319  /*******************************************************************/
320  /** \brief Accessor. Get the ID of the user that created this change record.
321 
322  \returns an integer. The ID of the user.
323  */
324  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
325  public function GetUserID()
326  {
327  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
328  return $this->change_user_int;
329  }
330 
331  /*******************************************************************/
332  /** \brief Accessor. Get the ID of the Service Body that was represented
333  by the user that created this change record.
334 
335  \returns an integer. The ID of the Service Body.
336  */
337  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
338  public function GetServiceBodyID()
339  {
340  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
341  return $this->change_service_body_int;
342  }
343 
344  /*******************************************************************/
345  /** \brief Accessor. Return the ID of the "before" object.
346 
347  \returns an integer.
348  */
349  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
350  public function GetBeforeObjectID()
351  {
352  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
353  return $this->before_object_id_bigint;
354  }
355 
356  /*******************************************************************/
357  /** \brief Accessor. Return the ID of the "after" object.
358 
359  \returns an integer.
360  */
361  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
362  public function GetAfterObjectID()
363  {
364  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
365  return $this->after_object_id_bigint;
366  }
367 
368  /*******************************************************************/
369  /** \brief Accessor. Return the date/time the change was made.
370 
371  \returns an integer. The UNIX epoch time (time() return) of the change.
372  */
373  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
374  public function GetChangeDate()
375  {
376  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
377  return $this->change_datetime_int;
378  }
379 
380  /*******************************************************************/
381  /** \brief Accessor. Return the before object in serialized form.
382 
383  \returns a binary string, containing the serialized data.
384  */
385  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
386  public function GetBeforeSerialized()
387  {
388  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
389  return $this->before_object_string;
390  }
391 
392  /*******************************************************************/
393  /** \brief Accessor. Return the after object in serialized form.
394 
395  \returns a binary string, containing the serialized data.
396  */
397  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
398  public function GetAfterSerialized()
399  {
400  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
401  return $this->after_object_string;
402  }
403 
404  /*******************************************************************/
405  /** \brief Return the before object in object form.
406 
407  \returns a new c_comdef_meeting, c_comdef_user, c_comdef_service_body or c_comdef_format object. Null if failed or there is no object.
408  */
409  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
410  public function GetBeforeObject(
411  $in_parent_object = null ///< A reference to the parent object for the new object. If null, the server will be used.
412  ) {
413  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
414  $ret = null;
415 
416  if (null == $in_parent_object) {
417  $in_parent_object = c_comdef_server::GetServer();
418  }
419 
420  if (null != $this->before_object_string) {
421  switch ($this->object_class_string) {
422  case 'c_comdef_meeting':
423  $ret = c_comdef_meeting::UnserializeObject($in_parent_object, $this->before_object_string);
424  $current = c_comdef_server::GetOneMeeting($ret->GetID());
425  if (null == $current) {
426  // Restoring deleted meetings always unpublishes them before restoring them.
427  $ret->SetPublished(0);
428  }
429  break;
430 
431  case 'c_comdef_format':
432  $ret = c_comdef_format::UnserializeObject($in_parent_object, $this->before_object_string);
433  break;
434 
435  case 'c_comdef_user':
436  $ret = c_comdef_user::UnserializeObject($in_parent_object, $this->before_object_string);
437  break;
438 
439  case 'c_comdef_service_body':
440  $ret = c_comdef_user::UnserializeObject($in_parent_object, $this->before_object_string);
441  break;
442  }
443  }
444 
445  return $ret;
446  }
447 
448  /*******************************************************************/
449  /** \brief Return the after object in object form.
450 
451  \returns a new c_comdef_meeting, c_comdef_user, c_comdef_service_body or c_comdef_format object. Null if failed or there is no object.
452  */
453  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
454  public function GetAfterObject(
455  $in_parent_object = null ///< A reference to the parent object for the new object. If null, the server will be used.
456  ) {
457  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
458  $ret = null;
459 
460  if (null == $in_parent_object) {
461  $in_parent_object = c_comdef_server::GetServer();
462  }
463 
464  if (null != $this->after_object_string) {
465  switch ($this->object_class_string) {
466  case 'c_comdef_meeting':
467  $ret = c_comdef_meeting::UnserializeObject($in_parent_object, $this->after_object_string);
468  break;
469 
470  case 'c_comdef_format':
471  $ret = c_comdef_format::UnserializeObject($in_parent_object, $this->after_object_string);
472  break;
473 
474  case 'c_comdef_user':
475  $ret = c_comdef_user::UnserializeObject($in_parent_object, $this->after_object_string);
476  break;
477 
478  case 'c_comdef_service_body':
479  $ret = c_comdef_user::UnserializeObject($in_parent_object, $this->after_object_string);
480  break;
481  }
482  }
483 
484  return $ret;
485  }
486 
487  /*******************************************************************/
488  /** \brief Rolls the subject of this change to the "before" version.
489 
490  This will only work if there is a "before," and if the current
491  user is cleared to edit both the before and current versions of the
492  item.
493 
494  \returns true, if successful. False, otherwise.
495  */
496  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
497  public function Rollback()
498  {
499  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
500  $ret = false;
501 
502  // Start off by getting the prior version of the object.
503  $before = $this->GetBeforeObject();
504 
505  $current = false;
506 
507  switch ($this->object_class_string) {
508  case 'c_comdef_meeting':
509  $id = $before->GetID();
510  $current = c_comdef_server::GetOneMeeting($id);
511  break;
512 
513  case 'c_comdef_format':
514  $id = $before->GetSharedID();
515  $lang = $before->GetLocalLang();
516  $current = c_comdef_server::GetOneMeeting($id, $lang);
517  break;
518 
519  case 'c_comdef_user':
520  $id = $before->GetID();
521  $current = c_comdef_server::GetOneUser($id);
522  break;
523 
524  case 'c_comdef_service_body':
525  $id = $before->GetID();
526  $current = c_comdef_server::GetOneServiceBody($id);
527  break;
528  }
529 
530  // We can't do a rollback unless we pass both these bars.
531  if ((null != $before) && ($before->UserCanEdit())) {
532  // Either there is no current (the object was deleted), or the user is allowed to mess with the current version.
533  if ((null == $current) || ((null != $current) && ($current->UserCanEdit()))) {
534  $ret = $before->UpdateToDB(true);
535  }
536  }
537 
538  return $ret;
539  }
540 
541  /*******************************************************************/
542  /** \brief Return a string that describes the change.
543 
544  \returns a string array, describing the change, in fairly natural language.
545  */
546  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
547  public function DescribeChange()
548  {
549  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
550  $ret = "";
551 
552  // We build a macro, based upon the various parameters.
553  $macro = "__THE_";
554  switch ($this->object_class_string) {
555  case 'c_comdef_meeting':
556  $macro .= "MEETING_";
557  break;
558 
559  case 'c_comdef_format':
560  $macro .= "FORMAT_";
561  break;
562 
563  case 'c_comdef_user':
564  $macro .= "USER_";
565  break;
566 
567  case 'c_comdef_service_body':
568  $macro .= "SERVICE_BODY_";
569  break;
570  }
571 
572  switch ($this->change_type_enum) {
573  case 'comdef_change_type_new':
574  $macro .= "WAS_CREATED__";
575  break;
576 
577  case 'comdef_change_type_delete':
578  $macro .= "WAS_DELETED__";
579  break;
580 
581  case 'comdef_change_type_change':
582  $macro .= "WAS_CHANGED__";
583  break;
584 
585  case 'comdef_change_type_rollback':
586  $macro .= "WAS_ROLLED_BACK__";
587  break;
588  }
589 
590  if ($macro != "__THE_") {
591  $localized_strings = c_comdef_server::GetLocalStrings();
592 
593  // This is a rather general description of the change.
594  $ret = array('change_desc' => $localized_strings['change_type_strings'][$macro]);
595  if ($this->GetLocalDescription()) {
596  $ret['description'] = $this->GetLocalDescription();
597  }
598  if ($this->GetLocalName()) {
599  $ret['name'] = $this->GetLocalName();
600  }
601  }
602 
603  return $ret;
604  }
605 
606  /*******************************************************************/
607  /** \brief Return an array of strings that describes the change in
608  a fairly detailed manner.
609 
610  \returns an associative array, containing an item-by-item change description. Null if no description.
611  - 'overall' (required) Contains the same description as returned in DescribeChange()
612  - 'details' (optional) Contains an array of individual change items.
613  */
614  // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
615  public function DetailedChangeDescription()
616  {
617  // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
618  // We load the defines with the change phrases.
619 
620  $ret = null;
621 
622  $localized_strings = c_comdef_server::GetLocalStrings();
623 
624  switch ($this->object_class_string) {
625  // So far, the only type we are supporting is a meeting. The other types get generic answers.
626  case 'c_comdef_meeting':
627  switch ($this->change_type_enum) {
628  case 'comdef_change_type_new':
629  case 'comdef_change_type_delete':
630  case 'comdef_change_type_rollback':
631  $ret['overall'] = $this->DescribeChange();
632  $ret['details'] = $ret['overall'];
633  break;
634 
635  // We only detail a change. The others get the generic ones.
636  case 'comdef_change_type_change':
637  $ret['overall'] = $this->DescribeChange();
638  // The first thing that we do, is we get an instance of the before, and an instance of the after.
639  $before = $this->GetBeforeObject();
640  $after = $this->GetAfterObject();
641  // We then get pointers to the meeting data for each.
642  if (($before instanceof c_comdef_meeting) && ($after instanceof c_comdef_meeting)) {
643  $before_data = $before->GetMeetingData();
644  $after_data = $after->GetMeetingData();
645 
646  // Make sure we're kosher.
647  if (is_array($before_data) && is_array($after_data)) {
648  // Get all the keys, for both arrays. This way, we sort through even deleted and added items.
649  $key_array = null;
650 
651  // We do it this way, because we don't want repeats. array_merge is a bit of a "blunt instrument."
652  foreach ($before_data as $key => $value) {
653  $key_array[$key] = 1;
654  }
655 
656  foreach ($after_data as $key => $value) {
657  $key_array[$key] = 1;
658  }
659 
660  if (is_array($key_array)) {
661  $key_array = array_keys($key_array);
662 
663  // Okay, now we have an array of every key used in both objects. Time to look for changes.
664  foreach ($key_array as $array_key) {
665  $before_value = null;
666  $after_value = null;
667  $before_value = isset($before_data[$array_key]) ? $before_data[$array_key] : null;
668  // This is a security measure. If the reader can't see BOTH the before and after, we show them neither.
669  if (isset($before_value['visibility']) && ($before_value['visibility'] == _VISIBILITY_NONE_) && (!$after->UserCanObserve() || !$before->UserCanObserve())) {
670  $before_value['value'] == $localized_strings['comdef_server_admin_strings']['hidden_value'];
671  }
672 
673  $after_value = isset($after_data[$array_key]) ? $after_data[$array_key] : null;
674  if (isset($after_value['visibility']) && ($after_value['visibility'] == _VISIBILITY_NONE_) && (!$after->UserCanObserve() || !$before->UserCanObserve())) {
675  $after_value['value'] == $localized_strings['comdef_server_admin_strings']['hidden_value'];
676  }
677  $prompt = $array_key;
678  $change_string = null;
679 
680  if (is_array($before_value)) {
681  if (isset($before_value['prompt'])) {
682  $prompt = $before_value['prompt'];
683  }
684  if (isset($before_value['value'])) {
685  $before_value = $before_value['value'];
686  }
687  }
688 
689  if (is_array($after_value)) {
690  if (isset($after_value['prompt'])) {
691  $prompt = $after_value['prompt'];
692  }
693  if (isset($after_value['value'])) {
694  $after_value = $after_value['value'];
695  }
696  }
697 
698  if ($prompt && (isset($before_value) || isset($after_value))) {
699  if (isset($before_value) && !isset($after_value)) { // Just deleted.
700  switch ($array_key) {
701  case 'published':
702  $change_string = c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_unpublished']).$localized_strings['end_change_report'];
703  break;
704  case 'root_server_uri':
705  break; // Hide from change history
706  default:
707  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_deleted']).$localized_strings['end_change_report'];
708  break;
709  }
710  } elseif (!isset($before_value) && isset($after_value)) { // Just added.
711  switch ($array_key) {
712  case 'root_server_uri':
713  break; // Hide from change history
714  case 'email_contact': // For security reasons, we don't display email conact changes as anything but "changed."
715  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed']).$localized_strings['end_change_report'];
716  break;
717 
718  case 'published':
719  if (intval($after_value) != 0) {
720  $change_string = c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_published']).$localized_strings['end_change_report'];
721  }
722  break;
723 
724  // With these two values, we turn them into military time values and compare from there.
725  case 'start_time':
726  case 'duration_time':
727  $prompt = $localized_strings['detailed_change_strings'][$array_key];
728  $after_value_ar = explode(':', $after_value);
729  $after_value = (intval($after_value_ar[0]) * 100) + intval($after_value_ar[1]);
730  // Not breaking on purpose?
731  default:
732  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_added_as']).' &quot;'.c_comdef_htmlspecialchars($after_value).'&quot; '.$localized_strings['end_change_report'];
733  break;
734  }
735  } else // If it wasn't deleted or added, we need to dig a bit deeper to find the changes.
736  {
737  // Array values require even more digging.
738  if (is_array($before_value) && is_array($after_value)) {
739  switch ($array_key) {
740  case 'formats':
741  $before_keys = array();
742  $after_keys = array();
743 
744  foreach ($before_value as &$a_format_obj) {
745  if ($a_format_obj instanceof c_comdef_format) {
746  array_push($before_keys, $a_format_obj->GetKey());
747  }
748  }
749 
750  foreach ($after_value as &$a_format_obj) {
751  if ($a_format_obj instanceof c_comdef_format) {
752  array_push($after_keys, $a_format_obj->GetKey());
753  }
754  }
755 
756  asort($before_keys);
757  asort($after_keys);
758 
759  $before_value = join(', ', $before_keys);
760  $after_value = join(', ', $after_keys);
761 
762  if ($before_value != $after_value) {
763  $change_string = c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['formats_prompt']).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed_from']).' &quot;'.c_comdef_htmlspecialchars($before_value).'&quot; '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['to']).' &quot;'.c_comdef_htmlspecialchars($after_value).'&quot;'.$localized_strings['end_change_report'];
764  }
765  break;
766 
767  default:
768  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed']).$localized_strings['end_change_report'];
769  break;
770  }
771  } else // Otherwise, we simply compare the values to see if they are different.
772  {
773  // If the value changed, we create a record of the change.
774  if ($before_value != $after_value) {
775  switch ($array_key) {
776  case 'root_server_uri':
777  break; // Hide from change history
778  case 'email_contact': // For security reasons, we don't display email conact changes as anything but "changed."
779  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed']).$localized_strings['end_change_report'];
780  break;
781 
782  case 'published':
783  if (intval($before_value) != intval($after_value)) {
784  $change_string = c_comdef_htmlspecialchars($localized_strings['detailed_change_strings'][((intval($after_value) != 0) ? 'was_published' : 'was_unpublished')]).$localized_strings['end_change_report'];
785  }
786  break;
787 
788  case 'weekday_tinyint':
789  $prompt = $localized_strings['detailed_change_strings'][$array_key];
790  $before_value = $localized_strings['weekdays'][max(0, min(6, intval($before_value)))];
791  $after_value = $localized_strings['weekdays'][max(0, min(6, intval($after_value)))];
792  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed_from']).' '.c_comdef_htmlspecialchars($before_value).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['to']).' '.c_comdef_htmlspecialchars($after_value).$localized_strings['end_change_report'];
793  break;
794 
795  case 'service_body_bigint':
796  $from_sb = c_comdef_server::GetServer()->GetServiceBodyByIDObj(intval($before_value));
797  $to_sb = c_comdef_server::GetServer()->GetServiceBodyByIDObj(intval($after_value));
798  if ($from_sb instanceof c_comdef_service_body) {
799  $before_value = $from_sb->GetLocalName();
800  } else {
801  $before_value = $localized_strings['detailed_change_strings']['non_existent_service_body'];
802  }
803 
804  if ($to_sb instanceof c_comdef_service_body) {
805  $after_value = $to_sb->GetLocalName();
806  } else {
807  $before_value = $localized_strings['detailed_change_strings']['non_existent_service_body'];
808  }
809 
810  $prompt = $localized_strings['detailed_change_strings']['sb_prompt'];
811  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($before_value).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['to']).' '.c_comdef_htmlspecialchars($after_value).$localized_strings['end_change_report'];
812  break;
813 
814  case 'lang_enum':
815  $prompt = $localized_strings['detailed_change_strings'][$array_key];
816  $file_path = dirname(__FILE__)."/../../local_server/server_admin/lang/$before_value/name.txt";
817 
818  if (file_exists($file_path)) {
819  $before_value = trim(file_get_contents($file_path));
820  }
821 
822  $file_path = dirname(__FILE__)."/../../local_server/server_admin/lang/$after_value/name.txt";
823 
824  if (file_exists($file_path)) {
825  $before_value = trim(file_get_contents($file_path));
826  }
827  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed_from']).' &quot;'.c_comdef_htmlspecialchars($before_value).'&quot; '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['to']).' &quot;'.c_comdef_htmlspecialchars($after_value).'&quot;'.$localized_strings['end_change_report'];
828  break;
829 
830  case 'longitude':
831  case 'latitude':
832  $before_value = floatval($before_value);
833  $after_value = floatval($after_value);
834  // Not breaking on purpose?
835  case 'worldid_mixed':
836  case 'shared_group_id_bigint':
837  $prompt = $localized_strings['detailed_change_strings'][$array_key];
838  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed_from']).' &quot;'.c_comdef_htmlspecialchars($before_value).'&quot; '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['to']).' &quot;'.c_comdef_htmlspecialchars($after_value).'&quot;'.$localized_strings['end_change_report'];
839  break;
840 
841  // With these two values, we turn them into military time values and compare from there.
842  case 'start_time':
843  case 'duration_time':
844  $before_value = explode(':', $before_value);
845  $after_value = explode(':', $after_value);
846  $before_value = strval(intval($before_value[0])).':'.(intval($before_value[1]) < 10 ? '0' : '').strval(intval($before_value[1]));
847  $after_value = strval(intval($after_value[0])).':'.(intval($after_value[1]) < 10 ? '0' : '').strval(intval($after_value[1]));
848 
849  if ($before_value == $after_value) {
850  break;
851  }
852  // Not breaking on purpose?
853  case 'id_bigint':
854  $prompt = $localized_strings['detailed_change_strings'][$array_key];
855  // Not breaking on purpose?
856  default:
857  $change_string = c_comdef_htmlspecialchars($prompt).' '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['was_changed_from']).' &quot;'.c_comdef_htmlspecialchars($before_value).'&quot; '.c_comdef_htmlspecialchars($localized_strings['detailed_change_strings']['to']).' &quot;'.c_comdef_htmlspecialchars($after_value).'&quot;'.$localized_strings['end_change_report'];
858  break;
859  }
860  }
861  }
862  }
863 
864  if ($change_string) {
865  if (!isset($ret['details']) || !is_array($ret['details'])) {
866  $ret['details'] = array();
867  }
868 
869  array_push($ret['details'], $change_string);
870  }
871  }
872  }
873  }
874  }
875  }
876  break;
877  }
878  break;
879 
880  case 'c_comdef_format':
881  case 'c_comdef_user':
882  case 'c_comdef_service_body':
883  $ret['overall'] = $this->DescribeChange();
884  $ret['details'] = $ret['overall'];
885  break;
886  }
887 
888  return $ret;
889  }
890 }
GetAfterSerialized()
Accessor. Return the after object in serialized form.
static GetLocalStrings($in_lang_enum=null)
This gets the appropriate language files, and puts all the the strings into an associative array...
UpdateToDB()
Updates or adds this instance to the database.
GetServiceBodyID()
Accessor. Get the ID of the Service Body that was represented by the user that created this change re...
Rollback()
Rolls the subject of this change to the "before" version.
A Class for Service Body Objects.
static UnserializeObject($in_parent, $serialized_string)
This takes the serialized table, and instantiates a new object from it.
static GetOneUser($in_id_bigint)
Given an ID for a user, it returns one instance.
A class to hold a single meeting object.
static preparedExec($sql, $params=array())
Wrapper for preparing and executing a PDOStatement that does not return a resultset e...
GetBeforeObject($in_parent_object=null)
Return the before object in object form.
GetUserID()
Accessor. Get the ID of the user that created this change record.
This class handles BMLT users. One instance is created for each user on the server.
$ret
Definition: contact.php:226
GetBeforeSerialized()
Accessor. Return the before object in serialized form.
global $comdef_global_language
The local server language enum (Will default to English)
__construct($in_parent_obj, $in_change_type_enum, $in_user_id_int, $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_change_id_int=null, $in_change_name_string=null, $in_change_description_string=null, $in_lang_enum=null, $in_datetime_int=null)
The initial setup call for the class. If you send in values, the object will set itself up to use the...
static preparedQuery($sql, $params=array(), $fetchKeyPair=false)
Wrapper for preparing and executing a PDOStatement that returns a resultset e.g. SELECT SQL statement...
GetChangeDate()
Accessor. Return the date/time the change was made.
A Class for Format Codes.
GetAfterObjectID()
Accessor. Return the ID of the "after" object.
Allows us to specify a language to the instance (example: English or French)
GetObjectClass()
Accessor. Get the Object Class of this change record.
c_comdef_htmlspecialchars($in_string)
This function creates a displayable string.
GetBeforeObjectID()
Accessor. Return the ID of the "before" object.
static UnserializeObject($in_parent, $serialized_array)
This takes a serialized object, and instantiates a new object from it.
RestoreFromDB()
Updates this instance to the current values in the DB (replacing current values of the instance)...
A Class for Change Record Objects.
static UnserializeObject($in_parent, $serialized_array)
This takes the serialized data, and instantiates a new object from it.
Interface for entities that store themselves in the database.
GetAfterObject($in_parent_object=null)
Return the after object in object form.
const _VISIBILITY_NONE_
DetailedChangeDescription()
Return an array of strings that describes the change in a fairly detailed manner. ...
defined('BMLT_EXEC') or define('BMLT_EXEC'
Definition: index.php:3
global $_COMDEF_DEBUG
This flag, when set to true, will cause extra debug information to be output.
GetID()
Accessor. Get the ID of this change record.
GetChangeType()
Accessor. Get the type of this change record.
DescribeChange()
Return a string that describes the change.
static GetOneMeeting($in_id_bigint, $test_only=false)
Given an ID for a meeting, it returns one instance.
DeleteFromDB()
Deletes this instance from the database.