1: <?php
2:
3: namespace RedBeanPHP\Repository;
4:
5: use RedBeanPHP\OODBBean as OODBBean;
6: use RedBeanPHP\QueryWriter as QueryWriter;
7: use RedBeanPHP\RedException as RedException;
8: use RedBeanPHP\BeanHelper as BeanHelper;
9: use RedBeanPHP\RedException\SQL as SQLException;
10: use RedBeanPHP\Repository as Repository;
11:
12: /**
13: * Frozen Repository.
14: * OODB manages two repositories, a fluid one that
15: * adjust the database schema on-the-fly to accomodate for
16: * new bean types (tables) and new properties (columns) and
17: * a frozen one for use in a production environment. OODB
18: * allows you to swap the repository instances using the freeze()
19: * method.
20: *
21: * @file RedBeanPHP/Repository/Frozen.php
22: * @author Gabor de Mooij and the RedBeanPHP community
23: * @license BSD/GPLv2
24: *
25: * @copyright
26: * copyright (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community
27: * This source file is subject to the BSD/GPLv2 License that is bundled
28: * with this source code in the file license.txt.
29: */
30: class Frozen extends Repository
31: {
32: /**
33: * Handles exceptions. Suppresses exceptions caused by missing structures.
34: *
35: * @param \Exception $exception exception to handle
36: *
37: * @return void
38: * @throws \Exception
39: */
40: protected function handleException( \Exception $exception )
41: {
42: throw $exception;
43: }
44:
45: /**
46: * Stores a cleaned bean; i.e. only scalar values. This is the core of the store()
47: * method. When all lists and embedded beans (parent objects) have been processed and
48: * removed from the original bean the bean is passed to this method to be stored
49: * in the database.
50: *
51: * @param OODBBean $bean the clean bean
52: *
53: * @return void
54: */
55: protected function storeBean( OODBBean $bean )
56: {
57: if ( $bean->getMeta( 'changed' ) ) {
58:
59: list( $properties, $table ) = $bean->getPropertiesAndType();
60: $id = $properties['id'];
61: unset($properties['id']);
62: $updateValues = array();
63: $k1 = 'property';
64: $k2 = 'value';
65: foreach( $properties as $key => $value ) {
66: $updateValues[] = array( $k1 => $key, $k2 => $value );
67: }
68: $bean->id = $this->writer->updateRecord( $table, $updateValues, $id );
69: $bean->setMeta( 'changed', FALSE );
70: }
71: $bean->setMeta( 'tainted', FALSE );
72: }
73:
74: /**
75: * Part of the store() functionality.
76: * Handles all new additions after the bean has been saved.
77: * Stores addition bean in own-list, extracts the id and
78: * adds a foreign key. Also adds a constraint in case the type is
79: * in the dependent list.
80: *
81: * Note that this method raises a custom exception if the bean
82: * is not an instance of OODBBean. Therefore it does not use
83: * a type hint. This allows the user to take action in case
84: * invalid objects are passed in the list.
85: *
86: * @param OODBBean $bean bean to process
87: * @param array $ownAdditions list of addition beans in own-list
88: *
89: * @return void
90: * @throws RedException
91: */
92: protected function processAdditions( $bean, $ownAdditions )
93: {
94: $beanType = $bean->getMeta( 'type' );
95:
96: $cachedIndex = array();
97: foreach ( $ownAdditions as $addition ) {
98: if ( $addition instanceof OODBBean ) {
99:
100: $myFieldLink = $beanType . '_id';
101: $alias = $bean->getMeta( 'sys.alias.' . $addition->getMeta( 'type' ) );
102: if ( $alias ) $myFieldLink = $alias . '_id';
103:
104: $addition->$myFieldLink = $bean->id;
105: $addition->setMeta( 'cast.' . $myFieldLink, 'id' );
106: $this->store( $addition );
107:
108: } else {
109: throw new RedException( 'Array may only contain OODBBeans' );
110: }
111: }
112: }
113:
114: /**
115: * Dispenses a new bean (a OODBBean Bean Object)
116: * of the specified type. Always
117: * use this function to get an empty bean object. Never
118: * instantiate a OODBBean yourself because it needs
119: * to be configured before you can use it with RedBean. This
120: * function applies the appropriate initialization /
121: * configuration for you.
122: *
123: * @param string $type type of bean you want to dispense
124: * @param int $number number of beans you would like to get
125: * @param boolean $alwaysReturnArray if TRUE always returns the result as an array
126: *
127: * @return OODBBean
128: */
129: public function dispense( $type, $number = 1, $alwaysReturnArray = FALSE )
130: {
131: $OODBBEAN = defined( 'REDBEAN_OODBBEAN_CLASS' ) ? REDBEAN_OODBBEAN_CLASS : '\RedBeanPHP\OODBBean';
132: $beans = array();
133: for ( $i = 0; $i < $number; $i++ ) {
134: /** @var \RedBeanPHP\OODBBean $bean */
135: $bean = new $OODBBEAN;
136: $bean->initializeForDispense( $type, $this->oodb->getBeanHelper() );
137: $this->oodb->signal( 'dispense', $bean );
138: $beans[] = $bean;
139: }
140:
141: return ( count( $beans ) === 1 && !$alwaysReturnArray ) ? array_pop( $beans ) : $beans;
142: }
143:
144: /**
145: * Loads a bean from the object database.
146: * It searches for a OODBBean Bean Object in the
147: * database. It does not matter how this bean has been stored.
148: * RedBean uses the primary key ID $id and the string $type
149: * to find the bean. The $type specifies what kind of bean you
150: * are looking for; this is the same type as used with the
151: * dispense() function. If RedBean finds the bean it will return
152: * the OODB Bean object; if it cannot find the bean
153: * RedBean will return a new bean of type $type and with
154: * primary key ID 0. In the latter case it acts basically the
155: * same as dispense().
156: *
157: * Important note:
158: * If the bean cannot be found in the database a new bean of
159: * the specified type will be generated and returned.
160: *
161: * @param string $type type of bean you want to load
162: * @param integer $id ID of the bean you want to load
163: *
164: * @return OODBBean
165: * @throws SQLException
166: */
167: public function load( $type, $id )
168: {
169: $bean = $this->dispense( $type );
170: if ( isset( $this->stash[$this->nesting][$id] ) ) {
171: $row = $this->stash[$this->nesting][$id];
172: } else {
173: try {
174: $rows = $this->writer->queryRecord( $type, array( 'id' => array( $id ) ) );
175: } catch ( SQLException $exception ) {
176: if ( $this->writer->sqlStateIn( $exception->getSQLState(),
177: array(
178: QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN,
179: QueryWriter::C_SQLSTATE_NO_SUCH_TABLE )
180: )
181: ) {
182: throw $exception; //only throw if frozen
183: }
184: }
185: if ( empty( $rows ) ) {
186: return $bean;
187: }
188: $row = array_pop( $rows );
189: }
190: $bean->importRow( $row );
191: $this->nesting++;
192: $this->oodb->signal( 'open', $bean );
193: $this->nesting--;
194:
195: return $bean->setMeta( 'tainted', FALSE );
196: }
197: }
198: