Source for file RecordField.class.php

Documentation is available at RecordField.class.php

  1. <?php
  2.  
  3. require_once HARMONI."dataManager/record/RecordFieldValue.class.php";
  4.  
  5. /**
  6. * Holds a number of indexes for values within a specific field within a Record. For those fields with
  7. * only one value, only index 0 will be used. Otherwise, indexes will be created in numerical order (1, 2, ...).
  8. *
  9. * @package harmoni.datamanager
  10. *
  11. * @copyright Copyright &copy; 2005, Middlebury College
  12. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License (GPL)
  13. *
  14. * @version $Id: RecordField.class.php,v 1.22 2007/09/04 20:25:31 adamfranco Exp $
  15. ***/
  16. class RecordField {
  17. var $_values;
  18. var $_parent;
  19. var $_schemaField;
  20. var $_myLabel;
  21. var $_id;
  22. function RecordField( $schemaField, $parent ) {
  23. $this->_myLabel = $schemaField->getLabel();
  24. $this->_parent =$parent;
  25. $this->_schemaField =$schemaField;
  26. $this->_values = array();
  27. }
  28. /**
  29. * Takes a number of DB rows and sets up {@link RecordFieldValue} objects corresponding to the data within the rows.
  30. * @return bool
  31. * @param ref array $arrayOfRows
  32. */
  33. function populate( $arrayOfRows ) {
  34. foreach (array_keys($arrayOfRows) as $key) {
  35. $this->takeRow($arrayOfRows[$key]);
  36. }
  37. }
  38. /**
  39. * Takes a single row from a database and attempts to populate local objects.
  40. * @param ref array $row
  41. * @return void
  42. */
  43. function takeRow( $row ) {
  44. // If we don't just have null values...
  45. if ($row['record_field_index'] != NULL) {
  46. $i = $row['record_field_index'];
  47. if (!isset($this->_values[$i])) {
  48. // print "importing index $i : " . print_r($row, 1) . "<br>";
  49. $this->_values[$i] = new RecordFieldValue($this,$i);
  50. }
  51. $this->_values[$i]->takeRow($row);
  52. }
  53. }
  54. /**
  55. * Returns the indices for a multi-valued field. Will only return those values that are active (for version-controlled Records).
  56. * @param optional boolean $includeInactive Includes inactive indices as well.
  57. * @access public
  58. * @return array
  59. */
  60. function getIndices($includeInactive = false)
  61. {
  62. if ($includeInactive)
  63. return array_keys($this->_values);
  64. $array = array();
  65. foreach (array_keys($this->_values) as $key) {
  66. if (!$this->isIndexDeleted($key))
  67. $array[] = $key;
  68. }
  69. return $array;
  70. }
  71. /**
  72. * Re-indexes all the values so that they start from 0 and increment by 1. Useful when indexes in the middle have been deleted.
  73. * @access public
  74. * @return void
  75. */
  76. function reIndex()
  77. {
  78. $this->_parent->makeFull();
  79. $indices = $this->getIndices();
  80. $i = 0;
  81. $newValues = array();
  82. foreach($indices as $index) {
  83. $value =$this->getRecordFieldValue($index);
  84. $value->setIndex($i);
  85. $newValues[$i] =$value;
  86. $i++;
  87. }
  88. $this->_values =$newValues;
  89. }
  90. /**
  91. * Spiders through each index and calls commit() on it.
  92. * @return void
  93. */
  94. function commit() {
  95. // cycle through each index and commit()
  96. // if any indexes are going to be completely pruned, we need to keep track of those
  97. // so that we can unset them after we're done comitting.
  98. $pruned = array();
  99. foreach ($this->getIndices(true) as $i) {
  100. if ($this->_values[$i]->willPruneAll()) $pruned[] = $i;
  101. $this->_values[$i]->commit();
  102. }
  103. foreach ($pruned as $i) {
  104. unset ($this->_values[$i]);
  105. }
  106. }
  107. /**
  108. * Goes through all the old versions of values and actually DELETES them from the database once commit() is called.
  109. * @param ref object $versionConstraint A {@link VersionConstraint) on which to base our pruning.}
  110. * @return void
  111. */
  112. function prune($versionConstraint) {
  113. $this->_parent->makeFull();
  114. // just step through each ValueVersions object and call prune()
  115. $j = 0;
  116. foreach ($this->getIndices(true) as $i) {
  117. $this->_values[$i]->prune($versionConstraint);
  118. // now, if we are pruning and we will completely remove an index within this field,
  119. // we need to re-index the fields and make sure they update.
  120. // so, if the field is going to have an active value, then we're going to re-index it (???? or always?)
  121. $this->_values[$i]->setIndex($j++);
  122. }
  123. }
  124. /**
  125. * Returns the {@link RecordFieldValue} object associated with $index.
  126. * @return ref object
  127. * @param int $index
  128. */
  129. function getRecordFieldValue($index) {
  130. $this->_parent->makeCurrent();
  131. if (!isset($this->_values[$index])) {
  132. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  133. }
  134. return $this->_values[$index];
  135. }
  136. /**
  137. * Checks to make sure that the {@link Primitive} object is of the appropriate type for this label.
  138. * @return bool
  139. * @param ref object $object The {@link Primitive} object.
  140. */
  141. function _checkObjectType($object) {
  142. $dataTypeManager = Services::getService("DataTypeManager");
  143. $type = $this->_schemaField->getType();
  144. if ($dataTypeManager->isObjectOfDataType($object,$type)) return true;
  145. // otherwise... throw an error.
  146. throwError( new Error(
  147. "While trying to add/set a value in Record ID ".$this->_parent->getID().", we recieved an unexpected
  148. data type. Expecting: $type, but got an object of class ".get_class($object).".", "Record",true));
  149. return false;
  150. }
  151. /**
  152. * Adds $value to a new index within this label, assuming it allows multiple values.
  153. * @return bool
  154. * @param ref object $value A {@link SObject} object.
  155. */
  156. function addValueFromPrimitive($value) {
  157. // make sure that we have all our values & indices represented before trying to add a new one
  158. // or we might "overwrite" an existing one that's been deactivated.
  159. $this->_parent->makeFull();
  160.  
  161. // if we are one-value only and we already have a value, throw an error.
  162. // allow addValue() if we don't have any values yet.
  163. if (!$this->_schemaField->getMultFlag() && $this->numValues(true)) {
  164. $label = $this->_myLabel;
  165. throwError ( new Error(
  166. "Field label '$label' can not add a new value because it does not allow multiple
  167. values. In Schema ".$this->_parent->getSchemaID().".",
  168. "Record",true));
  169. return false;
  170. }
  171. // Call the appropriate conversion method in case we were passed a
  172. // value of the wrong type, but that can be properly converted, say
  173. // we are given a date, but want to save it as a string.
  174. $dataTypeManager = Services::getService("DataTypeManager");
  175. $type = $this->_schemaField->getType();
  176. // Ensure that the value can be converted
  177. if (method_exists($value, $dataTypeManager->getConversionMethod($type))) {
  178. eval('$value =$value->'.$dataTypeManager->getConversionMethod($type).'();');
  179. }
  180. $this->_checkObjectType($value);
  181. $newIndex = $this->_getNextAvailableIndex();
  182. $this->_values[$newIndex] = new RecordFieldValue($this, $newIndex);
  183. $this->_values[$newIndex]->setValueFromPrimitive($value);
  184. return true;
  185. }
  186. function _getNextAvailableIndex() {
  187. for($i=0; true; $i++) {
  188. if (!in_array($i,$this->getIndices(true))) return $i;
  189. }
  190. print "<b>Eh? We can't find a new index?</b><br />";
  191. printDebugBacktrace(); exit();
  192. }
  193. /**
  194. * Attempts to set the value of $index to $value. If the Record is version controlled, this will
  195. * add a new version rather than set the existing value.
  196. * @return bool
  197. * @param int $index
  198. * @param ref object $value A {@link SObject} object.
  199. */
  200. function setValueFromPrimitive($index, $value) {
  201. // Call the appropriate conversion method in case we were passed a
  202. // value of the wrong type, but that can be properly converted, say
  203. // we are given a date, but want to save it as a string.
  204. $dataTypeManager = Services::getService("DataTypeManager");
  205. $type = $this->_schemaField->getType();
  206. // Ensure that the value can be converted
  207. if (method_exists($value, $dataTypeManager->getConversionMethod($type))) {
  208. eval('$value =$value->'.$dataTypeManager->getConversionMethod($type).'();');
  209. }
  210. $this->_checkObjectType($value);
  211. $this->_parent->makeFull();
  212. // any field can have at least one value.. if index 0 is not yet set up, set it up
  213. if ($index == 0 && !isset($this->_values[0])) {
  214. $this->addValueFromPrimitive($value);
  215. }
  216. if (!isset($this->_values[$index])) {
  217. // if we allow multiple values, just create a new value at $index
  218. if ($this->_schemaField->getMultFlag()) {
  219. $this->_values[$index] = new RecordFieldValue($this, $index);
  220. } else
  221. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  222. }
  223. return $this->_values[$index]->setValueFromPrimitive($value);
  224. }
  225. /**
  226. * Deactivates all versions under index $index.
  227. * @return bool
  228. * @param int $index
  229. */
  230. function deleteValue($index) {
  231. $this->_parent->makeCurrent();
  232. if (!isset($this->_values[$index])) {
  233. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  234. }
  235. // if we are version-controlled, just unset the active flag.
  236. // otherwise, we will actually delete the value from the db.
  237. // this functionality is actually handled by RecordFieldValue
  238. $this->_values[$index]->setActiveFlag(false);
  239. return true;
  240. }
  241. /**
  242. * Re-activates the newest version of $index.
  243. * @return bool
  244. * @param int $index
  245. */
  246. function undeleteValue($index) {
  247. $this->_parent->makeFull();
  248. if (!isset($this->_values[$index])) {
  249. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  250. }
  251. $this->_values[$index]->setActiveFlag(true);
  252. return true;
  253. }
  254. /**
  255. * Checks if the index has been deleted.
  256. * @param integer $index
  257. * @access public
  258. * @return bool
  259. */
  260. function isIndexDeleted($index)
  261. {
  262. $this->_parent->makeFull();
  263. if (!isset($this->_values[$index])) {
  264. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  265. }
  266. return !$this->_values[$index]->isActive();
  267. }
  268. /**
  269. * Returns the number of values for this label we have set.
  270. * @return int
  271. * @access public
  272. * @param optional boolean $includeInactive if TRUE will include inactive values in the count.
  273. */
  274. function numValues($includeInactive = false) {
  275. if ($includeInactive) {
  276. $this->_parent->makeFull();
  277. return count($this->_values);
  278. }
  279. $this->_parent->makeCurrent();
  280. return count($this->getIndices());
  281. }
  282.  
  283. /**
  284. * Returns the number of versions we have set for specific $index.
  285. * @return int
  286. * @param optional int $index Defaults to 0.
  287. */
  288. function numVersions( $index=0 ) {
  289. $this->_parent->makeFull();
  290. if (!isset($this->_values[$index])) {
  291. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  292. }
  293. return $this->_values[$index]->numVersions();
  294. }
  295. /**
  296. * Returns an array of version IDs associated with $index.
  297. * @return array
  298. * @param optional int $index Defaults to 0.
  299. */
  300. function getVersionIDs( $index=0 ) {
  301. $this->_parent->makeFull();
  302. if (!isset($this->_values[$index])) {
  303. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  304. }
  305. return $this->_values[$index]->getVersionIDs();
  306. }
  307. /**
  308. * Returns the {@link RecordFieldData} object associated with $verID under $index.
  309. * @return ref object
  310. * @param int $verID
  311. * @param optional int $index Defaults to 0.
  312. */
  313. function getVersion( $verID, $index=0 ) {
  314. $this->_parent->makeFull();
  315. if (!isset($this->_values[$index])) {
  316. throwError( new ValueIndexNotFoundError($this->_myLabel, $this->_parent->getID(), $index));
  317. }
  318. return $this->_values[$index]->getVersion($verID);
  319. }
  320. /**
  321. * Returns the Record object that the current object is a part of.
  322. * @return ref object Record The parent Record object
  323. */
  324. function getRecord() {
  325. return $this->_parent;
  326. }
  327. /**
  328. * Returns the {@link SchemaField} object for the this RecordField object.
  329. * @return ref objectThe {@link SchemaField} object.
  330. */
  331. function getSchemaField() {
  332. return $this->_schemaField;
  333. }
  334.  
  335. /**
  336. * Returns the id of this RecordField object.
  337. * @return ref object Id The id of this RecordField object.
  338. */
  339. function getId() {
  340. if (!isset($this->_id)) {
  341. $idManager = Services::getService("Id");
  342. $idString = $this->_parent->getID()."::".$this->_myLabel;
  343. $this->_id =$idManager->getId($idString);
  344. }
  345. return $this->_id;
  346. }
  347. }
  348.  
  349. ?>

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