This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /* |
||
3 | * This file is part of the PommProject/ModelManager package. |
||
4 | * |
||
5 | * (c) 2014 - 2015 Grégoire HUBERT <[email protected]> |
||
6 | * |
||
7 | * For the full copyright and license information, please view the LICENSE |
||
8 | * file that was distributed with this source code. |
||
9 | */ |
||
10 | namespace PommProject\ModelManager\Model; |
||
11 | |||
12 | use PommProject\Foundation\Client\ClientInterface; |
||
13 | use PommProject\Foundation\Session\Session; |
||
14 | use PommProject\ModelManager\Converter\PgEntity; |
||
15 | use PommProject\ModelManager\Exception\ModelException; |
||
16 | use PommProject\ModelManager\Model\FlexibleEntity\FlexibleEntityInterface; |
||
17 | |||
18 | /** |
||
19 | * Model |
||
20 | * |
||
21 | * Base class for custom Model classes. |
||
22 | * |
||
23 | * @abstract |
||
24 | * @package Pomm |
||
25 | * @copyright 2014 - 2019 Grégoire HUBERT |
||
26 | * @author Grégoire HUBERT |
||
27 | * @license X11 {@link http://opensource.org/licenses/mit-license.php} |
||
28 | * @see ClientInterface |
||
29 | */ |
||
30 | abstract class Model implements ClientInterface |
||
31 | { |
||
32 | protected $session; |
||
33 | protected $flexible_entity_class; |
||
34 | |||
35 | |||
36 | /** |
||
37 | * @var RowStructure |
||
38 | */ |
||
39 | protected $structure; |
||
40 | |||
41 | /** |
||
42 | * getSession |
||
43 | * |
||
44 | * Return the current session. If session is not set, a ModelException is |
||
45 | * thrown. |
||
46 | * |
||
47 | * @access public |
||
48 | * @return Session |
||
49 | * @throws ModelException |
||
50 | */ |
||
51 | public function getSession() |
||
52 | { |
||
53 | if ($this->session === null) { |
||
54 | throw new ModelException(sprintf("Model class '%s' is not registered against the session.", get_class($this))); |
||
55 | } |
||
56 | |||
57 | return $this->session; |
||
58 | } |
||
59 | |||
60 | /** |
||
61 | * getClientType |
||
62 | * |
||
63 | * @see ClientInterface |
||
64 | */ |
||
65 | public function getClientType() |
||
66 | { |
||
67 | return 'model'; |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * getClientIdentifier |
||
72 | * |
||
73 | * @see ClientInterface |
||
74 | */ |
||
75 | public function getClientIdentifier() |
||
76 | { |
||
77 | return trim(get_class($this), "\\"); |
||
78 | } |
||
79 | |||
80 | /** |
||
81 | * initialize |
||
82 | * |
||
83 | * @see ClientInterface |
||
84 | */ |
||
85 | public function initialize(Session $session) |
||
86 | { |
||
87 | $this->session = $session; |
||
88 | |||
89 | if ($this->structure === null) { |
||
90 | throw new ModelException(sprintf("Structure not set while initializing Model class '%s'.", get_class($this))); |
||
91 | } |
||
92 | |||
93 | if ($this->flexible_entity_class == null) { |
||
94 | throw new ModelException(sprintf("Flexible entity not set while initializing Model class '%s'.", get_class($this))); |
||
95 | } elseif (!(new \ReflectionClass($this->flexible_entity_class)) |
||
96 | ->implementsInterface('\PommProject\ModelManager\Model\FlexibleEntity\FlexibleEntityInterface') |
||
97 | ) { |
||
98 | throw new ModelException(sprintf("Flexible entity must implement FlexibleEntityInterface.")); |
||
99 | } |
||
100 | |||
101 | $session->getPoolerForType('converter') |
||
0 ignored issues
–
show
|
|||
102 | ->getConverterHolder() |
||
103 | ->registerConverter( |
||
104 | $this->flexible_entity_class, |
||
105 | new PgEntity( |
||
106 | $this->flexible_entity_class, |
||
107 | $this->getStructure() |
||
108 | ), |
||
109 | [ |
||
110 | $this->getStructure()->getRelation(), |
||
111 | $this->flexible_entity_class, |
||
112 | ] |
||
113 | ); |
||
114 | } |
||
115 | |||
116 | /** |
||
117 | * shutdown |
||
118 | * |
||
119 | * @see ClientInterface |
||
120 | */ |
||
121 | public function shutdown() |
||
122 | { |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * createEntity |
||
127 | * |
||
128 | * Create a new entity. |
||
129 | * |
||
130 | * @access public |
||
131 | * @param array $values |
||
132 | * @return FlexibleEntityInterface |
||
133 | */ |
||
134 | public function createEntity(array $values = []) |
||
135 | { |
||
136 | $class_name = $this->getFlexibleEntityClass(); |
||
137 | |||
138 | return (new $class_name) |
||
139 | ->hydrate($values) |
||
140 | ; |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * query |
||
145 | * |
||
146 | * Execute the given query and return a Collection iterator on results. If |
||
147 | * no projections are passed, it will use the default projection using |
||
148 | * createProjection() method. |
||
149 | * |
||
150 | * @access protected |
||
151 | * @param string $sql |
||
152 | * @param array $values |
||
153 | * @param Projection $projection |
||
154 | * @return CollectionIterator |
||
155 | */ |
||
156 | protected function query($sql, array $values = [], Projection $projection = null) |
||
157 | { |
||
158 | if ($projection === null) { |
||
159 | $projection = $this->createProjection(); |
||
160 | } |
||
161 | |||
162 | $result = $this |
||
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
PommProject\Foundation\Client\ClientInterface as the method execute() does only exist in the following implementations of said interface: PommProject\Foundation\PreparedQuery\PreparedQuery .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
163 | ->getSession() |
||
164 | ->getClientUsingPooler('prepared_query', $sql) |
||
165 | ->execute($values) |
||
166 | ; |
||
167 | |||
168 | $collection = new CollectionIterator( |
||
169 | $result, |
||
170 | $this->getSession(), |
||
171 | $projection |
||
172 | ); |
||
173 | |||
174 | return $collection; |
||
175 | } |
||
176 | |||
177 | /** |
||
178 | * createDefaultProjection |
||
179 | * |
||
180 | * This method creates a projection based on the structure definition of |
||
181 | * the underlying relation. It may be used to shunt parent createProjection |
||
182 | * call in inherited classes. |
||
183 | * This method can be used where a projection that sticks to table |
||
184 | * definition is needed like recursive CTEs. For normal projections, use |
||
185 | * createProjection instead. |
||
186 | * |
||
187 | * @access public |
||
188 | * @return Projection |
||
189 | */ |
||
190 | final public function createDefaultProjection() |
||
191 | { |
||
192 | return new Projection($this->flexible_entity_class, $this->structure->getDefinition()); |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * createProjection |
||
197 | * |
||
198 | * This is a helper to create a new projection according to the current |
||
199 | * structure.Overriding this method will change projection for all models. |
||
200 | * |
||
201 | * @access public |
||
202 | * @return Projection |
||
203 | */ |
||
204 | public function createProjection() |
||
205 | { |
||
206 | return $this->createDefaultProjection(); |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * checkFlexibleEntity |
||
211 | * |
||
212 | * Check if the given entity is an instance of this model's flexible class. |
||
213 | * If not an exception is thrown. |
||
214 | * |
||
215 | * @access protected |
||
216 | * @param FlexibleEntityInterface $entity |
||
217 | * @throws \InvalidArgumentException |
||
218 | * @return Model $this |
||
219 | */ |
||
220 | protected function checkFlexibleEntity(FlexibleEntityInterface $entity) |
||
221 | { |
||
222 | if (!($entity instanceof $this->flexible_entity_class)) { |
||
223 | throw new \InvalidArgumentException(sprintf( |
||
224 | "Entity class '%s' is not a '%s'.", |
||
225 | get_class($entity), |
||
226 | $this->flexible_entity_class |
||
227 | )); |
||
228 | } |
||
229 | |||
230 | return $this; |
||
231 | } |
||
232 | |||
233 | /** |
||
234 | * getStructure |
||
235 | * |
||
236 | * Return the structure. |
||
237 | * |
||
238 | * @access public |
||
239 | * @return RowStructure |
||
240 | */ |
||
241 | public function getStructure() |
||
242 | { |
||
243 | return $this->structure; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * getModel |
||
248 | * |
||
249 | * Proxy to Session::getModel(); |
||
250 | * |
||
251 | * @param string model identifier |
||
252 | * @return Model |
||
253 | */ |
||
254 | protected function getModel($identifier) |
||
255 | { |
||
256 | return $this |
||
257 | ->getSession() |
||
258 | ->getClientUsingPooler('model', $identifier); |
||
259 | } |
||
260 | |||
261 | |||
262 | /** |
||
263 | * getFlexibleEntityClass |
||
264 | * |
||
265 | * Return the according flexible entity class associate with this Model |
||
266 | * instance. |
||
267 | * |
||
268 | * @access public |
||
269 | * @return string |
||
270 | */ |
||
271 | public function getFlexibleEntityClass() |
||
272 | { |
||
273 | return $this->flexible_entity_class; |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * escapeLiteral |
||
278 | * |
||
279 | * Handy method to escape strings. |
||
280 | * |
||
281 | * @access protected |
||
282 | * @param string $string |
||
283 | * @return string |
||
284 | */ |
||
285 | protected function escapeLiteral($string) |
||
286 | { |
||
287 | return $this |
||
288 | ->getSession() |
||
289 | ->getConnection() |
||
290 | ->escapeLiteral($string); |
||
291 | } |
||
292 | |||
293 | /** |
||
294 | * escapeLiteral |
||
295 | * |
||
296 | * Handy method to escape strings. |
||
297 | * |
||
298 | * @access protected |
||
299 | * @param string $string |
||
300 | * @return string |
||
301 | */ |
||
302 | protected function escapeIdentifier($string) |
||
303 | { |
||
304 | return $this |
||
305 | ->getSession() |
||
306 | ->getConnection() |
||
307 | ->escapeIdentifier($string); |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * executeAnonymousQuery |
||
312 | * |
||
313 | * Handy method for DDL statements. |
||
314 | * |
||
315 | * @access protected |
||
316 | * @param string $sql |
||
317 | * @return Model $this |
||
318 | */ |
||
319 | protected function executeAnonymousQuery($sql) |
||
320 | { |
||
321 | $this |
||
322 | ->getSession() |
||
323 | ->getConnection() |
||
324 | ->executeAnonymousQuery($sql); |
||
325 | |||
326 | return $this; |
||
327 | } |
||
328 | } |
||
329 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: