Completed
Push — master ( d208aa...25518b )
by Lars
12:37
created

YearEnd::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.0123

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 3
nop 1
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
ccs 8
cts 9
cp 0.8889
crap 3.0123
1
<?php
2
/**
3
 * Meget af det der er i year_end tabellen kan vist lige så godt indkorporeres i selve årstabellen
4
 * @package Intraface_Accounting
5
 */
6
class YearEnd extends Intraface_Standard
7
{
8
    public $error;
9
    public $value;
10
    public $year;
11
12
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% 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...
13
    protected $step = array(
14
        1 => 'Er alle poster i året indtastet?',
15
        2 => 'Har du lavet momsregnskab og opgivet det til Skat?',
16
        3 => 'Vælg resultatkonto og overfør posterne til resultatkontoen',
17
        4 => 'Rapport med årsregnskabet'
18
    );
19
    */
20
21
    // disse typer bruges i forbindelse med om statements er drift eller status
22
    public $types = array(
23
        1 => 'operating',
24
        2 => 'balance'
25
    );
26
27
    public $actions = array(
28
        1 => 'operating_reset',
29
        2 => 'result_account_reset'
30
    );
31
32 8
    function __construct($year)
33
    {
34 8
        if (!is_object($year)) {
35
            throw new Exception('Year::__construct: Ikke et gyldigt Year object');
36
        }
37 8
        $this->year = $year;
38 8
        $this->error = new Intraface_Error;
39 8
        if (!$this->load()) {
40 8
            $this->start();
41 8
        }
42 8
    }
43
44 8 View Code Duplication
    private function load()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
45
    {
46 8
        $db = new DB_Sql;
47 8
        $db->query("SELECT * FROM accounting_year_end WHERE year_id = " . $this->year->get('id') . " AND intranet_id =" . $this->year->kernel->intranet->get('id'));
48 8
        if (!$db->nextRecord()) {
49 8
            return 0;
50
        }
51 2
        $this->value['id'] = $db->f('id');
52 2
        $this->value['step_key'] = $db->f('step_key');
53 2
        $this->value['step'] = $db->f('step_key');
54 8
        $this->value['result_account_reset_voucher_id'] = $db->f('result_account_reset_voucher_id');
55 2
        $this->value['operating_reset_voucher_id'] = $db->f('operating_reset_voucher_id');
56 2
        return $db->f('id');
57
    }
58
59 8
    function start()
60
    {
61 8
        if ($this->get('id') > 0) {
62
            return false;
63
        }
64 8
        $db = new DB_Sql;
65 8
        $db->query("INSERT INTO accounting_year_end SET date_created=NOW(), year_id = " . $this->year->get('id') . ", intranet_id =" .$this->year->kernel->intranet->get('id'));
66 8
        return true;
67
    }
68
69 1
    function setStep($step)
70
    {
71 1
        $db = new DB_Sql;
72 1
        $db->query("UPDATE accounting_year_end SET date_updated=NOW(), step_key = " . (int)$step . " WHERE year_id = " . $this->year->get('id'));
73 1
        return true;
74
    }
75
76 2
    function setStated($action, $voucher_id)
77
    {
78 2
        $db = new DB_Sql;
79
80
        switch ($action) {
81
            // bruges i forbindelse med nulstilling af resultatkontoen
82 2
            case 'operating_reset':
83 1
                $db->query("UPDATE accounting_year_end SET date_updated=NOW(), operating_reset_voucher_id = " . (int)$voucher_id . " WHERE year_id = " . $this->year->get('id'));
84 1
                return true;
85
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
86
            // bruges i forbindelse med overførelse af kapitalkontoen
87 2
            case 'result_account_reset':
88 2
                $db->query("UPDATE accounting_year_end SET date_updated=NOW(), result_account_reset_voucher_id = " . (int)$voucher_id . " WHERE year_id = " . $this->year->get('id'));
89 2
                return true;
90
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
91
92
            default:
93
                throw new Exception('YearEnd::setStated: Ugyldig type');
94
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
95 2
        }
96 2
    }
97
98
    /**
99
     * Denne funktion skal gemme de ændringer der bliver lavet i bogføringen
100
     *
101
     * Det betyder at vi har mulighed for at vende den igen - skal i så tilfælde bogføres
102
     * på samme bilag med modposteringer foran.
103
     *
104
     * debet-konto
105
     * credit-konto
106
     * amount
107
     *
108
     */
109
    function saveStatedAction($action, $voucher_id, $debet_account_id, $credit_account_id, $amount)
110
    {
111
        $db = new Db_Sql;
112
        $db->query("INSERT INTO accounting_year_end_action SET date_created = NOW(), voucher_id = ".$voucher_id.", debet_account_id = ".$debet_account_id.", credit_account_id = ".$credit_account_id.", amount=".$amount.", intranet_id=".$this->year->kernel->intranet->get('id').", type_key = ".array_search($action, $this->actions).", year_id = ".$this->year->get('id'));
113
        return true;
114
    }
115
116
    function deleteStatedAction($id)
117
    {
118
        $db = new DB_Sql;
119
        $db->query("DELETE FROM accounting_year_end_action WHERE id = " . (int)$id);
120
        return true;
121
    }
122
123 1 View Code Duplication
    function getStatedActions($action)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
124
    {
125 1
        $db = new DB_Sql;
126 1
        $db->query("SELECT * FROM accounting_year_end_action WHERE year_id = " . $this->year->get('id') . " AND type_key = ".array_search($action, $this->actions)." AND intranet_id = " . $this->year->kernel->intranet->get('id'));
127 1
        $actions = array();
128 1
        $i = 0;
129 1
        while ($db->nextRecord()) {
130
            $actions[$i]['id'] = $db->f('id');
131
            $actions[$i]['voucher_id'] = $db->f('voucher_id');
132
            $actions[$i]['debet_account_id'] = $db->f('debet_account_id');
133
            $actions[$i]['credit_account_id'] = $db->f('credit_account_id');
134
            $actions[$i]['amount'] = $db->f('amount');
135
136
            $i++;
137
        }
138
139 1
        return $actions;
140
    }
141
142 1
    function flushStatement($type)
143
    {
144 1
        $db = new DB_Sql;
145 1
        $db->query("DELETE FROM accounting_year_end_statement WHERE intranet_id = ".$this->year->kernel->intranet->get('id')." AND year_id = " . $this->year->get('id') . " AND type_key = " . array_search($type, $this->types));
146 1
        return true;
147
    }
148
149
    /**
150
     * Gemme resultatopgørelsen
151
     *
152
     * @todo Der er problemer hvis man gemmer resultatopgørelsen flere gange (hvis man også nulstiller kontiene), så det
153
     * bør vel egentlig ikke være muligt! Måske kan man forestille sig, at den så bare
154
     * gemmer videre og at den ved get lægger tallene i amount sammen?
155
     *
156
     */
157 1
    function saveStatement($type)
158
    {
159 1
        $this->flushStatement($type);
160
161
        switch ($type) {
162 1
            case 'operating':
163
                // disse konti bliver nulstillet, så vi kan ikke bare gemme løs. Hvad gør vi ved det?
164 1
                $account_start = $this->getAccount($this->year->getSetting('result_account_id_start'));
165 1
                $account_end = $this->getAccount($this->year->getSetting('result_account_id_end'));
166 1
                break;
167 1
            case 'balance':
168
                // her kunne det måske være en ide at flushe
169
                // for de bliver ikke nulstillet
170 1
                $account_start = $this->getAccount($this->year->getSetting('balance_account_id_start'));
171 1
                $account_end = $this->getAccount($this->year->getSetting('balance_account_id_end'));
172 1
                break;
173
            default:
174
                throw new Exception('YearEnd::getStatement: Ugyldig type');
175
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
176
        }
177
178 1
        $db = new DB_Sql;
179 1
        $db2 = new DB_Sql;
180
181 1
        $db->query("SELECT id FROM accounting_account WHERE year_id = " .$this->year->get('id'). " AND intranet_id = " . $this->year->kernel->intranet->get('id') . " AND number >= " . $account_start->get('number') . " AND number <= " . $account_end->get('number') . " ORDER BY number ASC");
182
183 1
        while ($db->nextRecord()) {
184
            $account = new Account($this->year, $db->f('id'));
185
            $account->getSaldo();
186
187
            // vi vender sgu lige fortegnet, så udgifter får negativt fortegn
188
            // og indtægter positivt fortegn
189
            $db2->query("INSERT INTO accounting_year_end_statement SET type_key = ".array_search($type, $this->types).", intranet_id = ".$this->year->kernel->intranet->get('id').", year_id = ".$this->year->get('id').", account_id = " . $account->get('id') . ", amount = '".-1 * $account->get('saldo')."'");
190
        }
191
192 1
        return true;
193
    }
194
195 1
    function getAccount($id = 0)
196
    {
197 1
        return new Account($this->year, $id);
198
    }
199
200
    function getStatement($type)
201
    {
202
203
        switch ($type) {
204
            case 'operating':
205
                break;
206
            case 'balance':
207
                break;
208
            default:
209
                throw new Exception('YearEnd::getStatement: Ugyldig type');
210
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
211
        }
212
213
        // @todo hvis jeg kunne få den her til at håndtere summen af det der er gemt,
214
        // så kunne jeg måske gøre noget rigtig smart?
215
        $db = new DB_Sql;
216
        $db->query("SELECT * FROM accounting_year_end_statement WHERE year_id = ".$this->year->get('id')." AND intranet_id = ".$this->year->kernel->intranet->get('id')." AND type_key = ".array_search($type, $this->types)." ORDER BY id ASC");
217
        $i = 0;
218
        while ($db->nextRecord()) {
219
            $account = new Account($this->year, $db->f('account_id'));
220
            $statement[$i]['name'] = $account->get('name');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$statement was never initialized. Although not strictly required by PHP, it is generally a good practice to add $statement = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
221
            $statement[$i]['number'] = $account->get('number');
0 ignored issues
show
Bug introduced by
The variable $statement does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
222
            $statement[$i]['saldo'] = $db->f('amount');
223
            $statement[$i]['type'] = $account->get('type');
224
225
            $i++;
226
        }
227
        return $statement;
228
    }
229
230
    /**
231
     *
232
     * @param $type (kan være do og reverse) - reverse er hvis man fortryder at man har gemt
233
     *              dog skal det jo stadig bogføres
234
     */
235 1
    function resetOperatingAccounts($type = 'do')
236
    {
237
        switch ($type) {
238 1
            case 'do':
239 1
                break;
240
            case 'reverse':
241
                break;
242
            default:
243
                throw new Exception('YearEnd::resetOperatingAccounts ugyldig type');
244
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
245
        }
246
247 1
        if ($this->year->getSetting('result_account_id') <= 0) {
248
            $this->error->set('Resultatkontoen er ikke sat');
249
        }
250
251 1
        if ($this->error->isError()) {
252
            return false;
253
        }
254 1
        $account = $this->getAccount();
255 1
        $result_account = $this->getAccount($this->year->getSetting('result_account_id'));
256
257
        switch ($type) {
258 1
            case 'reverse':
259
                // hvis man vil reverse skal vi finde actions
260
                // vi skal lave bogføringen
261
                // og derefter slette actions igen.
262
263
                if ($this->get('operating_reset_voucher_id') == 0) {
264
                    $this->error->set('Du kan ikke lave en reversep� noget der ikke er bogf�rt');
265
                }
266
267
                $voucher = new Voucher($this->year, $this->get('operating_reset_voucher_id'));
268
269
                $actions = $this->getStatedActions('operating_reset');
270
271
                if (!is_array($actions) or count($actions) == 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or 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...
272
                    $this->error->set('Du kan ikke lave en reverse, n�r der ikke er gemt nogen actions');
273
                }
274
275
                if ($this->error->isError()) {
276
                    $this->error->view();
277
                    return 0;
278
                }
279
280 View Code Duplication
                foreach ($actions as $a) {
281
                    $save_array = array();
0 ignored issues
show
Unused Code introduced by
$save_array 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...
282
                    // der er byttet om på debet og credit med vilje, fordi
283
                    // det skal reverses
284
                    $debet_account = new Account($this->year, $a['credit_account_id']);
285
                    $credit_account = new Account($this->year, $a['debet_account_id']);
286
287
                    $save_array = array(
288
                        'date' => $this->year->get('to_date_dk'),
289
                        'debet_account_number' => $debet_account->get('number'),
290
                        'credit_account_number' => $credit_account->get('number'),
291
                        'amount' => amountToForm($a['amount']),
292
                        'text' => 'Modpostering: ' . $debet_account->get('name') . ' og ' . $credit_account->get('name'),
293
                        'vat_off' => 1
294
295
                    );
296
297
                    if (!empty($save_array)) {
298
                        if ($voucher->saveInDayBook($save_array, true)) {
299
                            $this->deleteStatedAction($a['id']);
300
                        } else {
301
                            $voucher->error->view();
302
                        }
303
                    }
304
                }
305
                break;
306 1
            default:
307 1
                $voucher = new Voucher($this->year, $this->get('operating_reset_voucher_id'));
308 1
                $voucher->save(array(
309 1
                    'date' => $this->year->get('to_date_dk'),
310
                    'text' => 'Årsafslutning. Overførsel af driftskonti til resultatopgørelse'
311 1
                ));
312
313 1
                $accounts = $account->getList('operating', true);
314 1
                if (!is_array($accounts) or count($accounts) == 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or 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...
315 1
                    $this->error->set('Du kan ikke nulstille nogle konti der ikke findes');
316 1
                    return false;
317
                }
318
319
                foreach ($accounts as $a) {
320
                    $save_array = array();
321
                    $account = new Account($this->year, $a['id']);
322
                    $account->getSaldo();
323
324 View Code Duplication
                    if ($account->get('saldo') > 0) {
325
                        $save_array = array(
326
                            'date' => $this->year->get('to_date_dk'),
327
                            'debet_account_number' => $result_account->get('number'),
328
                            'credit_account_number' => $account->get('number'),
329
                            'amount' => amountToForm(abs($account->get('saldo'))), // amountToFrom necessary to get the correct format for daybook
330
                            'text' => $account->get('name') . ' til resultatkontoen',
331
                            'vat_off' => 1
332
333
                        );
334
                        $debet_account = $result_account;
335
                        $credit_account = $account;
336
                    } elseif ($account->get('saldo') <= 0) {
337
                        $save_array = array(
338
                            'date' => $this->year->get('to_date_dk'),
339
                            'debet_account_number' => $account->get('number'),
340
                            'credit_account_number' => $result_account->get('number'),
341
                            'amount' => amountToForm(abs($account->get('saldo'))), // amountToFrom necessary to get the correct format for daybook
342
                            'text' => $account->get('name') . ' til resultatkontoen',
343
                            'vat_off' => 1
344
                        );
345
                        $debet_account = $account;
346
                        $credit_account = $result_account;
347
                    }
348
349 View Code Duplication
                    if (!empty($save_array)) {
350
                        if ($voucher->saveInDayBook($save_array, true)) {
351
                            $this->saveStatedAction('operating_reset', $voucher->get('id'), $debet_account->get('id'), $credit_account->get('id'), abs(amountToForm($account->get('saldo'))));
0 ignored issues
show
Bug introduced by
The variable $debet_account does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $credit_account does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
352
                        }
353
                    }
354
                    $this->setStated('operating_reset', $voucher->get('id'));
355
                }
356
                return true;
357
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
358 1
        }
359
    }
360
361 1
    function resetYearResult($type = 'do')
362
    {
363
        switch ($type) {
364 1
            case 'do':
365
                // her sker ikke noget
366 1
                break;
367
            case 'reverse':
368
                // her sker ikke noget
369
                break;
370
            default:
371
                throw new Exception('YearEnd::resetOperatingAccounts ugyldig type');
372
                break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
373
        }
374
375 1
        if ($this->year->getSetting('result_account_id') <= 0) {
376
            $this->error->set('Resultatkontoen er ikke sat');
377
        }
378
379 1
        if ($this->year->getSetting('capital_account_id') <= 0) {
380
            $this->error->set('Kapitalkontoen er ikke sat');
381
        }
382
383
384 1
        if ($this->error->isError()) {
385
            return false;
386
        }
387
388
        switch ($type) {
389 1
            case 'reverse':
390
                // hvis man vil reverse skal vi finde actions
391
                // vi skal lave bogføringen
392
                // og derefter slette actions igen.
393
394
                if ($this->get('result_account_reset_voucher_id') == 0) {
395
                    $this->error->set('Du kan ikke lave en reverse på noget der ikke er bogført');
396
                }
397
398
                $voucher = new Voucher($this->year, $this->get('result_account_reset_voucher_id'));
399
400
                $actions = $this->getStatedActions('result_account_reset');
401
402
403
                if (!is_array($actions) or count($actions) == 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or 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...
404
                    $this->error->set('Du kan ikke lave en reverse, når der ikke er gemt nogen actions');
405
                }
406
407
                if ($this->error->isError()) {
408
                    return false;
409
                }
410
411 View Code Duplication
                foreach ($actions as $a) {
412
                    $save_array = array();
0 ignored issues
show
Unused Code introduced by
$save_array 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...
413
                    // der er byttet om på debet og credit med vilje, fordi
414
                    // det skal reverses
415
                    $debet_account = new Account($this->year, $a['credit_account_id']);
416
                    $credit_account = new Account($this->year, $a['debet_account_id']);
417
418
                    $save_array = array(
419
                        'date' => $this->year->get('to_date_dk'),
420
                        'debet_account_number' => $debet_account->get('number'),
421
                        'credit_account_number' => $credit_account->get('number'),
422
                        'amount' => amountToForm($a['amount']),
423
                        'text' => 'Modpostering: ' . $debet_account->get('name') . ' og ' . $credit_account->get('name'),
424
                        'vat_off' => 1
425
426
                    );
427
428
                    if (!empty($save_array)) {
429
                        if ($voucher->saveInDayBook($save_array, true)) {
430
                            $this->deleteStatedAction($a['id']);
431
                        }
432
                    }
433
                }
434
                return true;
435
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
436 1
            default:
437 1
                if (!$this->get('result_account_reset_voucher_id')) {
438 1
                    $voucher = new Voucher($this->year);
439 1
                    $voucher->save(array(
440 1
                        'date' => $this->year->get('to_date_dk'),
441
                        'text' => 'Årsafslutning. Årets resultat overføres til egenkapitalen'
442 1
                    ));
443 1
                } else {
444
                    $voucher = new Voucher($this->year, $this->get('result_account_reset_voucher_id'));
445
                }
446
447 1
                $result_account = new Account($this->year, $this->year->getSetting('result_account_id'));
448 1
                $result_account->getSaldo();
449 1
                $capital_account = new Account($this->year, $this->year->getSetting('capital_account_id'));
450
451 1
                $save_array = array();
452 1 View Code Duplication
                if ($result_account->get('saldo') < 0) {
453
                    $save_array = array(
454
                        'date' => $this->year->get('to_date_dk'),
455
                        'debet_account_number' => $result_account->get('number'),
456
                        'credit_account_number' => $capital_account->get('number'),
457
                        'amount' => abs(amountToForm($result_account->get('saldo'))), // amountToFrom necessary to get the correct format for daybook
458
                        'text' => $result_account->get('name') . ' nulstilles',
459
                        'vat_off' => 1
460
461
                    );
462
                    $debet_account = $result_account;
463
                    $credit_account = $capital_account;
464 1
                } elseif ($result_account->get('saldo') >= 0) {
465
                    $save_array = array(
466 1
                        'date' => $this->year->get('to_date_dk'),
467 1
                        'debet_account_number' => $capital_account->get('number'),
468 1
                        'credit_account_number' => $result_account->get('number'),
469 1
                        'amount' => abs(amountToForm($result_account->get('saldo'))), // amountToFrom necessary to get the correct format for daybook
470 1
                        'text' => $result_account->get('name') . ' nulstilles',
471
                        'vat_off' => 1
472 1
                    );
473 1
                    $debet_account = $capital_account;
474 1
                    $credit_account = $result_account;
475 1
                }
476
477 1 View Code Duplication
                if (!empty($save_array)) {
478 1
                    if ($voucher->saveInDayBook($save_array, true)) {
479
                        $this->saveStatedAction('result_account_reset', $voucher->get('id'), $debet_account->get('id'), $credit_account->get('id'), abs(amountToForm($result_account->get('saldo'))));
0 ignored issues
show
Bug introduced by
The variable $debet_account does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $credit_account does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
480
                    } else {
481 1
                        $voucher->error->view();
482
                    }
483 1
                }
484 1
                $this->setStated('result_account_reset', $voucher->get('id'));
485 1
                return true;
486
            break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
487 1
        }
488
    }
489
}
490