ClassMetaData   A
last analyzed

Complexity

Total Complexity 31

Size/Duplication

Total Lines 265
Duplicated Lines 0 %

Coupling/Cohesion

Components 3
Dependencies 6

Test Coverage

Coverage 97.83%

Importance

Changes 0
Metric Value
wmc 31
lcom 3
cbo 6
dl 0
loc 265
ccs 90
cts 92
cp 0.9783
rs 9.8
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A addRouteMetaData() 0 5 1
A getRoutesMetaData() 0 4 1
A getRouteMetaData() 0 8 2
C getOriginRoute() 0 25 7
A addRepresentations() 0 6 2
A addRepresentation() 0 13 4
A getRepresentations() 0 4 1
A getClassName() 0 4 1
A getElementName() 0 10 2
A getEntityAlias() 0 4 1
A getCollectionName() 0 6 1
A serialize() 0 13 1
A unserialize() 0 17 2
A expired() 0 12 4
1
<?php
2
/**
3
 * This file is part of the Drest package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author Lee Davis
9
 * @copyright Copyright (c) Lee Davis <@leedavis81>
10
 * @link https://github.com/leedavis81/drest/blob/master/LICENSE
11
 * @license http://opensource.org/licenses/MIT The MIT X License (MIT)
12
 */
13
namespace Drest\Mapping;
14
15
use Doctrine\Common\Inflector\Inflector;
16
use Doctrine\ORM\EntityManager;
17
use Drest\Service\Action\AbstractAction;
18
use DrestCommon\Representation\AbstractRepresentation;
19
use DrestCommon\Representation\RepresentationException;
20
21
/**
22
 *
23
 * A class metadata instance that holds all the information for a Drest entity
24
 * @author Lee
25
 *
26
 */
27
class ClassMetaData implements \Serializable
28
{
29
30
    /**
31
     * An array of RouteMetaData objects defined on this entity
32
     * @var array $routes
33
     */
34
    protected $routes = [];
35
36
    /**
37
     * An array of \DrestCommon\Representation\AbstractRepresentation object defined on this entity
38
     * @var array $representations
39
     */
40
    protected $representations = [];
41
42
    /**
43
     * Name of the class that we collected metadata for (eg Entities\User)
44
     * @var string $className
45
     */
46
    protected $className;
47
48
    /**
49
     * A reflection of the class
50
     * @var \ReflectionClass $reflection
51
     */
52
    protected $reflection;
53
54
    /**
55
     * File path used to load this metadata
56
     * @var string $fileResources
57
     */
58
    public $filePath;
59
60
    /**
61
     * time this instance was created - current Unix timestamp
62
     * @var integer $createdAt
63
     */
64
    public $createdAt;
65
66
    /**
67
     * The origin route name - null if one isn't found
68
     * @vat string $originRouteName
69
     */
70
    public $originRouteName;
71
72
73
    /**
74
     * Construct an instance of this classes metadata
75
     * @param \ReflectionClass $classRefl
76
     */
77 62
    public function __construct(\ReflectionClass $classRefl)
78
    {
79 62
        $this->reflection = $classRefl;
80 62
        $this->className = $classRefl->name;
81
82 62
        $this->filePath = $classRefl->getFileName();
83 62
        $this->createdAt = time();
84 62
    }
85
86
    /**
87
     * Add a route metadata object
88
     * @param RouteMetaData $route
89
     */
90 43
    public function addRouteMetaData(RouteMetaData $route)
91
    {
92 43
        $route->setClassMetaData($this);
93 43
        $this->routes[$route->getName()] = $route;
94 43
    }
95
96
    /**
97
     * Get an array of all route metadata information.
98
     * @return RouteMetaData[]|false  $routes
99
     */
100 34
    public function getRoutesMetaData()
101
    {
102 34
        return $this->routes;
103
    }
104
105
    /**
106
     * Get metadata for a specific route. Returns false if entry cannot be found
107
     * @param $name
108
     * @return RouteMetaData|false  $routes
109
     */
110 45
    public function getRouteMetaData($name)
111
    {
112 45
        if (!isset($this->routes[$name])) {
113 45
            return false;
114
        }
115
116 40
        return $this->routes[$name];
117
    }
118
119
    /**
120
     * get the origin route (if one is available), otherwise attempts to determine it from a GET {path}/{primary_key} route
121
     * @param  EntityManager      $em - Optionally pass the entity manager to assist in determining a GET origin location
122
     * @return null|RouteMetaData $route
123
     */
124 6
    public function getOriginRoute(EntityManager $em = null)
125
    {
126 6
        if (!empty($this->originRouteName)) {
127 1
            if (($route = $this->getRouteMetaData($this->originRouteName)) !== false) {
128 1
                return $route;
129
            }
130 5
        } elseif (!is_null($em)) {
131 5
            $ormClassMetadata = $em->getClassMetadata($this->getClassName());
132
133 5
            foreach ($this->getRoutesMetaData() as $route) {
134
                /* @var RouteMetaData $route */
135 5
                if (in_array('GET', $route->getVerbs()) && preg_match(
136 4
                        '/^(.*)?\/:' . implode('/:', $ormClassMetadata->getIdentifierFieldNames()) . '$/',
137 4
                        $route->getRoutePattern()
138 4
                    )
139 5
                ) {
140 4
                    $this->originRouteName = $route->getName();
141
142 4
                    return $route;
143
                }
144 1
            }
145 1
        }
146
147 1
        return null;
148
    }
149
150
    /**
151
     * Add an array of representations
152
     * @param array $representations
153
     */
154 40
    public function addRepresentations(array $representations)
155
    {
156 40
        foreach ($representations as $representation) {
157 39
            $this->addRepresentation($representation);
158 40
        }
159 40
    }
160
161
    /**
162
     * Set a representation instance to be used on this resource
163
     * @param  object|string           $representation - can be either an instance of DrestCommon\Representation\AbstractRepresentation or a string (shorthand allowed - Json / Xml) referencing the class.
164
     * @throws RepresentationException
165
     */
166 44
    public function addRepresentation($representation)
167
    {
168 44
        if (is_object($representation)) {
169 2
            if (!$representation instanceof AbstractRepresentation) {
170 1
                throw RepresentationException::unknownRepresentationClass(get_class($representation));
171
            }
172 1
            $this->representations[] = $representation;
173 43
        } elseif (is_string($representation)) {
174 40
            $this->representations[] = $representation;
175 40
        } else {
176 2
            throw RepresentationException::representationMustBeObjectOrString();
177
        }
178 41
    }
179
180
    /**
181
     * Get the representations available on this resource
182
     * @return array representations can be strings or an already instantiated object
183
     */
184 29
    public function getRepresentations()
185
    {
186 29
        return $this->representations;
187
    }
188
189
    /**
190
     * Get the metadata class name (immutable)
191
     * @return string $className
192
     */
193 37
    public function getClassName()
194
    {
195 37
        return $this->className;
196
    }
197
198
    /**
199
     * Get the text name that represents a single element. eg: user
200
     * @return string $element_name
201
     */
202 15
    public function getElementName()
203
    {
204
        // attempt to pull an entity name from the class
205 15
        $classNameParts = explode('\\', $this->className);
206 15
        if (is_array($classNameParts)) {
207 15
            return strtolower(Inflector::singularize(array_pop($classNameParts)));
208
        }
209
210
        return $this->className;
211
    }
212
213
    /**
214
     * Get an alias for this entity - used for DQL / QueryBuilder
215
     * @param  string $fieldName - The field the relation is on. Typical to root when using top level.
216
     * @return string alias unique string representing this entity
217
     */
218 24
    public function getEntityAlias($fieldName = 'rt')
219
    {
220 24
        return AbstractAction::getAlias($this->getClassName(), $fieldName);
221
    }
222
223
    /**
224
     * Get a plural term for the element name
225
     * @return string $collection_name
226
     */
227 13
    public function getCollectionName()
228
    {
229 13
        $elementName = $this->getElementName();
230
231 13
        return Inflector::pluralize($elementName);
232
    }
233
234
    /**
235
     * Serialise this object
236
     * @return string
237
     */
238 1
    public function serialize()
239
    {
240 1
        return serialize(
241
            [
242 1
                $this->routes,
243 1
                $this->representations,
244 1
                $this->className,
245 1
                $this->filePath,
246 1
                $this->createdAt,
247 1
                $this->originRouteName
248 1
            ]
249 1
        );
250
    }
251
252
    /**
253
     * Un-serialise this object and reestablish it's state
254
     * @param string $string
255
     */
256 1
    public function unserialize($string)
257
    {
258
        list(
259 1
            $this->routes,
260 1
            $this->representations,
261 1
            $this->className,
262 1
            $this->filePath,
263 1
            $this->createdAt,
264 1
            $this->originRouteName
265 1
            ) = unserialize($string);
266
267 1
        foreach ($this->routes as $route) {
268
            /* @var $route RouteMetaData */
269 1
            $route->setClassMetaData($this);
270 1
        }
271 1
        $this->reflection = new \ReflectionClass($this->className);
272 1
    }
273
274
    /**
275
     * Check to see if this classes metadata has expired (file has been modified or deleted)
276
     * @param timestamp
277
     * @return bool
278
     */
279 1
    public function expired($timestamp = null)
280
    {
281 1
        if ($timestamp === null) {
282 1
            $timestamp = $this->createdAt;
283 1
        }
284
285 1
        if (!file_exists($this->filePath) || $timestamp < filemtime($this->filePath)) {
286
            return true;
287
        }
288
289 1
        return false;
290
    }
291
}
292