PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/_releases/apps/sweeper-bundle/core/Modules/RedBean/OODB.php

https://github.com/adammoore/Swiftriver
PHP | 326 lines | 160 code | 24 blank | 142 comment | 31 complexity | 620de892f13d97ba1cdad4a0371ca86c MD5 | raw file
  1. <?php
  2. /**
  3. * @name RedBean OODB
  4. * @file RedBean
  5. * @author Gabor de Mooij and the RedBean Team
  6. * @copyright Gabor de Mooij (c)
  7. * @license BSD
  8. *
  9. * The RedBean OODB Class is the main class of RedBean.
  10. * It takes RedBean_OODBBean objects and stores them to and loads them from the
  11. * database as well as providing other CRUD functions. This class acts as a
  12. * object database.
  13. *
  14. */
  15. class RedBean_OODB extends RedBean_Observable implements RedBean_ObjectDatabase {
  16. /**
  17. *
  18. * @var array
  19. */
  20. private $stash = NULL;
  21. /**
  22. *
  23. * @var RedBean_Adapter_DBAdapter
  24. */
  25. private $writer;
  26. /**
  27. *
  28. * @var boolean
  29. */
  30. private $isFrozen = false;
  31. /**
  32. * The RedBean OODB Class is the main class of RedBean.
  33. * It takes RedBean_OODBBean objects and stores them to and loads them from the
  34. * database as well as providing other CRUD functions. This class acts as a
  35. * object database.
  36. * Constructor, requires a DBAadapter (dependency inversion)
  37. * @param RedBean_Adapter_DBAdapter $adapter
  38. */
  39. public function __construct( RedBean_QueryWriter $writer ) {
  40. $this->writer = $writer;
  41. }
  42. /**
  43. * Toggles fluid or frozen mode. In fluid mode the database
  44. * structure is adjusted to accomodate your objects. In frozen mode
  45. * this is not the case.
  46. * @param boolean $trueFalse
  47. */
  48. public function freeze( $tf ) {
  49. $this->isFrozen = (bool) $tf;
  50. }
  51. /**
  52. * Returns the current mode of operation of RedBean.
  53. * In fluid mode the database
  54. * structure is adjusted to accomodate your objects.
  55. * In frozen mode
  56. * this is not the case.
  57. * @return <type>
  58. */
  59. public function isFrozen() {
  60. return (bool) $this->isFrozen;
  61. }
  62. /**
  63. * Dispenses a new bean (a RedBean_OODBBean Bean Object)
  64. * of the specified type. Always
  65. * use this function to get an empty bean object. Never
  66. * instantiate a RedBean_OODBBean yourself because it needs
  67. * to be configured before you can use it with RedBean. This
  68. * function applies the appropriate initialization /
  69. * configuration for you.
  70. * @param string $type
  71. * @return RedBean_OODBBean $bean
  72. */
  73. public function dispense($type ) {
  74. $bean = new RedBean_OODBBean();
  75. $bean->setMeta("type", $type );
  76. $idfield = $this->writer->getIDField($bean->getMeta("type"));
  77. $bean->$idfield = 0;
  78. $this->signal( "dispense", $bean );
  79. $this->check( $bean );
  80. return $bean;
  81. }
  82. /**
  83. * Checks whether a RedBean_OODBBean bean is valid.
  84. * If the type is not valid or the ID is not valid it will
  85. * throw an exception: RedBean_Exception_Security.
  86. * @throws RedBean_Exception_Security $exception
  87. * @param RedBean_OODBBean $bean
  88. */
  89. public function check( RedBean_OODBBean $bean ) {
  90. $idfield = $this->writer->getIDField($bean->getMeta("type"));
  91. //Is all meta information present?
  92. if (!isset($bean->$idfield) || !($bean->getMeta("type"))) {
  93. throw new RedBean_Exception_Security("Bean has incomplete Meta Information");
  94. }
  95. //Pattern of allowed characters
  96. $pattern = '/[^abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]/';
  97. //Does the type contain invalid characters?
  98. if (preg_match($pattern,$bean->getMeta("type"))) {
  99. throw new RedBean_Exception_Security("Bean Type is invalid");
  100. }
  101. //Are the properties and values valid?
  102. foreach($bean as $prop=>$value) {
  103. if (
  104. is_array($value) ||
  105. is_object($value) ||
  106. strlen($prop)<1 ||
  107. preg_match($pattern,$prop)
  108. ) {
  109. throw new RedBean_Exception_Security("Invalid Bean: property $prop ");
  110. }
  111. }
  112. }
  113. /**
  114. * Checks whether the specified table already exists in the database.
  115. * Not part of the Object Database interface!
  116. * @param string $table
  117. * @return boolean $exists
  118. */
  119. public function tableExists($table) {
  120. //does this table exist?
  121. $tables = $this->writer->getTables();
  122. return in_array($table, $tables);
  123. }
  124. /**
  125. * Stores a bean in the database. This function takes a
  126. * RedBean_OODBBean Bean Object $bean and stores it
  127. * in the database. If the database schema is not compatible
  128. * with this bean and RedBean runs in fluid mode the schema
  129. * will be altered to store the bean correctly.
  130. * If the database schema is not compatible with this bean and
  131. * RedBean runs in frozen mode it will throw an exception.
  132. * This function returns the primary key ID of the inserted
  133. * bean.
  134. * @throws RedBean_Exception_Security $exception
  135. * @param RedBean_OODBBean $bean
  136. * @return integer $newid
  137. */
  138. public function store( RedBean_OODBBean $bean ) {
  139. $this->signal( "update", $bean );
  140. $this->check($bean);
  141. //what table does it want
  142. $table = $bean->getMeta("type");
  143. $idfield = $this->writer->getIDField($table);
  144. //Does table exist? If not, create
  145. if (!$this->isFrozen && !$this->tableExists($table)) {
  146. $this->writer->createTable( $table );
  147. }
  148. $columns = $this->writer->getColumns($table) ;
  149. //does the table fit?
  150. $insertvalues = array();
  151. $insertcolumns = array();
  152. $updatevalues = array();
  153. foreach( $bean as $p=>$v) {
  154. if ($p!=$idfield) {
  155. if (!$this->isFrozen) {
  156. //What kind of property are we dealing with?
  157. $typeno = $this->writer->scanType($v);
  158. //Is this property represented in the table?
  159. if (isset($columns[$p])) {
  160. //yes it is, does it still fit?
  161. $sqlt = $this->writer->code($columns[$p]);
  162. if ($typeno > $sqlt) {
  163. //no, we have to widen the database column type
  164. $this->writer->widenColumn( $table, $p, $typeno );
  165. }
  166. }
  167. else {
  168. //no it is not
  169. $this->writer->addColumn($table, $p, $typeno);
  170. }
  171. }
  172. //Okay, now we are sure that the property value will fit
  173. $insertvalues[] = $v;
  174. $insertcolumns[] = $p;
  175. $updatevalues[] = array( "property"=>$p, "value"=>$v );
  176. }
  177. }
  178. if (!$this->isFrozen && ($uniques = $bean->getMeta("buildcommand.unique"))) {
  179. foreach($uniques as $unique) {
  180. $this->writer->addUniqueIndex( $table, $unique );
  181. }
  182. }
  183. if ($bean->$idfield) {
  184. if (count($updatevalues)>0) {
  185. $this->writer->updateRecord( $table, $updatevalues, $bean->$idfield );
  186. }
  187. return (int) $bean->$idfield;
  188. }
  189. else {
  190. $id = $this->writer->insertRecord( $table, $insertcolumns, array($insertvalues) );
  191. $bean->$idfield = $id;
  192. return (int) $id;
  193. }
  194. }
  195. /**
  196. * Loads a bean from the object database.
  197. * It searches for a RedBean_OODBBean Bean Object in the
  198. * database. It does not matter how this bean has been stored.
  199. * RedBean uses the primary key ID $id and the string $type
  200. * to find the bean. The $type specifies what kind of bean your
  201. * are looking for; this is the same type as used with the
  202. * dispense() function. If RedBean finds the bean it will return
  203. * the RedBean_OODB Bean object; if it cannot find the bean
  204. * RedBean will return a new bean of type $type and with
  205. * primary key ID 0. In the latter case it acts basically the
  206. * same as dispense().
  207. * If the bean cannot be found in the database a new bean of
  208. * the specified type will be generated and returned.
  209. * @param string $type
  210. * @param integer $id
  211. * @return RedBean_OODBBean $bean
  212. */
  213. public function load($type, $id) {
  214. $id = intval( $id );
  215. if ($id < 0) throw new RedBean_Exception_Security("Id less than zero not allowed");
  216. $bean = $this->dispense( $type );
  217. if ($this->stash && isset($this->stash[$id])) {
  218. $row = $this->stash[$id];
  219. }
  220. else {
  221. try { $rows = $this->writer->selectRecord($type,array($id)); }catch(RedBean_Exception_SQL $e ){
  222. if ($e->getSQLState()=="42S02" || $e->getSQLState()=="42S22") {
  223. $rows = 0;
  224. if ($this->isFrozen) throw $e; //only throw if frozen;
  225. }
  226. else throw $e;
  227. }
  228. if (!$rows) return $this->dispense($type);
  229. $row = array_pop($rows);
  230. }
  231. foreach($row as $p=>$v) {
  232. //populate the bean with the database row
  233. $bean->$p = $v;
  234. }
  235. $this->signal( "open", $bean );
  236. return $bean;
  237. }
  238. /**
  239. * Removes a bean from the database.
  240. * This function will remove the specified RedBean_OODBBean
  241. * Bean Object from the database.
  242. * @throws RedBean_Exception_Security $exception
  243. * @param RedBean_OODBBean $bean
  244. */
  245. public function trash( RedBean_OODBBean $bean ) {
  246. $idfield = $this->writer->getIDField($bean->getMeta("type"));
  247. $this->signal( "delete", $bean );
  248. $this->check( $bean );
  249. try {
  250. $this->writer->deleteRecord( $bean->getMeta("type"), $bean->$idfield );
  251. }catch(RedBean_Exception_SQL $e ){
  252. if ($e->getSQLState()!="42S02" && $e->getSQLState()!="42S22") throw $e;
  253. }
  254. }
  255. /**
  256. * Loads and returns a series of beans of type $type.
  257. * The beans are loaded all at once.
  258. * The beans are retrieved using their primary key IDs
  259. * specified in the second argument.
  260. * @throws RedBean_Exception_Security $exception
  261. * @param string $type
  262. * @param array $ids
  263. * @return array $beans
  264. */
  265. public function batch( $type, $ids ) {
  266. if (!$ids) return array();
  267. $collection = array();
  268. try {
  269. $rows = $this->writer->selectRecord($type,$ids);
  270. }catch(RedBean_Exception_SQL $e ){
  271. if ($e->getSQLState()!="42S02" && $e->getSQLState()!="42S22") throw $e;
  272. $rows = false;
  273. }
  274. $this->stash = array();
  275. if (!$rows) return array();
  276. foreach($rows as $row) {
  277. $this->stash[$row[$this->writer->getIDField($type)]] = $row;
  278. }
  279. foreach($ids as $id) {
  280. $collection[ $id ] = $this->load( $type, $id );
  281. }
  282. $this->stash = NULL;
  283. return $collection;
  284. }
  285. /**
  286. * This is a convenience method; it converts database rows
  287. * (arrays) into beans.
  288. * @param string $type
  289. * @param array $rows
  290. * @return array $collectionOfBeans
  291. */
  292. public function convertToBeans($type, $rows) {
  293. $collection = array();
  294. $this->stash = array();
  295. foreach($rows as $row) {
  296. $id = $row[$this->writer->getIDField($type)];
  297. $this->stash[$id] = $row;
  298. $collection[ $id ] = $this->load( $type, $id );
  299. }
  300. return $collection;
  301. }
  302. }