Issues (180)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Relations/One2One.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Fwk
4
 *
5
 * Copyright (c) 2011-2012, Julien Ballestracci <[email protected]>.
6
 * All rights reserved.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
12
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
13
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
15
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
16
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
17
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
19
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
21
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22
 * POSSIBILITY OF SUCH DAMAGE.
23
 *
24
 * PHP Version 5.3
25
 * 
26
 * @category  Database
27
 * @package   Fwk\Db
28
 * @author    Julien Ballestracci <[email protected]>
29
 * @copyright 2011-2012 Julien Ballestracci <[email protected]>
30
 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
31
 * @link      http://www.phpfwk.com
32
 */
33
namespace Fwk\Db\Relations;
34
35
use Fwk\Db\Events\AbstractEntityEvent;
36
use Fwk\Db\Events\BeforeSaveEvent;
37
use Fwk\Db\Events\BeforeUpdateEvent;
38
use Fwk\Db\RelationInterface;
39
use Fwk\Db\Query;
40
use Fwk\Db\Accessor;
41
use Fwk\Db\Registry\Registry;
42
use Fwk\Db\Workers\SaveEntityWorker;
43
use Fwk\Db\Workers\DeleteEntityWorker;
44
use Fwk\Events\Dispatcher;
45
46
/**
47
 * Represents a One --> One database relation.
48
 *
49
 * @category Relations
50
 * @package  Fwk\Db
51
 * @author   Julien Ballestracci <[email protected]>
52
 * @license  http://www.opensource.org/licenses/bsd-license.php  BSD License
53
 * @link     http://www.phpfwk.com
54
 */
55
class One2One extends AbstractRelation implements RelationInterface
56
{
57
    /**
58
     * Prepares a Query to fetch this relation (only FETCH_EAGER)
59
     *
60
     * @param Query  $query      The query
61
     * @param string $columnName Column name on the parent entity
62
     *
63
     * @return void
64
     */
65
    public function prepare(Query $query, $columnName)
66
    {
67
        if ($this->isLazy()) {
68
            return; 
69
        }
70
71
        $this->columnName = $columnName;
72
        $join = array(
73
            'column'    => $this->columnName,
74
            'relation'  => $this,
75
            'skipped'   => false,
76
            'reference' => null,
77
            'entity'    => $this->getEntity()
78
        );
79
80
        $query->join(
81
            $this->getTableName(),
82
            $this->getLocal(),
83
            $this->getForeign(),
84
            Query::JOIN_LEFT, 
85
            $join
86
        );
87
    }
88
89
    /**
90
     * Fetches (if necessary) relation's entities
91
     * 
92
     * @return One2One
93
     */
94
    public function fetch()
95
    {
96
        if (!$this->fetched && $this->isActive()) {
97
            $query = new Query();
98
            $query->entity($this->getEntity());
99
100
            $query->select()
101
                ->from($this->getTableName(), 'lazy')
102
                ->where('lazy.'. $this->getForeign() .'=?');
103
104
            $connect    = $this->getConnection();
105
            $res        = $connect->execute($query, array($this->parentRefs));
106
            $idKeys     = $connect->table($this->getTableName())
107
                ->getIdentifiersKeys();
108
109
            if (count($res) >= 1) {
110
                $ids     = array();
111
                $access  = new Accessor($res[0]);
112
                foreach ($idKeys as $key) {
113
                    $ids[$key] = $access->get($key);
114
                }
115
                parent::add($res[0], $ids);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (add() instead of fetch()). Are you sure this is correct? If so, you might want to change this to $this->add().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
116
            }
117
118
            $this->setFetched(true);
119
        }
120
121
        return $this;
122
    }
123
124
    /**
125
     * Fetches and return the entity (or null)
126
     *
127
     * @return mixed
128
     */
129
    public function get()
130
    {
131
        $this->fetch();
132
133
        foreach ($this->getRegistry()->getStore() as $entry) {
134
            return $entry->getObject();
135
        }
136
137
        return null;
138
    }
139
140
    /**
141
     * Defines the $object as the One.
142
     * 
143
     * If $object is null, the relation is canceled on the parent object
144
     * 
145
     * @param mixed $object Entity
146
     * 
147
     * @return void 
148
     */
149
    public function set($object = null)
150
    {
151
        if (null === $object) {
152
            foreach ($this->getRegistry()->getStore() as $entry) {
153
                $this->remove($entry->getObject());
154
            }
155
156
            return;
157
        }
158
159
        parent::add($object);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (add() instead of set()). Are you sure this is correct? If so, you might want to change this to $this->add().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
160
    }
161
162
    /**
163
     * Magic method to allow $parent->relation->propName;
164
     * Returns value from the linked object.
165
     * 
166
     * @param string $key Property/Column name
167
     * 
168
     * @throws \RuntimeException if relation is empty
169
     * @return mixed 
170
     */
171
    public function __get($key)
172
    {
173
        $obj = $this->get();
174
        if (!\is_object($obj)) {
175
            throw new \RuntimeException('Empty relation');
176
        }
177
        
178
        return Accessor::factory($obj)->get($key);
179
    }
180
181
    /**
182
     * Magic method to allow $parent->relation->propName = "value"
183
     * 
184
     * @param string $key   Property/Column name
185
     * @param mixed  $value The value
186
     * 
187
     * @return void 
188
     */
189
    public function __set($key, $value)
190
    {
191
        $obj    = $this->get();
192
        if (!\is_object($obj)) {
193
            throw new \RuntimeException('Empty relation');
194
        }
195
        
196
        Accessor::factory($obj)->set($key, $value);
197
    }
198
199
    /**
200
     * Magic method to allow isset($parent->relation->propName)
201
     * 
202
     * @param string $key Property/Column name
203
     * 
204
     * @return boolean 
205
     */
206
    public function __isset($key)
0 ignored issues
show
function __isset() does not seem to conform to the naming convention (^(?:is|has|should|may|su...ster|unregister|exists)).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
207
    {
208
        $obj    = $this->fetch();
209
        if (!\is_object($obj)) {
210
            throw new \RuntimeException('Empty relation');
211
        }
212
        
213
        $test = Accessor::factory($obj)->get($key);
214
215
        return ($test != false ? true : false);
216
    }
217
218
    /**
219
     * Magic method to allow calling methods like $parent->relation->call()
220
     * 
221
     * @param string $name      Method name
222
     * @param array  $arguments Call arguments
223
     * 
224
     * @return mixed 
225
     */
226
    public function __call($name, $arguments)
227
    {
228
        $obj = $this->get();
229
        if (!\is_object($obj)) {
230
            throw new \RuntimeException('Empty relation');
231
        }
232
        
233
        $access = new Accessor($obj);
234
        try {
235
            $access->getReflector()->getMethod($name);
236
237
            return \call_user_func_array(array($obj, $name), $arguments);
238
        } catch (\ReflectionException $e) {
239
            throw new \RuntimeException(
240
                sprintf(
241
                    'Unable to call method %s::%s(): %s', 
242
                    get_class($obj), 
243
                    $name, 
244
                    $e->getMessage()
245
                )
246
            );
247
        }
248
    }
249
250
    /**
251
     * Defines a parent object (the other One) 
252
     * 
253
     * @param mixed      $object The parent object
254
     * @param Dispatcher $evd    The related Events Dispatcher
255
     * 
256
     * @return boolean
257
     */
258
    public function setParent($object, Dispatcher $evd)
259
    {
260
        $return = parent::setParent($object, $evd);
261
        if ($return === true) {
262
            $evd->on(BeforeSaveEvent::EVENT_NAME, array($this, 'onBeforeParentSave'));
263
            $evd->on(BeforeUpdateEvent::EVENT_NAME, array($this, 'onBeforeParentSave'));
264
        }
265
266
        return $return;
267
    }
268
269
    /**
270
     * Listener executed when parent entity is saved
271
     *
272
     * @param AbstractEntityEvent $event Dispatched event
273
     * 
274
     * @return void
275
     */
276
    public function onBeforeParentSave(AbstractEntityEvent $event)
277
    {
278
        $connection = $event->getConnection();
279
        $parent     = $event->getEntity();
280
281
        foreach ($this->getWorkersQueue() as $worker) {
282
            $worker->setRegistry($this->registry);
283
            $entity = $worker->getEntity();
284
285
            if ($worker instanceof SaveEntityWorker) {
286
                $worker->execute($connection);
287
                $current = Accessor::factory($entity)->get($this->foreign);
288
                Accessor::factory($parent)->set($this->local, $current);
289
                $this->getRegistry()->defineInitialValues(
290
                    $entity,
291
                    $connection,
292
                    $connection->table($this->tableName)
293
                );
294
            }
295
296
            if ($worker instanceof DeleteEntityWorker) {
297
                Accessor::factory($parent)->set($this->local, null);
298
                $this->getRegistry()->remove($entity);
299
            }
300
        }
301
    }
302
303
    /**
304
     * Returns an array of all entities in this relation
305
     *
306
     * @return array
307
     */
308
    public function toArray()
309
    {
310
        $this->fetch();
311
312
        $final = array();
313
        $list = $this->getRegistry()->getStore();
314
        foreach ($list as $entry) {
315
            if ($entry->getAction() == Registry::ACTION_DELETE) {
316
                continue;
317
            }
318
319
            $final[] = $entry->getObject();
320
        }
321
322
        return $final;
323
    }
324
}
325