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/Table.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;
34
35
use Fwk\Db\Registry\Registry;
36
37
/**
38
 * Table 
39
 * 
40
 * Represents a database table. 
41
 * 
42
 * @category Library
43
 * @package  Fwk\Db
44
 * @author   Julien Ballestracci <[email protected]>
45
 * @license  http://www.opensource.org/licenses/bsd-license.php  BSD License
46
 * @link     http://www.phpfwk.com
47
 */
48
class Table
49
{
50
    /**
51
     * Table name
52
     *
53
     * @var string
54
     */
55
    protected $name;
56
57
    /**
58
     * Connection
59
     *
60
     * @var Connection
61
     */
62
    protected $connection;
63
64
    /**
65
     * Array of primary keys
66
     *
67
     * @var array
68
     */
69
    protected $identifiersKey;
70
71
    /**
72
     * Entity registry
73
     *
74
     * @var Registry
75
     */
76
    protected $registry;
77
78
    /**
79
     * Classname of the default entity for this table
80
     *
81
     * @var string
82
     */
83
    protected $defaultEntity;
84
85
    /**
86
     * List of default entity listeners to be used with this table
87
     *
88
     * @var array
89
     */
90
    protected $defaultEntityListeners = array();
91
92
    /**
93
     * Constructor
94
     *
95
     * @param string $tableName This table name
96
     * 
97
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
98
     */
99
    public function __construct($tableName)
100
    {
101
        $this->name     = $tableName;
102
    }
103
104
    /**
105
     * Returns all columns from this table
106
     *
107
     * @return array
0 ignored issues
show
Consider making the return type a bit more specific; maybe use \Doctrine\DBAL\Schema\Column[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
108
     */
109
    public function getColumns()
110
    {
111
        return $this
112
            ->getConnection()
113
            ->getSchema()
114
            ->getTable($this->name)
115
            ->getColumns();
116
    }
117
118
    /**
119
     * Defines a connection for this table
120
     *
121
     * @param Connection $connection Database connection
122
     * 
123
     * @return Table
124
     */
125
    public function setConnection(Connection $connection)
126
    {
127
        $this->connection   = $connection;
128
129
        return $this;
130
    }
131
132
    /**
133
     * Returns current connection for this table
134
     *
135
     * @throws Exception If no connection is defined
136
     * @return Connection
137
     */
138
    public function getConnection()
139
    {
140
        if (!isset($this->connection)) {
141
            throw new Exception(
142
                sprintf(
143
                    'No connection defined for table "%s"', 
144
                    $this->name
145
                )
146
            );
147
        }
148
149
        return $this->connection;
150
    }
151
152
    /**
153
     * Returns a Finder instance to navigate into this table
154
     *
155
     * @param string $entity    Entity class to be returned by this Finder
0 ignored issues
show
Should the type for parameter $entity not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
156
     * @param array  $listeners Overrides default entity/table listeners
157
     *
158
     * @return Finder
159
     */
160
    public function finder($entity = null, array $listeners = array())
161
    {
162
163
        $finder = new Finder($this, $this->connection);
164
        $finder->setEntity($entity, $listeners);
165
166
        return $finder;
167
    }
168
169
    /**
170
     * Returns this table's name
171
     *
172
     * @return string
173
     */
174
    public function getName()
175
    {
176
177
        return $this->name;
178
    }
179
180
    /**
181
     * Returns primary identifiers keys for this table
182
     *
183
     * @throws Exceptions\TableLacksIdentifiersException
184
     *
185
     * @return array
186
     */
187
    public function getIdentifiersKeys()
188
    {
189
        if (!isset($this->identifiersKey)) {
190
            $idx = $this
191
                ->getConnection()
192
                ->getSchema()
193
                ->getTable($this->name)
194
                ->getIndexes();
195
196
            if (!count($idx)) {
197
                throw new Exceptions\TableLacksIdentifiersException(
198
                    sprintf('"%s" has no indexes', $this->name)
199
                );
200
            }
201
202
            $final = array();
203
            foreach ($idx as $index) {
204
                if ($index->isPrimary()) {
205
                    $final += $index->getColumns();
206
                }
207
            }
208
209
            $final = array_unique($final);
210
            if (!count($final)) {
211
                throw new Exceptions\TableLacksIdentifiersException(
212
                    sprintf('"%s" has no identifiers key(s)', $this->name)
213
                );
214
            }
215
216
            $this->identifiersKey = $final;
217
        }
218
219
        return $this->identifiersKey;
220
    }
221
222
    /**
223
     * Returns the entity registry for this table
224
     *
225
     * @return Registry
226
     */
227
    public function getRegistry()
228
    {
229
        if (!isset($this->registry)) {
230
            $this->registry = new Registry($this->name);
231
        }
232
233
        return $this->registry;
234
    }
235
236
    /**
237
     * Returns an object representation of a given column
238
     *
239
     * @param string $columnName Column name
240
     * 
241
     * @return \Doctrine\DBAL\Schema\Column
242
     */
243
    public function getColumn($columnName)
244
    {
245
        if (!$this->hasColumn($columnName)) {
246
            throw new Exceptions\TableColumnNotFoundException(
247
                sprintf(
248
                    'Unknown Column "%s" on table %s',
249
                    $columnName,
250
                    $this->name
251
                )
252
            );
253
        }
254
255
        return $this->getConnection()
256
            ->getSchema()
257
            ->getTable($this->name)
258
            ->getColumn($columnName);
259
    }
260
261
    /**
262
     * Tells if this table has a column named $columnName
263
     * 
264
     * @param string $columnName Column name
265
     * 
266
     * @return boolean 
267
     */
268
    public function hasColumn($columnName)
269
    {
270
        $tbl = $this->getConnection()->getSchema()->getTable($this->name);
271
272
        return $tbl->hasColumn($columnName);
273
    }
274
275
    /**
276
     * Defines the default returned entity
277
     * 
278
     * @param string $entityClass Entity class name
279
     * 
280
     * @return Table 
281
     */
282
    public function setDefaultEntity($entityClass)
283
    {
284
        $this->defaultEntity = (string)$entityClass;
285
286
        return $this;
287
    }
288
289
    /**
290
     * Returns the default returned entity for this table
291
     * 
292
     * @return string 
293
     */
294
    public function getDefaultEntity()
295
    {
296
        if (!isset($this->defaultEntity)) {
297
            $this->defaultEntity = '\stdClass';
298
        }
299
300
        return $this->defaultEntity;
301
    }
302
303
    /**
304
     * Defines the default entity listeners to be used with this table
305
     *
306
     * @param array $listeners List of listeners
307
     *
308
     * @return Table
309
     */
310
    public function setDefaultEntityListeners(array $listeners)
311
    {
312
        $this->defaultEntityListeners = $listeners;
313
314
        return $this;
315
    }
316
317
    /**
318
     * Returns the default entity listeners used this table
319
     *
320
     * @return array
321
     */
322
    public function getDefaultEntityListeners()
323
    {
324
        return $this->defaultEntityListeners;
325
    }
326
327
    /**
328
     * Save one or more entities into this table
329
     * 
330
     * @param mixed $entity    Entity or List of entities
331
     * @param array $listeners Overrides default entity/table listeners
332
     * 
333
     * @return void 
334
     */
335
    public function save($entity, array $listeners = array())
336
    {
337
        if (!\is_array($entity)) {
338
            $entity = array($entity);
339
        }
340
        
341
        foreach ($entity as $object) {
342
            if (!\is_object($object) || is_null($object)) {
343
                throw new \InvalidArgumentException(
344
                    sprintf(
345
                        "You can only save an object or a list of objects"
346
                    )
347
                );
348
            }
349
            
350
            $this->getRegistry()->markForAction(
351
                $object,
352
                Registry::ACTION_SAVE,
353
                (count($listeners) ? $listeners : $this->getDefaultEntityListeners())
354
            );
355
        }
356
357
        $this->work();
358
    }
359
360
    /**
361
     * Delete one or more entities from this table
362
     * 
363
     * @param mixed $entity    Entity or List of entities
364
     * @param array $listeners Overrides default entity listeners
365
     * 
366
     * @return void 
367
     */
368
    public function delete($entity, array $listeners = array())
369
    {
370
        if (!\is_array($entity)) {
371
            $entity = array($entity);
372
        }
373
374
        foreach ($entity as $object) {
375
            if (!\is_object($object) || is_null($object)) {
376
                throw new \InvalidArgumentException(
377
                    sprintf(
378
                        "You can only save an object or a list of objects"
379
                    )
380
                );
381
            }
382
383
            $this->getRegistry()->markForAction(
384
                $object, 
385
                Registry::ACTION_DELETE,
386
                (count($listeners) ? $listeners : $this->getDefaultEntityListeners())
387
            );
388
        }
389
390
        $this->work();
391
    }
392
393
    /**
394
     * Executes all waiting workers
395
     * 
396
     * @return void
397
     */
398
    protected function work()
399
    {
400
        $queue          = $this->getRegistry()->getWorkersQueue();
401
        $connection     = $this->getConnection();
402
403
        foreach ($queue as $worker) {
404
            $worker->execute($connection);
405
        }
406
    }
407
408
    /**
409
     * Delete all entries from this table
410
     * 
411
     * @return void 
412
     */
413
    public function deleteAll()
414
    {
415
        $query = Query::factory()->delete($this->getName());
416
        $this->getConnection()->execute($query);
417
    }
418
}