~ubuntu-branches/ubuntu/utopic/php-doctrine-common/utopic

« back to all changes in this revision

Viewing changes to lib/Doctrine/Common/Proxy/AbstractProxyFactory.php

  • Committer: Package Import Robot
  • Author(s): David Prévot
  • Date: 2014-06-15 11:26:00 UTC
  • mfrom: (2.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20140615112600-sg4mgpwq9sfg4mre
Tags: 2.4.2-2
* Upload to unstable
* No tests if DEB_BUILD_OPTIONS contains nocheck

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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\Proxy;
 
21
 
 
22
use Doctrine\Common\Persistence\Mapping\ClassMetadataFactory;
 
23
use Doctrine\Common\Proxy\Exception\InvalidArgumentException;
 
24
use Doctrine\Common\Proxy\Exception\OutOfBoundsException;
 
25
use Doctrine\Common\Util\ClassUtils;
 
26
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
 
27
 
 
28
/**
 
29
 * Abstract factory for proxy objects.
 
30
 *
 
31
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 
32
 */
 
33
abstract class AbstractProxyFactory
 
34
{
 
35
    /**
 
36
     * Never autogenerate a proxy and rely that it was generated by some
 
37
     * process before deployment.
 
38
     *
 
39
     * @var integer
 
40
     */
 
41
    const AUTOGENERATE_NEVER = 0;
 
42
 
 
43
    /**
 
44
     * Always generates a new proxy in every request.
 
45
     *
 
46
     * This is only sane during development.
 
47
     *
 
48
     * @var integer
 
49
     */
 
50
    const AUTOGENERATE_ALWAYS = 1;
 
51
 
 
52
    /**
 
53
     * Autogenerate the proxy class when the proxy file does not exist.
 
54
     *
 
55
     * This strategy causes a file exists call whenever any proxy is used the
 
56
     * first time in a request.
 
57
     *
 
58
     * @var integer
 
59
     */
 
60
    const AUTOGENERATE_FILE_NOT_EXISTS = 2;
 
61
 
 
62
    /**
 
63
     * Generate the proxy classes using eval().
 
64
     *
 
65
     * This strategy is only sane for development, and even then it gives me
 
66
     * the creeps a little.
 
67
     *
 
68
     * @var integer
 
69
     */
 
70
    const AUTOGENERATE_EVAL = 3;
 
71
 
 
72
    /**
 
73
     * @var \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory
 
74
     */
 
75
    private $metadataFactory;
 
76
 
 
77
    /**
 
78
     * @var \Doctrine\Common\Proxy\ProxyGenerator the proxy generator responsible for creating the proxy classes/files.
 
79
     */
 
80
    private $proxyGenerator;
 
81
 
 
82
    /**
 
83
     * @var bool Whether to automatically (re)generate proxy classes.
 
84
     */
 
85
    private $autoGenerate;
 
86
 
 
87
    /**
 
88
     * @var \Doctrine\Common\Proxy\ProxyDefinition[]
 
89
     */
 
90
    private $definitions = array();
 
91
 
 
92
    /**
 
93
     * @param \Doctrine\Common\Proxy\ProxyGenerator                     $proxyGenerator
 
94
     * @param \Doctrine\Common\Persistence\Mapping\ClassMetadataFactory $metadataFactory
 
95
     * @param bool|int                                                  $autoGenerate
 
96
     */
 
97
    public function __construct(ProxyGenerator $proxyGenerator, ClassMetadataFactory $metadataFactory, $autoGenerate)
 
98
    {
 
99
        $this->proxyGenerator  = $proxyGenerator;
 
100
        $this->metadataFactory = $metadataFactory;
 
101
        $this->autoGenerate    = (int)$autoGenerate;
 
102
    }
 
103
 
 
104
    /**
 
105
     * Gets a reference proxy instance for the entity of the given type and identified by
 
106
     * the given identifier.
 
107
     *
 
108
     * @param  string $className
 
109
     * @param  array  $identifier
 
110
     *
 
111
     * @return \Doctrine\Common\Proxy\Proxy
 
112
     *
 
113
     * @throws \Doctrine\Common\Proxy\Exception\OutOfBoundsException
 
114
     */
 
115
    public function getProxy($className, array $identifier)
 
116
    {
 
117
        $definition = isset($this->definitions[$className])
 
118
            ? $this->definitions[$className]
 
119
            : $this->getProxyDefinition($className);
 
120
        $fqcn       = $definition->proxyClassName;
 
121
        $proxy      = new $fqcn($definition->initializer, $definition->cloner);
 
122
 
 
123
        foreach ($definition->identifierFields as $idField) {
 
124
            if (! isset($identifier[$idField])) {
 
125
                throw OutOfBoundsException::missingPrimaryKeyValue($className, $idField);
 
126
            }
 
127
 
 
128
            $definition->reflectionFields[$idField]->setValue($proxy, $identifier[$idField]);
 
129
        }
 
130
 
 
131
        return $proxy;
 
132
    }
 
133
 
 
134
    /**
 
135
     * Generates proxy classes for all given classes.
 
136
     *
 
137
     * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata[] $classes The classes (ClassMetadata instances)
 
138
     *                                                                      for which to generate proxies.
 
139
     * @param string $proxyDir The target directory of the proxy classes. If not specified, the
 
140
     *                         directory configured on the Configuration of the EntityManager used
 
141
     *                         by this factory is used.
 
142
     * @return int Number of generated proxies.
 
143
     */
 
144
    public function generateProxyClasses(array $classes, $proxyDir = null)
 
145
    {
 
146
        $generated = 0;
 
147
 
 
148
        foreach ($classes as $class) {
 
149
            if ($this->skipClass($class)) {
 
150
                continue;
 
151
            }
 
152
 
 
153
            $proxyFileName = $this->proxyGenerator->getProxyFileName($class->getName(), $proxyDir);
 
154
 
 
155
            $this->proxyGenerator->generateProxyClass($class, $proxyFileName);
 
156
 
 
157
            $generated += 1;
 
158
        }
 
159
 
 
160
        return $generated;
 
161
    }
 
162
 
 
163
    /**
 
164
     * Reset initialization/cloning logic for an un-initialized proxy
 
165
     *
 
166
     * @param \Doctrine\Common\Proxy\Proxy $proxy
 
167
     *
 
168
     * @return \Doctrine\Common\Proxy\Proxy
 
169
     *
 
170
     * @throws \Doctrine\Common\Proxy\Exception\InvalidArgumentException
 
171
     */
 
172
    public function resetUninitializedProxy(Proxy $proxy)
 
173
    {
 
174
        if ($proxy->__isInitialized()) {
 
175
            throw InvalidArgumentException::unitializedProxyExpected($proxy);
 
176
        }
 
177
 
 
178
        $className  = ClassUtils::getClass($proxy);
 
179
        $definition = isset($this->definitions[$className])
 
180
            ? $this->definitions[$className]
 
181
            : $this->getProxyDefinition($className);
 
182
 
 
183
        $proxy->__setInitializer($definition->initializer);
 
184
        $proxy->__setCloner($definition->cloner);
 
185
 
 
186
        return $proxy;
 
187
    }
 
188
 
 
189
    /**
 
190
     * Get a proxy definition for the given class name.
 
191
     *
 
192
     * @return ProxyDefinition
 
193
     */
 
194
    private function getProxyDefinition($className)
 
195
    {
 
196
        $classMetadata = $this->metadataFactory->getMetadataFor($className);
 
197
        $className     = $classMetadata->getName(); // aliases and case sensitivity
 
198
 
 
199
        $this->definitions[$className] = $this->createProxyDefinition($className);
 
200
        $proxyClassName                = $this->definitions[$className]->proxyClassName;
 
201
 
 
202
        if ( ! class_exists($proxyClassName, false)) {
 
203
            $fileName  = $this->proxyGenerator->getProxyFileName($className);
 
204
 
 
205
            switch ($this->autoGenerate) {
 
206
                case self::AUTOGENERATE_NEVER:
 
207
                    require $fileName;
 
208
                    break;
 
209
 
 
210
                case self::AUTOGENERATE_FILE_NOT_EXISTS:
 
211
                    if ( ! file_exists($fileName)) {
 
212
                        $this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
 
213
                    }
 
214
                    require $fileName;
 
215
                    break;
 
216
 
 
217
                case self::AUTOGENERATE_ALWAYS:
 
218
                    $this->proxyGenerator->generateProxyClass($classMetadata, $fileName);
 
219
                    require $fileName;
 
220
                    break;
 
221
 
 
222
                case self::AUTOGENERATE_EVAL:
 
223
                    $this->proxyGenerator->generateProxyClass($classMetadata, false);
 
224
                    break;
 
225
            }
 
226
        }
 
227
 
 
228
        return $this->definitions[$className];
 
229
    }
 
230
 
 
231
    /**
 
232
     * Determine if this class should be skipped during proxy generation.
 
233
     *
 
234
     * @param \Doctrine\Common\Persistence\Mapping\ClassMetadata $metadata
 
235
     * @return bool
 
236
     */
 
237
    abstract protected function skipClass(ClassMetadata $metadata);
 
238
 
 
239
    /**
 
240
     * @return ProxyDefinition
 
241
     */
 
242
    abstract protected function createProxyDefinition($className);
 
243
}
 
244