User   B
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 459
Duplicated Lines 5.66 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 26
loc 459
rs 8.2608
c 0
b 0
f 0
wmc 40
lcom 1
cbo 1

13 Methods

Rating   Name   Duplication   Size   Complexity  
B getUser() 0 23 4
A __construct() 0 4 1
A setRememberMeCookie() 0 10 1
A logoutUser() 0 8 1
A isAuthorized() 0 4 1
A deleteJoinedButNotActivitatedUsers() 0 8 1
A isUserAuthenticated() 0 8 3
A getUserIdFromSession() 0 4 1
F createUserSession() 10 153 13
B checkUser() 16 40 5
B loginUser() 0 30 2
B checkLoginCookie() 0 41 5
A sessionSetUserId() 0 20 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like User often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use User, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * Koch Framework
5
 * Jens-André Koch © 2005 - onwards.
6
 *
7
 * This file is part of "Koch Framework".
8
 *
9
 * License: GNU/GPL v2 or any later version, see LICENSE file.
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 2 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace Koch\User;
26
27
/**
28
 * Koch Framework - Class for User Handling.
29
 */
30
class User
31
{
32
    /**
33
     * @var object User Object
34
     */
35
    private $user = null;
36
37
    /**
38
     * @var object Koch\Configuration
39
     */
40
    private $config = null;
41
42
    /**
43
     * Constructor.
44
     */
45
    public function __construct(\Koch\Config\Config $config)
46
    {
47
        $this->config = $config;
48
    }
49
50
    /**
51
     * getUser by user_id.
52
     *
53
     * @param int $user_id The ID of the User. Defaults to the user_id from session.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $user_id not be integer|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...
54
     *
55
     * @return array $userdata (Dataset of CsUsers + CsProfile)
0 ignored issues
show
Documentation introduced by
Should the return type not be array|false? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
56
     */
57
    public function getUser($user_id = null)
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Coding Style introduced by
getUser uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
58
    {
59
        // init user_id
60
        if ($user_id === null and $_SESSION['user']['user_id'] > 0) {
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
61
            // incomming via session
62
            $user_id = $_SESSION['user']['user_id'];
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
63
        } else {
64
            // incomming via method parameter
65
            $user_id = (int) $user_id;
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
66
        }
67
68
        $userdata = Doctrine_Query::create()
69
            ->from('CsUsers u')
70
            ->leftJoin('CsProfiles')
71
            ->where('u.user_id = ?')
72
            ->fetchOne([$user_id], Doctrine::HYDRATE_ARRAY);
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
73
74
        if (is_array($userdata)) {
75
            return $userdata;
76
        } else {
77
            return false;
78
        }
79
    }
80
81
    /**
82
     * Creates the User-Object and the $session['user'] Array.
83
     *
84
     * @param $user_id The ID of the User.
85
     * @param $email The email of the User.
86
     * @param $nick The nick of the User.
87
     */
88
    public function createUserSession($user_id = '', $email = '', $nick = '')
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Coding Style introduced by
createUserSession uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
createUserSession uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
89
    {
90
        // Initialize the User Object
91
        $this->user = null;
92
93
        /*
94
         * Get User via DB Queries
95
         *
96
         * 1) user_id
97
         * 2) email
98
         * 3) nick
99
         */
100
        if (empty($user_id) === false) {
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
101
            // Get the user from the user_id
102
            $this->user = Doctrine_Query::create()
103
                #->select('u.*,g.*,o.*')
104
                ->from('CsUsers u')
105
                ->leftJoin('u.CsOptions o')
106
                #->leftJoin('u.CsGroups g')
107
                ->where('u.user_id = ?')
108
                ->fetchOne([$user_id], Doctrine::HYDRATE_ARRAY);
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
109
        } elseif (empty($email) === false) {
110
            // Get the user from the email
111
            $this->user = Doctrine_Query::create()
112
                #->select('u.*,g.*,o.*')
113
                ->from('CsUsers u')
114
                ->leftJoin('u.CsOptions o')
115
                #->leftJoin('u.CsGroups g')
116
                ->where('u.email = ?')
117
                ->fetchOne([$email], Doctrine::HYDRATE_ARRAY);
118
        } elseif (empty($nick) === false) {
119
            // Get the user from the nick
120
            $this->user = Doctrine_Query::create()
121
                #->select('u.*,g.*,o.*')
122
                ->from('CsUsers u')
123
                ->leftJoin('u.CsOptions o')
124
                #->leftJoin('u.CsGroups g')
125
                ->where('u.nick = ?')
126
                ->fetchOne([$nick], Doctrine::HYDRATE_ARRAY);
127
        }
128
129
        /*
130
         * Check if this user is activated,
131
         * else reset cookie, session and redirect
132
         */
133
        if (is_array($this->user) and $this->user['activated'] === 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
134
            $this->logoutUser();
135
136
            // redirect
137
            $message = _('Your account is not yet activated.');
138
139
            \Koch\Http\HttpResponse::redirect('/account/activation_email', 5, 403, $message);
140
        }
141
142
        /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
143
         * Create $_SESSION['user'] array, containing user data
144
         */
145
        if (is_array($this->user)) {
146
            /*
147
             * Transfer User Data into Session
148
             */
149
            #\Koch\Debug\Debug::firebug($_SESSION);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
150
            #\Koch\Debug\Debug::firebug($this->config);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
151
152
            $_SESSION['user']['authed']  = 1;
153
            $_SESSION['user']['user_id'] = $this->user['user_id'];
154
155
            $_SESSION['user']['passwordhash'] = $this->user['passwordhash'];
156
            $_SESSION['user']['email']        = $this->user['email'];
157
            $_SESSION['user']['nick']         = $this->user['nick'];
158
159
            $_SESSION['user']['disabled']  = $this->user['disabled'];
160
            $_SESSION['user']['activated'] = $this->user['activated'];
161
162
            /*
163
             * SetLanguage
164
             *
165
             * At this position the language might already by set by
166
             * the language_via_get filter. the language value set via GET
167
             * precedes over the user config and the general config
168
             * the full order is
169
             * a) language_via_get filter
170
             * a) user['language'] from database / personal user setting
171
             * b) standard language / fallback as defined by $this->config['locale']['locale']
172
             */
173
            if (false === isset($_SESSION['user']['language_via_url'])) {
174
                $_SESSION['user']['language'] = (false === empty($this->user['language']))
175
                ? $this->user['language']
176
                : $this->config['locale']['default'];
177
            }
178
179
            /**
180
             * Frontend-Theme.
181
             *
182
             * first take standard theme as defined by $config->theme
183
             *
184
             * @todo remove $_REQUEST, frontend theme is selectable via frontend
185
             */
186 View Code Duplication
            if (false === isset($_REQUEST['theme'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
187
                $_SESSION['user']['frontend_theme'] = (!empty($this->user['frontend_theme']))
188
                ? $this->user['frontend_theme']
189
                : $this->config['template']['frontend_theme'];
190
            }
191
192
            /*
193
             * Backend-Theme
194
             */
195 View Code Duplication
            if (empty($this->user['backend_theme']) === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
                $_SESSION['user']['backend_theme'] = $this->user['backend_theme'];
197
            } else {
198
                $_SESSION['user']['backend_theme'] = $this->config['template']['backend_theme'];
199
            }
200
201
            /*
202
             * Permissions
203
             *
204
             * Get Group & Rights of user_id
205
             */
206
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
207
              User-Datensatz beinhaltet ein CsGroups-Array
208
              user => Array (
209
              [user_id] => 1
210
              ...
211
              [CsGroups] => Array (
212
              [0] => Array (
213
              [group_id] => 3
214
              ...
215
              [role_id] => 5
216
              )
217
              )
218
              )
219
             */
220
            // Initialize User Session Arrays
221
            $_SESSION['user']['group']  = '';
222
            $_SESSION['user']['rights'] = '';
223
224
            if (false === empty($this->user['CsGroups'])) {
225
                $_SESSION['user']['group']  = $this->user['CsGroups'][0]['group_id'];
226
                $_SESSION['user']['role']   = $this->user['CsGroups'][0]['role_id'];
227
                $_SESSION['user']['rights'] = Koch\ACL::createRightSession(
228
                    $_SESSION['user']['role'],
229
                    $this->user['user_id']
230
                );
231
            }
232
233
            #\Koch\Debug\Debug::firebug($_SESSION);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
234
        } else {
235
            // this resets the $_SESSION['user'] array
0 ignored issues
show
Unused Code Comprehensibility introduced by
39% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
236
            GuestUser::instantiate();
237
238
            #Koch\Debug\Debug::printR($_SESSION);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
239
        }
240
    }
241
242
    /**
243
     * Check the user.
244
     *
245
     * Validates the existance of the user via nick or email and the passwordhash
246
     * This is done in two steps:
247
     * 1. check if given nick or email exists
248
     * and if thats the case
249
     * 2. compare password from login form with database
250
     *
251
     * @param string $login_method contains the login_method ('nick' or 'email')
252
     * @param string $value        contains nick or email string to look for
0 ignored issues
show
Documentation introduced by
Should the type for parameter $value 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...
253
     * @param string $passwordhash contains password string
0 ignored issues
show
Documentation introduced by
Should the type for parameter $passwordhash 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...
254
     *
255
     * @return int ID of User. If the user is found, the $user_id - otherwise false.
256
     */
257
    public function checkUser($login_method = 'nick', $value = null, $passwordhash = null)
0 ignored issues
show
Coding Style introduced by
$login_method does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
258
    {
259
        $user = null;
260
261
        // check if a given nick or email exists
262 View Code Duplication
        if ($login_method === 'nick') {
0 ignored issues
show
Coding Style introduced by
$login_method does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
263
            // get user_id and passwordhash with the nick
264
            $user = Doctrine_Query::create()
265
                ->select('u.user_id, u.passwordhash, u.salt')
266
                ->from('CsUsers u')
267
                ->where('u.nick = ?')
268
                ->fetchOne([$value], Doctrine::HYDRATE_ARRAY);
269
        }
270
271
        // check if a given email exists
272 View Code Duplication
        if ($login_method === 'email') {
0 ignored issues
show
Coding Style introduced by
$login_method does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
273
            // get user_id and passwordhash with the email
274
            $user = Doctrine_Query::create()
275
                ->select('u.user_id, u.passwordhash, u.salt')
276
                ->from('CsUsers u')
277
                ->where('u.email = ?')
278
                ->fetchOne([$value], Doctrine::HYDRATE_ARRAY);
279
        }
280
281
        $this->moduleconfig = $this->config->readModuleConfig('account');
0 ignored issues
show
Bug introduced by
The property moduleconfig does not seem to exist. Did you mean config?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
282
283
        // if user was found, check if passwords match each other
284
        if (true === (bool) $user and true === Koch\Security\Security::checkSaltedHash(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
285
            $passwordhash,
286
            $user['passwordhash'],
287
            $user['salt'],
288
            $this->moduleconfig['login']['hash_algorithm']
0 ignored issues
show
Bug introduced by
The property moduleconfig does not seem to exist. Did you mean config?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
289
        )) {
290
            // ok, the user with nick or email exists and the passwords matched, then return the user_id
291
            return $user['user_id'];
292
        } else {
293
            // no user was found with this combination of either nick and password or email and password
294
            return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by Koch\User\User::checkUser of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
295
        }
296
    }
297
298
    /**
299
     * Login.
300
     *
301
     * @param int    $user_id      contains user_id
302
     * @param int    $remember_me  contains remember_me setting
303
     * @param string $passwordhash contains password string
304
     */
305
    public function loginUser($user_id, $remember_me, $passwordhash)
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Coding Style introduced by
loginUser uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
306
    {
307
        /*
308
         * 1. Create the User Data Array and the Session via $user_id
309
         */
310
        $this->createUserSession($user_id);
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
311
312
        /*
313
         * 2. Remember-Me ( set Logindata via Cookie )
314
         */
315
        if ($remember_me === true) {
0 ignored issues
show
Coding Style introduced by
$remember_me does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
316
            $this->setRememberMeCookie($user_id, $passwordhash);
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
317
        }
318
319
        /*
320
         * 3. user_id is now inserted into the session
321
         * This transforms the so called Guest-Session to a User-Session
322
         */
323
        $this->sessionSetUserId($user_id);
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
324
325
        /*
326
         * 4. Delete Login attempts
327
         */
328
        unset($_SESSION['login_attempts']);
329
330
        /*
331
         * 5. Stats-Updaten
332
         * @todo stats update after login?
333
         */
334
    }
335
336
    /**
337
     * Set the remember me cookie
338
     * If this cookie is found, the user is re-logged in automatically.
339
     *
340
     * @param int    $user_id      contains user_id
341
     * @param string $passwordhash contains password string
342
     */
343
    private function setRememberMeCookie($user_id, $passwordhash)
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
344
    {
345
        // calculate cookie lifetime and combine cookie string
346
        $cookie_lifetime = time() + round($this->moduleconfig['login']['remember_me_time'] * 24 * 60 * 60);
0 ignored issues
show
Coding Style introduced by
$cookie_lifetime does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Bug introduced by
The property moduleconfig does not seem to exist. Did you mean config?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
347
        $cookie_string   = $user_id . '#' . $passwordhash;
0 ignored issues
show
Coding Style introduced by
$cookie_string does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
348
349
        setcookie('cs_cookie', $cookie_string, $cookie_lifetime);
0 ignored issues
show
Coding Style introduced by
$cookie_string does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
350
351
        unset($cookie_string, $cookie_lifetime);
0 ignored issues
show
Coding Style introduced by
$cookie_string does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
352
    }
353
354
    /**
355
     * Logout.
356
     */
357
    public function logoutUser()
358
    {
359
        // Destroy the old session
360
        session_regenerate_id(true);
361
362
        // Delete cookie
363
        setcookie('cs_cookie', false);
364
    }
365
366
    /**
367
     * Checks if a login cookie is set.
368
     */
369
    public function checkLoginCookie()
0 ignored issues
show
Coding Style introduced by
checkLoginCookie uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
370
    {
371
        // Check for login cookie
372
        if (isset($_COOKIE['cs_cookie'])) {
373
            $cookie_array    = explode('#', $_COOKIE['cs_cookie']);
0 ignored issues
show
Coding Style introduced by
$cookie_array does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
374
            $cookie_user_id  = (int) $cookie_array['0'];
0 ignored issues
show
Coding Style introduced by
$cookie_user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Unused Code introduced by
$cookie_user_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
375
            $cookie_password = (string) $cookie_array['1'];
0 ignored issues
show
Coding Style introduced by
$cookie_password does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Unused Code introduced by
$cookie_password is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
376
377
            #Koch_Module_Controller::initModel('users');
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
378
379
            $this->user = Doctrine_Query::create()
380
                ->select('u.user_id, u.passwordhash, u.salt')
381
                ->from('CsUsers u')
382
                ->where('u.user_id = ?')
383
                ->fetchOne([$user_id], Doctrine::HYDRATE_ARRAY);
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Bug introduced by
The variable $user_id does not exist. Did you mean $cookie_user_id?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
384
385
            $this->moduleconfig = $this->config->readModuleConfig('account');
0 ignored issues
show
Bug introduced by
The property moduleconfig does not seem to exist. Did you mean config?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
386
387
            $hash_ok = Koch\Security::checkSaltedHash(
0 ignored issues
show
Coding Style introduced by
$hash_ok does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
388
                $_COOKIE['cs_cookie_password'],
389
                $this->user['passwordhash'],
390
                $this->user['salt'],
391
                $this->moduleconfig['login']['hash_algorithm']
0 ignored issues
show
Bug introduced by
The property moduleconfig does not seem to exist. Did you mean config?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
392
            );
393
394
            if (is_array($this->user) and $hash_ok and $_COOKIE['cs_cookie_user_id'] === $this->user['user_id']) {
0 ignored issues
show
Coding Style introduced by
$hash_ok does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
395
                // Update the cookie
396
                $this->setRememberMeCookie($_COOKIE['cs_cookie_user_id'], $_COOKIE['cs_cookie_password']);
397
398
                // Create the user session array ($this->session['user'] etc.) by using this user_id
399
                $this->createUserSession($this->user['user_id']);
400
401
                // Update Session in DB
402
                $this->sessionSetUserId($this->user['user_id']);
403
            } else {
404
                // Delete cookies, if no match
405
                setcookie('cs_cookie_user_id', false);
406
                setcookie('cs_cookie_password', false);
407
            }
408
        }
409
    }
410
411
    /**
412
     * Sets user_id to current session.
413
     *
414
     * @param $user_id int The user_id to set to the session.
415
     */
416
    public function sessionSetUserId($user_id)
0 ignored issues
show
Coding Style introduced by
function sessionSetUserId() does not seem to conform to the naming convention (^(?:is|has|should|may|supports)).

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...
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
417
    {
418
        $result = Doctrine_Query::create()
419
            ->select('user_id')
420
            ->from('CsSession')
421
            ->where('session_id = ?')
422
            ->fetchOne([session_id()]);
423
424
        /*
425
         * Update Session, because we know that session_id already exists
426
         */
427
        if ($result) {
428
            $result->user_id = $user_id;
0 ignored issues
show
Coding Style introduced by
$user_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

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...
429
            $result->save();
430
431
            return true;
432
        }
433
434
        return false;
435
    }
436
437
    /**
438
     * Checks, if the user is authorized to access a resource.
439
     * It's a proxy method forwarding to Authorization::isAuthorized().
440
     *
441
     * @param string $module     Module name, e.g. 'guestbook'.
442
     * @param string $permission Permission name, e.g. 'actionList'.
443
     *
444
     * @return bool True, if the user is authorized. Otherwise, false.
445
     */
446
    public static function isAuthorized($module = '', $permission = '')
447
    {
448
        return \Koch\User\Authorization\Authorization::isAuthorized($module, $permission);
449
    }
450
451
    /**
452
     * Deletes all USERS which have joined but are not activated after 3 days.
453
     *
454
     * 259200 = (60s * 60m * 24h * 3d)
455
     */
456
    public function deleteJoinedButNotActivitatedUsers()
457
    {
458
        Doctrine_Query::create()
459
            ->delete('CsUsers')
460
            ->from('CsUsers')
461
            ->where('activated = ? AND joined < ?')
462
            ->execute([0, time() - 259200]);
463
    }
464
465
    /**
466
     * Check, whether a user is authenticated (logged in).
467
     *
468
     * @return bool Returns Tru,e if user is authenticated. Otherwise, false.
469
     */
470
    public function isUserAuthenticated()
0 ignored issues
show
Coding Style introduced by
isUserAuthenticated uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
471
    {
472
        if (true === isset($_SESSION['user']['authenticated']) and true === (bool) $_SESSION['user']['authenticated']) {
0 ignored issues
show
Coding Style introduced by
The if-else statement can be simplified to return true === isset($_...ser']['authenticated'];.
Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
473
            return true;
474
        } else {
475
            return false;
476
        }
477
    }
478
479
    /**
480
     * Returns the user_id from Session.
481
     *
482
     * @return int user_id
483
     */
484
    public function getUserIdFromSession()
0 ignored issues
show
Coding Style introduced by
getUserIdFromSession uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
485
    {
486
        return $_SESSION['user']['user_id'];
487
    }
488
}
489