Mercurial > hg > isophonics-drupal-site
comparison vendor/doctrine/common/lib/Doctrine/Common/Persistence/PersistentObject.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 /* | |
3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
14 * | |
15 * This software consists of voluntary contributions made by many individuals | |
16 * and is licensed under the MIT license. For more information, see | |
17 * <http://www.doctrine-project.org>. | |
18 */ | |
19 | |
20 namespace Doctrine\Common\Persistence; | |
21 | |
22 use Doctrine\Common\Collections\ArrayCollection; | |
23 use Doctrine\Common\Collections\Collection; | |
24 use Doctrine\Common\Persistence\Mapping\ClassMetadata; | |
25 | |
26 /** | |
27 * PersistentObject base class that implements getter/setter methods for all mapped fields and associations | |
28 * by overriding __call. | |
29 * | |
30 * This class is a forward compatible implementation of the PersistentObject trait. | |
31 * | |
32 * Limitations: | |
33 * | |
34 * 1. All persistent objects have to be associated with a single ObjectManager, multiple | |
35 * ObjectManagers are not supported. You can set the ObjectManager with `PersistentObject#setObjectManager()`. | |
36 * 2. Setters and getters only work if a ClassMetadata instance was injected into the PersistentObject. | |
37 * This is either done on `postLoad` of an object or by accessing the global object manager. | |
38 * 3. There are no hooks for setters/getters. Just implement the method yourself instead of relying on __call(). | |
39 * 4. Slower than handcoded implementations: An average of 7 method calls per access to a field and 11 for an association. | |
40 * 5. Only the inverse side associations get autoset on the owning side as well. Setting objects on the owning side | |
41 * will not set the inverse side associations. | |
42 * | |
43 * @example | |
44 * | |
45 * PersistentObject::setObjectManager($em); | |
46 * | |
47 * class Foo extends PersistentObject | |
48 * { | |
49 * private $id; | |
50 * } | |
51 * | |
52 * $foo = new Foo(); | |
53 * $foo->getId(); // method exists through __call | |
54 * | |
55 * @author Benjamin Eberlei <kontakt@beberlei.de> | |
56 */ | |
57 abstract class PersistentObject implements ObjectManagerAware | |
58 { | |
59 /** | |
60 * @var ObjectManager|null | |
61 */ | |
62 private static $objectManager = null; | |
63 | |
64 /** | |
65 * @var ClassMetadata|null | |
66 */ | |
67 private $cm = null; | |
68 | |
69 /** | |
70 * Sets the object manager responsible for all persistent object base classes. | |
71 * | |
72 * @param ObjectManager|null $objectManager | |
73 * | |
74 * @return void | |
75 */ | |
76 static public function setObjectManager(ObjectManager $objectManager = null) | |
77 { | |
78 self::$objectManager = $objectManager; | |
79 } | |
80 | |
81 /** | |
82 * @return ObjectManager|null | |
83 */ | |
84 static public function getObjectManager() | |
85 { | |
86 return self::$objectManager; | |
87 } | |
88 | |
89 /** | |
90 * Injects the Doctrine Object Manager. | |
91 * | |
92 * @param ObjectManager $objectManager | |
93 * @param ClassMetadata $classMetadata | |
94 * | |
95 * @return void | |
96 * | |
97 * @throws \RuntimeException | |
98 */ | |
99 public function injectObjectManager(ObjectManager $objectManager, ClassMetadata $classMetadata) | |
100 { | |
101 if ($objectManager !== self::$objectManager) { | |
102 throw new \RuntimeException("Trying to use PersistentObject with different ObjectManager instances. " . | |
103 "Was PersistentObject::setObjectManager() called?"); | |
104 } | |
105 | |
106 $this->cm = $classMetadata; | |
107 } | |
108 | |
109 /** | |
110 * Sets a persistent fields value. | |
111 * | |
112 * @param string $field | |
113 * @param array $args | |
114 * | |
115 * @return void | |
116 * | |
117 * @throws \BadMethodCallException When no persistent field exists by that name. | |
118 * @throws \InvalidArgumentException When the wrong target object type is passed to an association. | |
119 */ | |
120 private function set($field, $args) | |
121 { | |
122 $this->initializeDoctrine(); | |
123 | |
124 if ($this->cm->hasField($field) && !$this->cm->isIdentifier($field)) { | |
125 $this->$field = $args[0]; | |
126 } else if ($this->cm->hasAssociation($field) && $this->cm->isSingleValuedAssociation($field)) { | |
127 $targetClass = $this->cm->getAssociationTargetClass($field); | |
128 if (!($args[0] instanceof $targetClass) && $args[0] !== null) { | |
129 throw new \InvalidArgumentException("Expected persistent object of type '".$targetClass."'"); | |
130 } | |
131 $this->$field = $args[0]; | |
132 $this->completeOwningSide($field, $targetClass, $args[0]); | |
133 } else { | |
134 throw new \BadMethodCallException("no field with name '".$field."' exists on '".$this->cm->getName()."'"); | |
135 } | |
136 } | |
137 | |
138 /** | |
139 * Gets a persistent field value. | |
140 * | |
141 * @param string $field | |
142 * | |
143 * @return mixed | |
144 * | |
145 * @throws \BadMethodCallException When no persistent field exists by that name. | |
146 */ | |
147 private function get($field) | |
148 { | |
149 $this->initializeDoctrine(); | |
150 | |
151 if ( $this->cm->hasField($field) || $this->cm->hasAssociation($field) ) { | |
152 return $this->$field; | |
153 } else { | |
154 throw new \BadMethodCallException("no field with name '".$field."' exists on '".$this->cm->getName()."'"); | |
155 } | |
156 } | |
157 | |
158 /** | |
159 * If this is an inverse side association, completes the owning side. | |
160 * | |
161 * @param string $field | |
162 * @param ClassMetadata $targetClass | |
163 * @param object $targetObject | |
164 * | |
165 * @return void | |
166 */ | |
167 private function completeOwningSide($field, $targetClass, $targetObject) | |
168 { | |
169 // add this object on the owning side as well, for obvious infinite recursion | |
170 // reasons this is only done when called on the inverse side. | |
171 if ($this->cm->isAssociationInverseSide($field)) { | |
172 $mappedByField = $this->cm->getAssociationMappedByTargetField($field); | |
173 $targetMetadata = self::$objectManager->getClassMetadata($targetClass); | |
174 | |
175 $setter = ($targetMetadata->isCollectionValuedAssociation($mappedByField) ? "add" : "set").$mappedByField; | |
176 $targetObject->$setter($this); | |
177 } | |
178 } | |
179 | |
180 /** | |
181 * Adds an object to a collection. | |
182 * | |
183 * @param string $field | |
184 * @param array $args | |
185 * | |
186 * @return void | |
187 * | |
188 * @throws \BadMethodCallException | |
189 * @throws \InvalidArgumentException | |
190 */ | |
191 private function add($field, $args) | |
192 { | |
193 $this->initializeDoctrine(); | |
194 | |
195 if ($this->cm->hasAssociation($field) && $this->cm->isCollectionValuedAssociation($field)) { | |
196 $targetClass = $this->cm->getAssociationTargetClass($field); | |
197 if (!($args[0] instanceof $targetClass)) { | |
198 throw new \InvalidArgumentException("Expected persistent object of type '".$targetClass."'"); | |
199 } | |
200 if (!($this->$field instanceof Collection)) { | |
201 $this->$field = new ArrayCollection($this->$field ?: []); | |
202 } | |
203 $this->$field->add($args[0]); | |
204 $this->completeOwningSide($field, $targetClass, $args[0]); | |
205 } else { | |
206 throw new \BadMethodCallException("There is no method add".$field."() on ".$this->cm->getName()); | |
207 } | |
208 } | |
209 | |
210 /** | |
211 * Initializes Doctrine Metadata for this class. | |
212 * | |
213 * @return void | |
214 * | |
215 * @throws \RuntimeException | |
216 */ | |
217 private function initializeDoctrine() | |
218 { | |
219 if ($this->cm !== null) { | |
220 return; | |
221 } | |
222 | |
223 if (!self::$objectManager) { | |
224 throw new \RuntimeException("No runtime object manager set. Call PersistentObject#setObjectManager()."); | |
225 } | |
226 | |
227 $this->cm = self::$objectManager->getClassMetadata(get_class($this)); | |
228 } | |
229 | |
230 /** | |
231 * Magic methods. | |
232 * | |
233 * @param string $method | |
234 * @param array $args | |
235 * | |
236 * @return mixed | |
237 * | |
238 * @throws \BadMethodCallException | |
239 */ | |
240 public function __call($method, $args) | |
241 { | |
242 $command = substr($method, 0, 3); | |
243 $field = lcfirst(substr($method, 3)); | |
244 if ($command == "set") { | |
245 $this->set($field, $args); | |
246 } else if ($command == "get") { | |
247 return $this->get($field); | |
248 } else if ($command == "add") { | |
249 $this->add($field, $args); | |
250 } else { | |
251 throw new \BadMethodCallException("There is no method ".$method." on ".$this->cm->getName()); | |
252 } | |
253 } | |
254 } |