Source for file RecordFieldValue.class.php

Documentation is available at RecordFieldValue.class.php

  1. <?php
  2.  
  3. require_once(HARMONI."dataManager/record/RecordFieldData.class.php");
  4.  
  5. /**
  6. * @constant string NEW_VERSION Used when created a new version to be attached to a value.
  7. * @package harmoni.datamanager
  8. */
  9. define("NEW_VERSION","new");
  10.  
  11. /**
  12. * Responsible for keeping track of multiple versions of a value for a specific index within a
  13. * field within a Record.
  14. *
  15. * @package harmoni.datamanager
  16. *
  17. * @copyright Copyright &copy; 2005, Middlebury College
  18. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)
  19. *
  20. * @version $Id: RecordFieldValue.class.php,v 1.22 2007/09/04 20:25:32 adamfranco Exp $
  21. *
  22. * @author Gabe Schine
  23. */
  24. class RecordFieldValue {
  25. var $_numVersions;
  26. var $_parent;
  27. var $_myIndex;
  28. var $_versions;
  29. var $_oldVersion;
  30. var $_id;
  31. function RecordFieldValue ($parent, $myIndex) {
  32. $this->_parent =$parent;
  33. $this->_numVersions = 0;
  34. $this->_myIndex = $myIndex;
  35. $this->_versions = array();
  36. $this->_oldVersion = null;
  37. }
  38. /**
  39. * Sets up a number of {@link RecordFieldData} objects based on an array of database rows.
  40. * @return void
  41. * @param ref array $arrayOfRows
  42. */
  43. function populate( $arrayOfRows ) {
  44. // we are responsible for keeping track of multiple RecordFieldData objects,
  45. // each corresponding to a specific version of a value of a field.
  46. foreach (array_keys($arrayOfRows) as $key) {
  47. $this->takeRow($arrayOfRows[$key]);
  48. }
  49. }
  50. /**
  51. * Takes a single row from a database and attempts to populate local objects.
  52. * @param ref array $row
  53. * @return void
  54. */
  55. function takeRow( $row ) {
  56. // If we don't just have null values...
  57. if ($row['record_field_id']) {
  58. $verID = $row['record_field_id'];
  59. $active = $row['record_field_active']?true:false;
  60. $this->_versions[$verID] = new RecordFieldData($this,$active);
  61. $this->_versions[$verID]->populate($row);
  62. $this->_numVersions++;
  63. }
  64. }
  65. /**
  66. * Commits the existing (and new, if applicable) versions of this value to the database. If the Record
  67. * is version controlled and the new value is the same as the old value, it is ignored.
  68. * @return void
  69. */
  70. function commit() {
  71. // before we commit, if we have a newVersion and an oldVersion,
  72. // let's check to see if their values are equal. if they are,
  73. // we can scrap the new version to save on DB space.
  74. if (isset($this->_versions[NEW_VERSION]) && isset($this->_oldVersion)) {
  75. $oldVal =$this->_oldVersion->getPrimitive();
  76. $newVal =$this->_versions[NEW_VERSION]->getPrimitive();
  77. if ($oldVal->isEqual($newVal)) {
  78. // let's kill the new version
  79. unset($this->_versions[NEW_VERSION]);
  80. $this->_numVersions--;
  81. $this->_oldVersion->setActiveFlag(true);
  82. }
  83. }
  84. // keep track of those versions that will be pruned, so we unset them after pruning.
  85. $pruned = array();
  86. foreach ($this->getVersionIDs() as $ver) {
  87. $verPrim =$this->_versions[$ver]->getPrimitive();
  88. if ($this->_versions[$ver]->willPrune()) $pruned[] = $ver;
  89. $this->_versions[$ver]->commit();
  90. }
  91. // now if we just committed a NEW_VERSION, let's move it to its proper place in the array
  92. if (isset($this->_versions[NEW_VERSION])) {
  93. $ref =$this->_versions[NEW_VERSION];
  94. $id = $ref->getID();
  95. if (!$id) return;
  96. $this->_versions[$id] =$this->_versions[NEW_VERSION];
  97. // now unset the old
  98. unset ($this->_versions[NEW_VERSION], $ref);
  99. // done.
  100. }
  101. foreach ($pruned as $id) {
  102. unset($this->_versions[$id]);
  103. }
  104. }
  105. /**
  106. * USED INTERNALLY: Returns true if all of our versions are about to be pruned.
  107. * @access public
  108. * @return bool
  109. */
  110. function willPruneAll()
  111. {
  112. foreach ($this->getVersionIDs() as $id) {
  113. $ver =$this->getVersion($id);
  114. if (!$ver->willPrune()) return false;
  115. }
  116. return true;
  117. }
  118. /**
  119. * Goes through all the old versions of values and actually DELETES them from the database.
  120. * @param ref object $versionConstraint A {@link VersionConstraint) on which to base our pruning.}
  121. * @return void
  122. */
  123. function prune($versionConstraint) {
  124. $versionConstraint->checkRecordFieldValue($this);
  125. }
  126. /**
  127. * Returns the number of versions we have set for this value.
  128. * @return int
  129. */
  130. function numVersions() {
  131. return $this->_numVersions;
  132. }
  133. /**
  134. * sets the index of this entry to $index.
  135. * @param int $index
  136. * @return bool TRUE if the index was changed. FALSE if not.
  137. */
  138. function setIndex( $index ) {
  139. if ($index == $this->_myIndex) return false;
  140. $this->_myIndex = $index;
  141. // now go through and tell all our values to update.
  142. foreach ($this->getVersionIDs() as $id) {
  143. $ver =$this->getVersion($id);
  144. $ver->update();
  145. }
  146. return true;
  147. }
  148. /**
  149. * Returns the index of this RecordFieldValue object.
  150. *
  151. * @return integer The index.
  152. */
  153. function getIndex() {
  154. return $this->_myIndex;
  155. }
  156. /**
  157. * "Sets" the value of this specific index to $value. If the Record is version controlled, a new
  158. * version is added. Otherwise, the current active version is modified.
  159. * @return bool
  160. * @param ref object $value A {@link SObject} object.
  161. */
  162. function setValueFromPrimitive($value) {
  163.  
  164. // if we're version controlled, we're adding a new version
  165. // otherwise, we're just setting the existing (or only active) one.
  166. if ($this->_parent->_parent->isVersionControlled()) { // @todo This is referencing another object's private variables. Bad!! Fix this!
  167. // we're going to add a new version
  168. // which means, we add a new RecordFieldValue with a *replicate*
  169. // of the primitive, so that it gets added to the DB.
  170. $newVer =$this->newRecordFieldData();
  171. $clone =$value->copy();
  172. $newVer->setValueFromPrimitive($clone);
  173. // all done (we hope)
  174. return true;
  175. }
  176. // let's just set the value of the existing one.
  177. // if we have an active version, set that one.
  178. if (!$this->hasActiveValue()) {
  179. $this->undelete();
  180. }
  181. $actVer =$this->getActiveVersion();
  182. $actVal =$actVer->getPrimitive();
  183. if ($actVal && $actVal->isEqual($value))
  184. return true;
  185.  
  186. $actVer->takeValueFromPrimitive($value);
  187. $actVer->setDate(DateAndTime::now());
  188. // now tell actVer to update the DB on commit()
  189. $actVer->update();
  190. return true;
  191. }
  192. /**
  193. * Returns a reference to a new {@link RecordFieldData} object and adds it to the list of versions for this value. USED INTERNALLY ONLY
  194. * @access protected
  195. * @return ref object
  196. */
  197. function newRecordFieldData() {
  198. if (!isset($this->_versions[NEW_VERSION])) {
  199. // first deactivate the old one
  200. if ($this->_numVersions) {
  201. $old =$this->getActiveVersion();
  202. if ($old) {
  203. $old->setActiveFlag(false);
  204. $old->update();
  205. $this->_oldVersion =$old;
  206. }
  207. }
  208. $this->_versions[NEW_VERSION] = new RecordFieldData($this,true);
  209. $this->_versions[NEW_VERSION]->update();
  210. $this->_numVersions++;
  211. }
  212. return $this->_versions[NEW_VERSION];
  213. }
  214. /**
  215. * Returns the active {@link RecordFieldData} object or FALSE if none exists. If no versions have yet been
  216. * set, a new {@link RecordFieldData} object is created.
  217. * @return ref object or false
  218. */
  219. function getActiveVersion() {
  220. if ($this->_numVersions == 0) {
  221. return $this->newRecordFieldData();
  222. }
  223. foreach (array_keys($this->_versions) as $id) {
  224. if ($this->_versions[$id]->isActive()) return $this->_versions[$id];
  225. }
  226. // if we get here there were no active versions.
  227. $false = false; // to compensate for the return reference
  228. return $false;
  229. }
  230. /**
  231. * Returns an array of version IDs set for this value.
  232. * @return array
  233. */
  234. function getVersionIDs() {
  235. return array_keys($this->_versions);
  236. }
  237. /**
  238. * Returns the {@link RecordFieldData} object associated with version ID $verID.
  239. * @return ref object
  240. * @param int $verID
  241. */
  242. function getVersion( $verID ) {
  243. if (!isset($this->_versions[$verID])) {
  244. throwError( new Error("Could not find version ID $verID.","Record",true));
  245. }
  246. return $this->_versions[$verID];
  247. }
  248. /**
  249. * Deactivates all existing versions for this value.
  250. * @return void
  251. */
  252. function delete() {
  253. // go through all the versions and deactivate them, if we are version controlled.
  254. // otherwise, go through the *one* version we have and actually prune it from the DB.
  255. if ($this->_parent->_parent->isVersionControlled()) {
  256. foreach ($this->getVersionIDs() as $ver) {
  257. if ($this->_versions[$ver]->getActiveFlag()) {
  258. $this->_versions[$ver]->setActiveFlag(false);
  259. $this->_versions[$ver]->update(); // update to DB on commit()
  260. }
  261. }
  262. } else {
  263. // although there should be only one version here, let's go through all to mamke sure
  264. foreach($this->getVersionIDs() as $ver) {
  265. $this->_versions[$ver]->prune();
  266. $this->_versions[$ver]->setActiveFlag(false);
  267. }
  268. }
  269. }
  270. /**
  271. * Re-activates the newest version value for this index.
  272. * @return void|trueif we're already active.
  273. */
  274. function undelete() {
  275. // if we're not active, go through and find the newest ver, then activate it.
  276. if ($this->isActive()) return true;
  277. $ver =$this->getNewestVersion();
  278. $ver->setActiveFlag(true);
  279. $ver->update(); // update to DB on commit()
  280. }
  281. /**
  282. * Calls either {@link RecordFieldValue::delete() delete()} or {@link RecordFieldValue::undelete() undelete()} depending on the value passed.
  283. * @param bool $bool
  284. * @access public
  285. * @return void
  286. */
  287. function setActiveFlag($bool)
  288. {
  289. if ($bool) $this->undelete();
  290. else $this->delete();
  291. }
  292. /**
  293. * Returns the most recently created version for this value.
  294. * @return ref object The newest {@link RecordFieldData} object.
  295. */
  296. function getNewestVersion() {
  297. $newest = null;
  298. if ($this->numVersions()) {
  299. foreach ($this->getVersionIDs() as $ver) {
  300. $version =$this->getVersion($ver);
  301. $versionDate =$version->getDate();
  302. if ($newest == null || $versionDate->isGreaterThan($newest->getDate())) {
  303. $newest =$version;
  304. }
  305. }
  306. }
  307. return $newest;
  308. }
  309. /**
  310. * Returns TRUE if a version is active, or if we have no versions defined yet. FALSE otherwise.
  311. * @return bool
  312. */
  313. function isActive() {
  314. if ($this->_numVersions == 0) return true; // if we don't have any values yet, assume we are active
  315. return $this->hasActiveValue();
  316. }
  317. /**
  318. * Returns TRUE if we have an active version.
  319. * @return bool
  320. */
  321. function hasActiveValue() {
  322. foreach ($this->getVersionIDs() as $verID) {
  323. if ($this->_versions[$verID]->isActive()) return true;
  324. }
  325. return false;
  326. }
  327. /**
  328. * Returns a new {@link RecordFieldData} object that is an exact data-specific replicate of the current object.
  329. * @param ref object A reference to a {@link RecordField} object that will act as the parent.
  330. * @return ref object
  331. */
  332. function replicate($parent) {
  333. $newObj = new RecordFieldValue($parent, $this->_myIndex);
  334. $this->_parent->_parent->makeFull();
  335. foreach ($this->getVersionIDs() as $verID) {
  336. $ver =$this->getVersion($verID);
  337. $newObj->_versions[++$newObj->_numVersions] =$ver->replicate($newObj);
  338. }
  339. return $newObj;
  340. }
  341. /**
  342. * Returns the {@link RecordField} object that the current object is a part of.
  343. * @return ref object FieldValues The parent {@link RecordField} object
  344. */
  345. function getRecordField() {
  346. return $this->_parent;
  347. }
  348. /**
  349. * Returns the id this RecordFieldValue object. The unique ID for the info
  350. * field should be the
  351. * RecordID::SchemaFieldLabel::RecordFieldValueIndex
  352. * @return ref object Id The id of this object.
  353. */
  354. function getId() {
  355. if (!isset($this->_id)) {
  356. $idManager = Services::getService("Id");
  357. $FieldValuesId =$this->_parent->getId();
  358. $idString = $FieldValuesId->getIdString()."::".$this->_myIndex;
  359. $this->_id =$idManager->getId($idString);
  360. }
  361. return $this->_id;
  362. }
  363. }
  364.  
  365. ?>

Documentation generated on Wed, 19 Sep 2007 10:25:51 -0400 by phpDocumentor 1.3.0RC3