PageRenderTime 55ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/apps/admin/models/Versions.php

https://bitbucket.org/jonphipps/elefant-vocabhub
PHP | 195 lines | 89 code | 11 blank | 95 comment | 10 complexity | fbe266385a3ab27af0f96b21d8d736c6 MD5 | raw file
  1. <?php
  2. /**
  3. * Elefant CMS - http://www.elefantcms.com/
  4. *
  5. * Copyright (c) 2011 Johnny Broadway
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. /**
  26. * Keeps a change history of any [[Model]] object.
  27. *
  28. * Usage:
  29. *
  30. * <?php
  31. *
  32. * // saving a new version
  33. * Versions::add ($obj);
  34. *
  35. * // getting the history of an object
  36. * $history = Versions::history ($obj);
  37. *
  38. * // get recent changes by current user
  39. * $recent = Versions::recent (User::$user);
  40. *
  41. * // compare current version of a web page to previous:
  42. *
  43. * // 1. fetch the page
  44. * $w = new Webpage ('index');
  45. *
  46. * // 2. get the previous version (limit=1, offset=1)
  47. * $history = Versions::history ($w, 1, 1);
  48. *
  49. * // 3. restore the first result's object
  50. * $v = new Versions;
  51. * $w2 = $v->restore ($history[0]);
  52. *
  53. * // 4. compare the two
  54. * $modified_fields = Versions::diff ($w, $w2);
  55. *
  56. * ?>
  57. *
  58. * Fields:
  59. *
  60. * - `id` - versions id
  61. * - `class` - class name of the object
  62. * - `pkey` - object's 'key' field value
  63. * - `user` - user id or 0 if no user saved
  64. * - `ts` - date/time of the change
  65. * - `serialized` - serialized version of the object
  66. */
  67. class Versions extends Model {
  68. /**
  69. * The database table name.
  70. */
  71. public $table = '#prefix#versions';
  72. /**
  73. * Add a version to the store.
  74. */
  75. public static function add ($obj) {
  76. $v = new Versions (array (
  77. 'class' => get_class ($obj),
  78. 'pkey' => $obj->{$obj->key},
  79. 'user' => (! User::$user) ? 0 : User::val ('id'),
  80. 'ts' => gmdate ('Y-m-d H:i:s'),
  81. 'serialized' => json_encode ($obj->data)
  82. ));
  83. $v->put ();
  84. return $v;
  85. }
  86. /**
  87. * Recreate an object from the stored version. Takes any
  88. * result from `recent()` or `history()`.
  89. */
  90. public function restore ($vobj = false) {
  91. if (! $vobj) {
  92. $vobj = $this;
  93. }
  94. $class = $vobj->class;
  95. $data = json_decode ($vobj->serialized);
  96. // determine if it's a deleted item
  97. $tmp = new $class;
  98. $obj = new $class ($data->{$tmp->key});
  99. if ($obj->error) {
  100. $obj = new $class ($data);
  101. } else {
  102. $obj = new $class ($data, false);
  103. }
  104. return $obj;
  105. }
  106. /**
  107. * Get recent versions by a user or everyone.
  108. */
  109. public static function recent ($user = false, $limit = 10, $offset = 0) {
  110. $v = Versions::query ();
  111. if ($user !== false) {
  112. $v->where ('user', $user);
  113. }
  114. return $v->order ('ts desc')
  115. ->group ('class')
  116. ->group ('pkey')
  117. ->fetch_orig ($limit, $offset);
  118. }
  119. /**
  120. * Get recent versions of an object, or of objects of a specific
  121. * class. If `$limit` is set to `true` (boolean), it will return
  122. * a count of the history.
  123. */
  124. public static function history ($obj, $limit = 10, $offset = 0) {
  125. if ($limit === true) {
  126. if (is_string ($obj)) {
  127. return count (Versions::query ()
  128. ->where ('class', $obj)
  129. ->group ('pkey')
  130. ->fetch_field ('pkey'));
  131. }
  132. return count (Versions::query ()
  133. ->where ('class', get_class ($obj))
  134. ->where ('pkey', $obj->{$obj->key})
  135. ->fetch_field ('pkey'));
  136. }
  137. if (is_string ($obj)) {
  138. return Versions::query ()
  139. ->where ('class', $obj)
  140. ->order ('ts desc')
  141. ->group ('pkey')
  142. ->fetch_orig ($limit, $offset);
  143. }
  144. return Versions::query ()
  145. ->where ('class', get_class ($obj))
  146. ->where ('pkey', $obj->{$obj->key})
  147. ->order ('ts desc')
  148. ->fetch_orig ($limit, $offset);
  149. }
  150. /**
  151. * Compare two versions of a Model object. Returns an array of properties
  152. * that have changed between the two versions, but does no comparison
  153. * of the changes themselves. Note that this looks at the data array
  154. * of the Model objects, not object properties, so it will not work
  155. * on ordinary objects, only Model-based objects and objects returned
  156. * by the `recent()` and `history()` methods.
  157. */
  158. public static function diff ($obj1, $obj2) {
  159. if (get_class ($obj1) === 'stdClass') {
  160. $v = new Versions;
  161. $obj1 = $v->restore ($obj1);
  162. }
  163. if (get_class ($obj2) === 'stdClass') {
  164. $v = new Versions;
  165. $obj2 = $v->restore ($obj2);
  166. }
  167. $changed = array ();
  168. foreach ($obj1->data as $key => $value) {
  169. if ($value !== $obj2->data[$key]) {
  170. $changed[] = $key;
  171. }
  172. }
  173. return $changed;
  174. }
  175. /**
  176. * Get a list of classes that have objects stored.
  177. */
  178. public static function get_classes () {
  179. return DB::shift_array (
  180. 'select distinct class from #prefix#versions order by class asc'
  181. );
  182. }
  183. }
  184. ?>