Entity.php 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016, ownCloud, Inc.
  4. *
  5. * @author Bernhard Posselt <dev@bernhard-posselt.com>
  6. * @author Morris Jobke <hey@morrisjobke.de>
  7. *
  8. * @license AGPL-3.0
  9. *
  10. * This code is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License, version 3,
  12. * as published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Affero General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Affero General Public License, version 3,
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>
  21. *
  22. */
  23. namespace OCP\AppFramework\Db;
  24. /**
  25. * @method integer getId()
  26. * @method void setId(integer $id)
  27. * @since 7.0.0
  28. */
  29. abstract class Entity {
  30. public $id;
  31. private $_updatedFields = array();
  32. private $_fieldTypes = array('id' => 'integer');
  33. /**
  34. * Simple alternative constructor for building entities from a request
  35. * @param array $params the array which was obtained via $this->params('key')
  36. * in the controller
  37. * @return Entity
  38. * @since 7.0.0
  39. */
  40. public static function fromParams(array $params) {
  41. $instance = new static();
  42. foreach($params as $key => $value) {
  43. $method = 'set' . ucfirst($key);
  44. $instance->$method($value);
  45. }
  46. return $instance;
  47. }
  48. /**
  49. * Maps the keys of the row array to the attributes
  50. * @param array $row the row to map onto the entity
  51. * @since 7.0.0
  52. */
  53. public static function fromRow(array $row){
  54. $instance = new static();
  55. foreach($row as $key => $value){
  56. $prop = ucfirst($instance->columnToProperty($key));
  57. $setter = 'set' . $prop;
  58. $instance->$setter($value);
  59. }
  60. $instance->resetUpdatedFields();
  61. return $instance;
  62. }
  63. /**
  64. * @return array with attribute and type
  65. * @since 7.0.0
  66. */
  67. public function getFieldTypes() {
  68. return $this->_fieldTypes;
  69. }
  70. /**
  71. * Marks the entity as clean needed for setting the id after the insertion
  72. * @since 7.0.0
  73. */
  74. public function resetUpdatedFields(){
  75. $this->_updatedFields = array();
  76. }
  77. /**
  78. * Generic setter for properties
  79. * @since 7.0.0
  80. */
  81. protected function setter($name, $args) {
  82. // setters should only work for existing attributes
  83. if(property_exists($this, $name)){
  84. if($this->$name === $args[0]) {
  85. return;
  86. }
  87. $this->markFieldUpdated($name);
  88. // if type definition exists, cast to correct type
  89. if($args[0] !== null && array_key_exists($name, $this->_fieldTypes)) {
  90. settype($args[0], $this->_fieldTypes[$name]);
  91. }
  92. $this->$name = $args[0];
  93. } else {
  94. throw new \BadFunctionCallException($name .
  95. ' is not a valid attribute');
  96. }
  97. }
  98. /**
  99. * Generic getter for properties
  100. * @since 7.0.0
  101. */
  102. protected function getter($name) {
  103. // getters should only work for existing attributes
  104. if(property_exists($this, $name)){
  105. return $this->$name;
  106. } else {
  107. throw new \BadFunctionCallException($name .
  108. ' is not a valid attribute');
  109. }
  110. }
  111. /**
  112. * Each time a setter is called, push the part after set
  113. * into an array: for instance setId will save Id in the
  114. * updated fields array so it can be easily used to create the
  115. * getter method
  116. * @since 7.0.0
  117. */
  118. public function __call($methodName, $args){
  119. $attr = lcfirst( substr($methodName, 3) );
  120. if(strpos($methodName, 'set') === 0){
  121. $this->setter($attr, $args);
  122. } elseif(strpos($methodName, 'get') === 0) {
  123. return $this->getter($attr);
  124. } else {
  125. throw new \BadFunctionCallException($methodName .
  126. ' does not exist');
  127. }
  128. }
  129. /**
  130. * Mark am attribute as updated
  131. * @param string $attribute the name of the attribute
  132. * @since 7.0.0
  133. */
  134. protected function markFieldUpdated($attribute){
  135. $this->_updatedFields[$attribute] = true;
  136. }
  137. /**
  138. * Transform a database columnname to a property
  139. * @param string $columnName the name of the column
  140. * @return string the property name
  141. * @since 7.0.0
  142. */
  143. public function columnToProperty($columnName){
  144. $parts = explode('_', $columnName);
  145. $property = null;
  146. foreach($parts as $part){
  147. if($property === null){
  148. $property = $part;
  149. } else {
  150. $property .= ucfirst($part);
  151. }
  152. }
  153. return $property;
  154. }
  155. /**
  156. * Transform a property to a database column name
  157. * @param string $property the name of the property
  158. * @return string the column name
  159. * @since 7.0.0
  160. */
  161. public function propertyToColumn($property){
  162. $parts = preg_split('/(?=[A-Z])/', $property);
  163. $column = null;
  164. foreach($parts as $part){
  165. if($column === null){
  166. $column = $part;
  167. } else {
  168. $column .= '_' . lcfirst($part);
  169. }
  170. }
  171. return $column;
  172. }
  173. /**
  174. * @return array array of updated fields for update query
  175. * @since 7.0.0
  176. */
  177. public function getUpdatedFields(){
  178. return $this->_updatedFields;
  179. }
  180. /**
  181. * Adds type information for a field so that its automatically casted to
  182. * that value once its being returned from the database
  183. * @param string $fieldName the name of the attribute
  184. * @param string $type the type which will be used to call settype()
  185. * @since 7.0.0
  186. */
  187. protected function addType($fieldName, $type){
  188. $this->_fieldTypes[$fieldName] = $type;
  189. }
  190. /**
  191. * Slugify the value of a given attribute
  192. * Warning: This doesn't result in a unique value
  193. * @param string $attributeName the name of the attribute, which value should be slugified
  194. * @return string slugified value
  195. * @since 7.0.0
  196. */
  197. public function slugify($attributeName){
  198. // toSlug should only work for existing attributes
  199. if(property_exists($this, $attributeName)){
  200. $value = $this->$attributeName;
  201. // replace everything except alphanumeric with a single '-'
  202. $value = preg_replace('/[^A-Za-z0-9]+/', '-', $value);
  203. $value = strtolower($value);
  204. // trim '-'
  205. return trim($value, '-');
  206. } else {
  207. throw new \BadFunctionCallException($attributeName .
  208. ' is not a valid attribute');
  209. }
  210. }
  211. }