PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/model/fieldtypes/CompositeDBField.php

http://github.com/silverstripe/sapphire
PHP | 182 lines | 9 code | 9 blank | 164 comment | 0 complexity | cd9ca09f79d644d45a6b060f54b1f28a MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, CC-BY-3.0, GPL-2.0, AGPL-1.0, LGPL-2.1
  1. <?php
  2. /**
  3. * Apply this interface to any {@link DBField} that doesn't have a 1-1 mapping with a database field.
  4. * This includes multi-value fields and transformed fields
  5. *
  6. * @todo Unittests for loading and saving composite values (see GIS module for existing similiar unittests)
  7. *
  8. * Example with a combined street name and number:
  9. * <code>
  10. * class Street extends DBFields implements CompositeDBField() {
  11. * protected $streetNumber;
  12. * protected $streetName;
  13. * protected $isChanged = false;
  14. * static $composite_db = return array(
  15. * "Number" => "Int",
  16. * "Name" => "Text"
  17. * );
  18. *
  19. * function requireField() {
  20. * DB::requireField($this->tableName, "{$this->name}Number", 'Int');
  21. * DB::requireField($this->tableName, "{$this->name}Name", 'Text');
  22. * }
  23. *
  24. * function writeToManipulation(&$manipulation) {
  25. * if($this->getStreetName()) {
  26. * $manipulation['fields']["{$this->name}Name"] = $this->prepValueForDB($this->getStreetName());
  27. * } else {
  28. * $manipulation['fields']["{$this->name}Name"] = DBField::create('Varchar', $this->getStreetName())->nullValue();
  29. * }
  30. *
  31. * if($this->getStreetNumber()) {
  32. * $manipulation['fields']["{$this->name}Number"] = $this->prepValueForDB($this->getStreetNumber());
  33. * } else {
  34. * $manipulation['fields']["{$this->name}Number"] = DBField::create('Int', $this->getStreetNumber())->nullValue();
  35. * }
  36. * }
  37. *
  38. * function addToQuery(&$query) {
  39. * parent::addToQuery($query);
  40. * $query->select[] = "{$this->name}Number";
  41. * $query->select[] = "{$this->name}Name";
  42. * }
  43. *
  44. * function setValue($value, $record = null, $markChanged=true) {
  45. * if ($value instanceof Street && $value->hasValue()) {
  46. * $this->setStreetName($value->getStreetName(), $markChanged);
  47. * $this->setStreetNumber($value->getStreetNumber(), $markChanged);
  48. * if($markChanged) $this->isChanged = true;
  49. * } else if($record && isset($record[$this->name . 'Name']) && isset($record[$this->name . 'Number'])) {
  50. * if($record[$this->name . 'Name'] && $record[$this->name . 'Number']) {
  51. * $this->setStreetName($record[$this->name . 'Name'], $markChanged);
  52. * $this->setStreetNumber($record[$this->name . 'Number'], $markChanged);
  53. * }
  54. * if($markChanged) $this->isChanged = true;
  55. * } else if (is_array($value)) {
  56. * if (array_key_exists('Name', $value)) {
  57. * $this->setStreetName($value['Name'], $markChanged);
  58. * }
  59. * if (array_key_exists('Number', $value)) {
  60. * $this->setStreetNumber($value['Number'], $markChanged);
  61. * }
  62. * if($markChanged) $this->isChanged = true;
  63. * }
  64. * }
  65. *
  66. * function setStreetNumber($val, $markChanged=true) {
  67. * $this->streetNumber = $val;
  68. * if($markChanged) $this->isChanged = true;
  69. * }
  70. *
  71. * function setStreetName($val, $markChanged=true) {
  72. * $this->streetName = $val;
  73. * if($markChanged) $this->isChanged = true;
  74. * }
  75. *
  76. * function getStreetNumber() {
  77. * return $this->streetNumber;
  78. * }
  79. *
  80. * function getStreetName() {
  81. * return $this->streetName;
  82. * }
  83. *
  84. * function isChanged() {
  85. * return $this->isChanged;
  86. * }
  87. *
  88. * function hasValue() {
  89. * return ($this->getStreetName() || $this->getStreetNumber());
  90. * }
  91. * }
  92. * </code>
  93. *
  94. * @package sapphire
  95. * @subpackage model
  96. */
  97. interface CompositeDBField {
  98. /**
  99. * Similiar to {@link DataObject::$db},
  100. * holds an array of composite field names.
  101. * Don't include the fields "main name",
  102. * it will be prefixed in {@link requireField()}.
  103. *
  104. * @var array $composite_db
  105. */
  106. //static $composite_db;
  107. /**
  108. * Set the value of this field in various formats.
  109. * Used by {@link DataObject->getField()}, {@link DataObject->setCastedField()}
  110. * {@link DataObject->dbObject()} and {@link DataObject->write()}.
  111. *
  112. * As this method is used both for initializing the field after construction,
  113. * and actually changing its values, it needs a {@link $markChanged}
  114. * parameter.
  115. *
  116. * @param DBField|array $value
  117. * @param array $record Map of values loaded from the database
  118. * @param boolean $markChanged Indicate wether this field should be marked changed.
  119. * Set to FALSE if you are initializing this field after construction, rather
  120. * than setting a new value.
  121. */
  122. function setValue($value, $record = null, $markChanged = true);
  123. /**
  124. * Used in constructing the database schema.
  125. * Add any custom properties defined in {@link $composite_db}.
  126. * Should make one or more calls to {@link DB::requireField()}.
  127. */
  128. //abstract function requireField();
  129. /**
  130. * Add the custom internal values to an INSERT or UPDATE
  131. * request passed through the ORM with {@link DataObject->write()}.
  132. * Fields are added in $manipulation['fields']. Please ensure
  133. * these fields are escaped for database insertion, as no
  134. * further processing happens before running the query.
  135. * Use {@link DBField->prepValueForDB()}.
  136. * Ensure to write NULL or empty values as well to allow
  137. * unsetting a previously set field. Use {@link DBField->nullValue()}
  138. * for the appropriate type.
  139. *
  140. * @param array $manipulation
  141. */
  142. function writeToManipulation(&$manipulation);
  143. /**
  144. * Add all columns which are defined through {@link requireField()}
  145. * and {@link $composite_db}, or any additional SQL that is required
  146. * to get to these columns. Will mostly just write to the {@link SQLQuery->select}
  147. * array.
  148. *
  149. * @param SQLQuery $query
  150. */
  151. function addToQuery(&$query);
  152. /**
  153. * Return array in the format of {@link $composite_db}.
  154. * Used by {@link DataObject->hasOwnDatabaseField()}.
  155. * @return array
  156. */
  157. function compositeDatabaseFields();
  158. /**
  159. * Determines if the field has been changed since its initialization.
  160. * Most likely relies on an internal flag thats changed when calling
  161. * {@link setValue()} or any other custom setters on the object.
  162. *
  163. * @return boolean
  164. */
  165. function isChanged();
  166. /**
  167. * Determines if any of the properties in this field have a value,
  168. * meaning at least one of them is not NULL.
  169. *
  170. * @return boolean
  171. */
  172. function hasValue();
  173. }