Coverage for Doctrine_Relation

Back to coverage report

1 <?php
2 /*
3  *  $Id: Relation.php 2702 2007-10-03 21:43:22Z Jonathan.Wage $
4  *
5  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16  *
17  * This software consists of voluntary contributions made by many individuals
18  * and is licensed under the LGPL. For more information, see
19  * <http://www.phpdoctrine.com>.
20  */
21 /**
22  * Doctrine_Relation
23  * This class represents a relation between components
24  *
25  * @package     Doctrine
26  * @subpackage  Relation
27  * @license     http://www.opensource.org/licenses/lgpl-license.php LGPL
28  * @link        www.phpdoctrine.com
29  * @since       1.0
30  * @version     $Revision: 2702 $
31  * @author      Konsta Vesterinen <kvesteri@cc.hut.fi>
32  */
33 abstract class Doctrine_Relation implements ArrayAccess
34 {
35     /**
36      * RELATION CONSTANTS
37      */
38
39     /**
40      * constant for ONE_TO_ONE and MANY_TO_ONE aggregate relationships
41      */
42     const ONE_AGGREGATE         = 0;
43     /**
44      * constant for ONE_TO_ONE and MANY_TO_ONE composite relationships
45      */
46     const ONE_COMPOSITE         = 1;
47     /**
48      * constant for MANY_TO_MANY and ONE_TO_MANY aggregate relationships
49      */
50     const MANY_AGGREGATE        = 2;
51     /**
52      * constant for MANY_TO_MANY and ONE_TO_MANY composite relationships
53      */
54     const MANY_COMPOSITE        = 3;
55
56     const ONE   = 0;
57     const MANY  = 2;
58     
59     protected $definition = array('alias'       => true,
60                                   'foreign'     => true,
61                                   'local'       => true,
62                                   'class'       => true,
63                                   'type'        => true,
64                                   'table'       => true,
65                                   'name'        => false,
66                                   'refTable'    => false,
67                                   'onDelete'    => false,
68                                   'onUpdate'    => false,
69                                   'deferred'    => false,
70                                   'deferrable'  => false,
71                                   'constraint'  => false,
72                                   'equal'       => false,
73                                   );
74     /**
75      * constructor
76      *
77      * @param array $definition         an associative array with the following structure:
78      *          name                    foreign key constraint name
79      *
80      *          local                   the local field(s)
81      *
82      *          foreign                 the foreign reference field(s)
83      *
84      *          table                   the foreign table object
85      *
86      *          refTable                the reference table object (if any)
87      *
88      *          onDelete                referential delete action
89      *  
90      *          onUpdate                referential update action
91      *
92      *          deferred                deferred constraint checking 
93      *
94      *          alias                   relation alias
95      *
96      *          type                    the relation type, either Doctrine_Relation::ONE or Doctrine_Relation::MANY
97      *
98      *          constraint              boolean value, true if the relation has an explicit referential integrity constraint
99      *
100      * The onDelete and onUpdate keys accept the following values:
101      *
102      * CASCADE: Delete or update the row from the parent table and automatically delete or
103      *          update the matching rows in the child table. Both ON DELETE CASCADE and ON UPDATE CASCADE are supported.
104      *          Between two tables, you should not define several ON UPDATE CASCADE clauses that act on the same column
105      *          in the parent table or in the child table.
106      *
107      * SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the
108      *          child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier 
109      *          specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
110      *
111      * NO ACTION: In standard SQL, NO ACTION means no action in the sense that an attempt to delete or update a primary 
112      *           key value is not allowed to proceed if there is a related foreign key value in the referenced table.
113      *
114      * RESTRICT: Rejects the delete or update operation for the parent table. NO ACTION and RESTRICT are the same as
115      *           omitting the ON DELETE or ON UPDATE clause.
116      *
117      * SET DEFAULT
118      */
119     public function __construct(array $definition)
120     {
121         $def = array();
122         foreach ($this->definition as $key => $val) {
123             if ( ! isset($definition[$key]) && $val) {
124                 throw new Doctrine_Exception($key . ' is required!');
125             }
126             if (isset($definition[$key])) {
127                 $def[$key] = $definition[$key];
128             } else {
129                 $def[$key] = null;          
130             }
131         }
132
133         $this->definition = $def;
134     }
135     /**
136      * hasConstraint
137      * whether or not this relation has an explicit constraint
138      *
139      * @return boolean
140      */
141     public function hasConstraint()
142     {
143         return ($this->definition['constraint'] ||
144                 ($this->definition['onUpdate']) ||
145                 ($this->definition['onDelete']));
146     }
147     public function isDeferred()
148     {
149         return $this->definition['deferred'];
150     }
151
152     public function isDeferrable()
153     {
154         return $this->definition['deferrable'];
155     }
156     public function isEqual()
157     {
158         return $this->definition['equal'];
159     }
160
161     public function offsetExists($offset)
162     {
163         return isset($this->definition[$offset]);
164     }
165
166     public function offsetGet($offset)
167     {
168         if (isset($this->definition[$offset])) {
169             return $this->definition[$offset];
170         }
171         
172         return null;
173     }
174
175     public function offsetSet($offset, $value)
176     {
177         if (isset($this->definition[$offset])) {
178             $this->definition[$offset] = $value;
179         }
180     }
181
182     public function offsetUnset($offset)
183     {
184         $this->definition[$offset] = false;
185     }
186     /**
187      * toArray
188      *
189      * @return array
190      */
191     public function toArray() 
192     {
193         return $this->definition;
194     }
195     /**
196      * getAlias
197      * returns the relation alias
198      *
199      * @return string
200      */
201     final public function getAlias()
202     {
203         return $this->definition['alias'];
204     }
205     /**
206      * getType
207      * returns the relation type, either 0 or 1
208      *
209      * @see Doctrine_Relation MANY_* and ONE_* constants
210      * @return integer
211      */
212     final public function getType()
213     {
214         return $this->definition['type'];
215     }
216     /**
217      * getTable
218      * returns the foreign table object
219      *
220      * @return object Doctrine_Table
221      */
222     final public function getTable()
223     {
224         return Doctrine_Manager::getInstance()
225                ->getConnectionForComponent($this->definition['class'])
226                ->getTable($this->definition['class']);
227     }
228     /**
229      * getLocal
230      * returns the name of the local column
231      *
232      * @return string
233      */
234     final public function getLocal()
235     {
236         return $this->definition['local'];
237     }
238     /**
239      * getForeign
240      * returns the name of the foreignkey column where
241      * the localkey column is pointing at
242      *
243      * @return string
244      */
245     final public function getForeign()
246     {
247         return $this->definition['foreign'];
248     }
249     /**
250      * isComposite
251      * returns whether or not this relation is a composite relation
252      *
253      * @return boolean
254      */
255     final public function isComposite()
256     {
257         return ($this->definition['type'] == Doctrine_Relation::ONE_COMPOSITE ||
258                 $this->definition['type'] == Doctrine_Relation::MANY_COMPOSITE);
259     }
260     /**
261      * isOneToOne
262      * returns whether or not this relation is a one-to-one relation
263      *
264      * @return boolean
265      */
266     final public function isOneToOne()
267     {
268         return ($this->definition['type'] == Doctrine_Relation::ONE_AGGREGATE ||
269                 $this->definition['type'] == Doctrine_Relation::ONE_COMPOSITE);
270     }
271     /**
272      * getRelationDql
273      *
274      * @param integer $count
275      * @return string
276      */
277     public function getRelationDql($count)
278     {
279         $component = $this->getTable()->getComponentName();
280
281         $dql  = 'FROM ' . $component
282               . ' WHERE ' . $component . '.' . $this->definition['foreign']
283               . ' IN (' . substr(str_repeat('?, ', $count), 0, -2) . ')';
284
285         return $dql;
286     }
287     /**
288      * fetchRelatedFor
289      *
290      * fetches a component related to given record
291      *
292      * @param Doctrine_Record $record
293      * @return Doctrine_Record|Doctrine_Collection
294      */
295     abstract public function fetchRelatedFor(Doctrine_Record $record);
296     /**
297      * __toString
298      *
299      * @return string
300      */
301     public function __toString()
302     {
303         $r[] = "<pre>";
304         foreach ($this->definition as $k => $v) {
305             if (is_object($v)) {
306                 $v = 'Object(' . get_class($v) . ')';
307             }
308             $r[] = $k . ' : ' . $v;
309         }
310         $r[] = "</pre>";
311         return implode("\n", $r);
312     }
313 }