Completed
Push — master ( 9d10c2...bf46e5 )
by Lars
05:14
created

Intraface_modules_modulepackage_Manager::upgrade()   C

Complexity

Conditions 11
Paths 11

Size

Total Lines 78
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 2
Bugs 2 Features 0
Metric Value
c 2
b 2
f 0
dl 0
loc 78
rs 5.3526
ccs 0
cts 57
cp 0
cc 11
eloc 48
nc 11
nop 2
crap 132

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Class to manage which ModulePackages an intranet has.
4
 * Should this class be called Intraface_IntranetModulePackage as this is actually what it is.
5
 *
6
 * @package Intraface_modules_modulepackage
7
 * @author sune
8
 * @version 0.0.1
9
 */
10
class Intraface_modules_modulepackage_Manager extends Intraface_Standard
11
{
12
13
    /**
14
     * @var object intranet
15
     */
16
    public $intranet;
17
18
    /**
19
     * @var object db
20
     */
21
    private $db;
22
23
    /**
24
     * @var object error
25
     */
26
    public $error;
27
28
    /**
29
     * @var object dbquery
30
     */
31
    private $dbquery;
32
33
    /**
34
     * @var integer id on intranet module package
35
     */
36
    private $id;
37
38
    /**
39
     * Constructor
40
     *
41
     * @param object intranet intranet object
42
     * @param integer id for intranet module package
43
     *
44
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

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

Please refer to the PHP core documentation on constructors.

Loading history...
45
     */
46 View Code Duplication
    public function __construct($intranet, $id = 0)
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...
47
    {
48
        // Should we rather just take intranet_id as parameter?
49
        $this->intranet = &$intranet;
50
        $this->db = MDB2::singleton(DB_DSN);
51
        $this->error =  new Intraface_Error;
52
        $this->id = (int)$id;
53
54
        if ($this->id > 0) {
55
            $this->load();
56
        }
57
    }
58
59
    /**
60
     * Loads information about intranet module package
61
     *
62
     * @return integer id
63
     */
64
    private function load()
65
    {
66
67
        if ($this->id == 0) {
68
            return false;
69
        }
70
71
        // TODO: This could actually easily use dbquery
72
        $result = $this->db->query('SELECT intranet_module_package.id, ' .
73
                'intranet_module_package.module_package_id, ' .
74
                'intranet_module_package.start_date, ' .
75
                'intranet_module_package.end_date, ' .
76
                'intranet_module_package.order_debtor_id, ' .
77
                'intranet_module_package.status_key, ' .
78
                'module_package_plan.plan, ' .
79
                'module_package_group.group_name, ' .
80
                'DATE_FORMAT(intranet_module_package.start_date, "%d-%m-%Y") AS dk_start_date, ' .
81
                'DATE_FORMAT(intranet_module_package.end_date, "%d-%m-%Y") AS dk_end_date ' .
82
            'FROM intranet_module_package ' .
83
            'INNER JOIN module_package ON intranet_module_package.module_package_id = module_package.id ' .
84
            'INNER JOIN module_package_plan ON module_package.module_package_plan_id = module_package_plan.id ' .
85
            'INNER JOIN module_package_group ON module_package.module_package_group_id = module_package_group.id ' .
86
            'WHERE intranet_id = '.$this->db->quote($this->intranet->get('id'), 'integer').' AND intranet_module_package.id = '.$this->db->quote($this->id, 'integer'));
87
88
        if (PEAR::isError($result)) {
89
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->load() :".$result->getUserInfo());
90
        }
91
92
        if ($row = $result->fetchRow()) {
93
            $status_types = $this->getStatusTypes();
94
            $row['status'] = $status_types[$row['status_key']];
95
            $this->value = $row;
96
            return $this->id;
97
        }
98
    }
99
100
    /**
101
     * Creates db query
102
     *
103
     * @param object kernel
104
     *
105
     * @return void
106
     */
107
    public function getDBQuery($kernel = null)
108
    {
109
        if ($this->dbquery) {
110
            return $this->dbquery;
111
        }
112
        if ($kernel == null) {
113
            throw new Exception('You need to provide kernel the first time you are calling getDBQuery');
114
        }
115
        $this->dbquery = new Intraface_DBQuery($kernel, 'intranet_module_package', 'intranet_module_package.active = 1 AND intranet_module_package.intranet_id = '.$this->intranet->get('id'));
116
        $this->dbquery->setJoin('INNER', 'module_package', 'intranet_module_package.module_package_id = module_package.id', '');
117
        $this->dbquery->setJoin('INNER', 'module_package_group', 'module_package.module_package_group_id = module_package_group.id', '');
118
        $this->dbquery->setJoin('INNER', 'module_package_plan', 'module_package.module_package_plan_id = module_package_plan.id', '');
119
        return $this->dbquery;
120
    }
121
122
    /**
123
     * Add a package to an intranet
124
     * This function should maybe have been a part of intranet class, e.g. $intranet->addModulePackage, but how do we get that to work.
125
     *
126
     * @param integer package_id id on modulepackage
127
     * @param string start_date The start date of the package in the pattern dd-mm-yyyy
128
     * @param string duration The duration as either date 'dd-mm-yyyy' or 'yyyy-mm-dd' or a 'X month' where X can be any whole number
129
     *
130
     * @return integer id on intranet module package
131
     */
132
    public function save($package_id, $start_date, $duration)
133
    {
134
        $modulepackage = new Intraface_modules_modulepackage_ModulePackage(intval($package_id));
135
136
        if ($modulepackage->get('id') == 0) {
137
            $this->error->set('Invalid module package in');
138
        }
139
140
        $validator = new Intraface_Validator($this->error);
141
142
        if (!$validator->isDate($start_date, 'Invalid start date')) {
143
            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 Intraface_modules_modulepackage_Manager::save 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...
144
        } else {
145
            $start_date = new Intraface_Date($start_date);
146
            $start_date->convert2db();
147
            $start_date = $start_date->get();
148
        }
149
150
        $parsed_duration = $this->parseDuration($start_date, $duration);
151
        $end_date = $parsed_duration['end_date'];
152
153
        // We make sure that it is not possible to add a package before existing is finished.
154
        if (strtotime($this->getLastEndDateInGroup($modulepackage)) >= strtotime($start_date)) {
155
            $this->error->set('you are trying to add a package in a group before the existing package is finished');
156
            throw new Exception('you are trying to add a package in a group before the existing package is finished');
157
            return false;
0 ignored issues
show
Unused Code introduced by
return false; 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...
158
        }
159
160
        if ($this->error->isError()) {
161
            return false;
162
        }
163
164
        $sql = "module_package_id = ".$this->db->quote($modulepackage->get('id'), 'integer').", " .
165
                "start_date = ".$this->db->quote($start_date, 'date').", " .
166
                "end_date = ".$this->db->quote($end_date, 'date');
167
168
        $result = $this->db->exec("INSERT INTO intranet_module_package SET ".$sql.", status_key = 1, active = 1, intranet_id = ".$this->intranet->get('id'));
169
        if (PEAR::isError($result)) {
170
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->save from result: ".$result->getUserInfo());
171
        }
172
173
        $id = $this->db->lastInsertID();
174
        if (PEAR::isError($id)) {
175
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->save from id: ".$id->getUserInfo());
176
        }
177
        $this->id = $id;
178
        return $this->id;
179
180
    }
181
182
    /**
183
     * Attach an order id to an intranet module package
184
     *
185
     * @param integer order_id Id on the order created as a part of adding the package
186
     *
187
     * @return mixed Number of affected rows or false on error
188
     */
189
    public function addOrderIdentifier($order_identifier)
190
    {
191
192
        if ($order_identifier != '') {
193
            return false;
194
        }
195
196
        if ($this->id == 0) {
197
            return false;
198
        }
199
200
        $result = $this->db->exec('UPDATE intranet_module_package ' .
201
            'SET order_debtor_identifier = '.$this->db->quote($order_identifier, 'text').' ' .
202
            'WHERE intranet_id = '.$this->db->quote($this->intranet->get('id'), 'integer').' AND id = '.$this->db->quote($this->id, 'integer'));
203
204
        if (PEAR::isError($result)) {
205
            throw new Exception('Error in query:'.$result->getUserInfo());
206
        }
207
208
        return $result;
209
    }
210
211
    /**
212
     * Set an intranet module package to be terminated
213
     *
214
     * @return boolean true or false
215
     */
216 View Code Duplication
    public function terminate()
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...
217
    {
218
        if ($this->id == 0) {
219
            return false;
220
        }
221
222
        $result = $this->db->exec("UPDATE intranet_module_package SET status_key = 3 WHERE intranet_id = ".$this->intranet->get('id')." AND id = ".intval($this->id));
223
        if (PEAR::isError($result)) {
224
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->terminate :". $result->getUserInfo());
225
        }
226
227
        return $result;
228
    }
229
230
    /**
231
     * Delete an intranet module package
232
     *
233
     * @return boolean true or false
234
     */
235 View Code Duplication
    public function delete()
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...
236
    {
237
        if ($this->id == 0) {
238
            return false;
239
        }
240
        $result = $this->db->exec("UPDATE intranet_module_package SET active = 0 WHERE intranet_id = ".$this->intranet->get('id')." AND id = ".intval($this->id));
241
        if (PEAR::isError($result)) {
242
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->delete :". $result->getUserInfo());
243
        }
244
245
        return $result;
246
    }
247
248
    /**
249
     * Returns on the basis of the module package which type of add this is. Can be either add, extend, or upgrade
250
     *
251
     * @param object modulepackage An modulepackage object
252
     *
253
     * @return string either 'add', 'extend' or 'upgrade'
254
     */
255
    public function getAddType($modulepackage)
256
    {
257
        if (!is_object($modulepackage) || strtolower(get_class($modulepackage)) != 'intraface_modules_modulepackage_modulepackage') {
258
            throw new Exception("Intraface_modules_modulepackage_Manager->getAddType needs object Intraface_modules_modulepackage_ModulePackage as first parameter");
259
        }
260
261
        if ($modulepackage->get('id') == 0) {
262
            throw new Exception('module package id is not valid in Intraface_modules_modulepackage_Manager->getAddType');
263
        }
264
265
        // TODO: If DBQuery had not needed kernel we could have used it here!
266
        $result = $this->db->query('SELECT module_package_plan.plan_index FROM intranet_module_package ' .
267
                'INNER JOIN module_package ON intranet_module_package.module_package_id = module_package.id ' .
268
                'INNER JOIN module_package_plan ON module_package.module_package_plan_id = module_package_plan.id ' .
269
                'WHERE intranet_module_package.intranet_id = '.$this->intranet->get('id').' AND intranet_module_package.active = 1 AND (intranet_module_package.status_key = 1 OR intranet_module_package.status_key = 2) AND module_package.module_package_group_id = '.$modulepackage->get('group_id').' ' .
270
                'ORDER BY end_date DESC');
271
272
        if (PEAR::isError($result)) {
273
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->getAddType: ".$result->getUserInfo());
274
        }
275
276
        if ($row = $result->fetchRow()) {
277
            if ($modulepackage->get('plan_index') > $row['plan_index']) {
278
                return 'upgrade';
279
            } else {
280
                return 'extend';
281
            }
282
        } else {
283
            return 'add';
284
        }
285
    }
286
287
    /**
288
     * Returns the end date of the last modulepacke in a given group
289
     *
290
     * @param object modulepackage
291
     */
292
    public function getLastEndDateInGroup($modulepackage)
293
    {
294
295
        if (!is_object($modulepackage) || strtolower(get_class($modulepackage)) != 'intraface_modules_modulepackage_modulepackage') {
296
            throw new Exception("Intraface_modules_modulepackage_Manager->getLastEndDateInGroup needs object Intraface_modules_modulepackage as Parameter");
297
        }
298
299
        if ($modulepackage->get('id') == 0) {
300
            throw new Exception('module package id is not valid in Intraface_modules_modulepackage_Manager->getLastEndDateInGroup');
301
        }
302
303
        // TODO: If DBQuery had not needed kernel we could have used it here!
304
        $result = $this->db->query('SELECT intranet_module_package.end_date FROM intranet_module_package ' .
305
                'INNER JOIN module_package ON intranet_module_package.module_package_id = module_package.id ' .
306
                'INNER JOIN module_package_plan ON module_package.module_package_plan_id = module_package_plan.id ' .
307
                'WHERE intranet_module_package.intranet_id = '.$this->intranet->get('id').' AND intranet_module_package.active = 1 AND (intranet_module_package.status_key = 1 OR intranet_module_package.status_key = 2) AND module_package.module_package_group_id = '.$modulepackage->get('group_id').' ' .
308
                'ORDER BY end_date DESC');
309
310
        if (PEAR::isError($result)) {
311
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->getLastEndDateInGroup: ".$result->getUserInfo());
312
        }
313
314
        if ($row = $result->fetchRow()) {
315
            return $row['end_date'];
316
        } else {
317
            // yesterday!
318
            return date('Y-m-d', strtotime('-1 day', time()));
319
        }
320
    }
321
322
    /**
323
     * By providing a start date and a duration it returns an end date and a number of month
324
     *
325
     * @param string start_date the start date of the periode yyyy-mm-dd
326
     * @param string duration the duration as either an end date yyyy-mm-dd or dd-mm-yyyy or 'X month' where X can be any whole number
327
     *
328
     * @return array array containing end_date and month
329
     */
330
    private function parseDuration($start_date, $duration)
331
    {
332
333
        // first we check for danish format of duration
334
        if (ereg('^[0-9]{2}-[0-9]{2}-[0-9]{4}$', $duration)) {
0 ignored issues
show
Deprecated Code introduced by
The function ereg() has been deprecated with message: Deprecated as of PHP 5.3.0. Relying on this feature is highly discouraged (use preg_match() instead).

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
335
            $validator = new Intraface_Validator($this->error);
336
            if ($validator->isDate($duration, 'Invalid end date')) {
337
                $end_date = new Intraface_Date($duration);
338
                $end_date->convert2db();
339
                $duration = $end_date->get();
340
            }
341
        }
342
343
        if (ereg('^[0-9]{4}-[0-9]{2}-[0-9]{2}$', $duration)) {
0 ignored issues
show
Deprecated Code introduced by
The function ereg() has been deprecated with message: Deprecated as of PHP 5.3.0. Relying on this feature is highly discouraged (use preg_match() instead).

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
344
            // firsts we translate the duration into an integer
345
            $end_date_integer = strtotime($duration);
346
            $start_date_integer = strtotime($start_date);
347
348
            // then we find the number of month left.
349
            $month = 0;
350
            // first we add a month to see if there is a full month left.
351
            // If we want to give them this month for free this should be removed.
352
            $running_start_date_integer = strtotime('+1 month', $start_date_integer);
353
            while ($running_start_date_integer <= $end_date_integer) {
354
                $running_start_date_integer = strtotime('+1 month', $running_start_date_integer);
355
                $month++;
356
            }
357
358
            return array('end_date' => $duration,
359
                'month' => $month);
360
        } elseif (ereg('^([0-9]{1,2}) month$', $duration, $params)) {
0 ignored issues
show
Deprecated Code introduced by
The function ereg() has been deprecated with message: Deprecated as of PHP 5.3.0. Relying on this feature is highly discouraged (use preg_match() instead).

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
361
            if (intval($params[1]) == 0) {
362
                $this->error->set('The duration in month should be higher than zero.');
363
            }
364
365
            /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% 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...
366
            // The nice an easy way, but first from  PHP5.2
367
            $end_date = new DateTime($start_date->get());
368
            $end_date->modify('+'.intval($params[1]).' month');
369
            // $end_date->format('d-m-Y')
370
            */
371
372
            $end_date_integer = strtotime('+'.intval($params[1]).' month', strtotime($start_date));
373
374
            $end_date = new Intraface_Date(date('d-m-Y', $end_date_integer));
375
            $end_date->convert2db();
376
377
            return array('end_date' => $end_date->get(),
378
                'month' => $params[1]);
379
        } else {
380
            $this->error->set('Duration does not have a valid pattern in Intraface_modules_modulepackage_Manager->parseDuration');
381
            return array();
382
        }
383
    }
384
385
    /**
386
     * Adds a module package if there is no one already in the group
387
     *
388
     * @param object modulepackage module package
389
     * @param string duration Duration as either date 'dd-mm-yyyy' or 'yyyy-mm-dd' or 'X month' where X is any whole number
390
     *
391
     * @return object Action object with the actions needed to be processed
392
     */
393
    public function add($modulepackage, $duration)
394
    {
395
        if (!is_object($modulepackage) || strtolower(get_class($modulepackage)) != 'intraface_modules_modulepackage_modulepackage') {
396
            throw new Exception('Intraface_modules_modulepackage_Manager->add needs object Intraface_modules_modulepackage_ModulePackage as Parameter');
397
        }
398
399
        if ($modulepackage->get('id') == 0) {
400
            throw new Exception('module package id is not valid in Intraface_modules_modulepackage_Manager->add');
401
        }
402
403
        // extends makes the same process
404
        return $this->extend($modulepackage, $duration);
405
    }
406
407
    /**
408
     * Extends with the given module package if there is already a module packe in the group
409
     *
410
     * @param object modulepackage
411
     * @param string duration Duration as either date 'dd-mm-yyyy' or 'yyyy-mm-dd' or 'X month' where X is any whole number
412
     *
413
     * @return object Action object with the actions needed to be performed
414
     */
415
    public function extend($modulepackage, $duration)
416
    {
417
        if (!is_object($modulepackage) || strtolower(get_class($modulepackage)) != 'intraface_modules_modulepackage_modulepackage') {
418
            throw new Exception('Intraface_modules_modulepackage_Manager->extend needs object Intraface_modules_modulepackage_ModulePackage as Parameter');
419
        }
420
421
        if ($modulepackage->get('id') == 0) {
422
            throw new Exception('module package id is not valid in Intraface_modules_modulepackage_Manager->extend');
423
        }
424
425
426
        $start_date = date('Y-m-d', strtotime('+1 day', strtotime($this->getLastEndDateInGroup($modulepackage))));
427
        $parsed_duration = $this->parseDuration($start_date, $duration);
428
        $end_date = $parsed_duration['end_date'];
429
        $month = $parsed_duration['month'];
430
431
        if ($this->error->isError()) {
432
            return array();
433
        }
434
435
        require_once('Intraface/modules/modulepackage/Action.php');
436
        $action = new Intraface_modules_modulepackage_Action;
437
438
        $action->addAction(array(
0 ignored issues
show
Documentation introduced by
array('action' => 'add',...ate, 'month' => $month) is of type array<string,?,{"action"...date":"?","month":"?"}>, but the function expects a object<action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
439
            'action' => 'add',
440
            'module_package_id' => $modulepackage->get('id'),
441
            'product_id' => $modulepackage->get('product_id'),
442
            'start_date' => $start_date,
443
            'end_date' => $end_date,
444
            'month' => $month));
445
446
447
        return $action;
448
449
    }
450
451
    /**
452
     * Upgrades to the given module package if there is already a module packe in the group
453
     *
454
     * @param object modulepackage
455
     * @param string duration Duration as either date 'dd-mm-yyyy' or 'yyyy-mm-dd' or 'X month' where X is any whole number
456
     *
457
     * @return object Action object with the actions needed to be performed
458
     */
459
    public function upgrade($modulepackage, $duration)
460
    {
461
        if (!is_object($modulepackage) || strtolower(get_class($modulepackage)) != 'intraface_modules_modulepackage_modulepackage') {
462
            throw new Exception('Intraface_modules_modulepackage_Manager->upgrade needs object Intraface_modules_modulepackage as Parameter');
463
        }
464
465
        if ($modulepackage->get('id') == 0) {
466
            throw new Exception('module package id is not valid in Intraface_modules_modulepackage_Manager->upgrade');
467
        }
468
469
        $start_date = date('Y-m-d');
470
        $parsed_duration = $this->parseDuration($start_date, $duration);
471
472
        if ($this->error->isError()) {
473
            return array();
474
        }
475
476
        require_once('Intraface/modules/modulepackage/Action.php');
477
        $action = new Intraface_modules_modulepackage_Action;
478
479
        require_once('Intraface/modules/modulepackage/ShopExtension.php');
480
        $shop = new Intraface_modules_modulepackage_ShopExtension;
481
482
        // TODO: If DBQuery had not needed kernel we could have used it here!
483
        $result = $this->db->query('SELECT intranet_module_package.id, intranet_module_package.status_key, intranet_module_package.start_date, intranet_module_package.end_date, intranet_module_package.order_debtor_id, intranet_module_package.module_package_id, module_package.product_id ' .
484
                'FROM intranet_module_package ' .
485
                'INNER JOIN module_package ON intranet_module_package.module_package_id = module_package.id ' .
486
                'INNER JOIN module_package_plan ON module_package.module_package_plan_id = module_package_plan.id ' .
487
                'WHERE intranet_module_package.intranet_id = '.$this->intranet->get('id').' AND intranet_module_package.active = 1 AND (intranet_module_package.status_key = 1 OR intranet_module_package.status_key = 2) AND module_package.module_package_group_id = '.$modulepackage->get('group_id').' ' .
488
                'ORDER BY end_date DESC');
489
490
        if (PEAR::isError($result)) {
491
            throw new Exception("Error in query in Intraface_modules_modulepackage_Manager->upgrade: ".$result->getUserInfo());
492
        }
493
494
        while ($row = $result->fetchRow()) {
495
            $add_action = array();
496
497
            if ($row['status_key'] == 1) { // 'created'
498
                $add_action['action'] = 'delete';
499
                // the whole package is left, we substract the whole package.
500
                // the start date as integer
501
                $remaining_start_date = $row['start_date'];
502
            } elseif ($row['status_key'] == 2) { // 'active'
503
                $add_action['action'] = 'terminate';
504
                // the package is in use. We substract from today
505
                // the start date as integer
506
                $remaining_start_date = date('Y-m-d');
507
            }
508
509
            $remaining = $this->parseDuration($remaining_start_date, $row['end_date']);
0 ignored issues
show
Bug introduced by
The variable $remaining_start_date 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...
510
            $add_action['month'] = $remaining['month'];
511
            $add_action['order_debtor_id'] = $row['order_debtor_id'];
512
            $add_action['intranet_module_package_id'] = $row['id'];
513
514
            if ($row['order_debtor_id'] != 0 && $modulepackage->get('product_id') != 0) {
515
                $product = $shop->getProductDetailFromExistingOrder($row['order_debtor_id'], $row['product_id']);
516
                $add_action['product_detail_id'] = $product['product_detail_id'];
517
                $add_action['product_id'] = $row['product_id'];
518
            } else {
519
                $add_action['product_detail_id'] = 0;
520
                $add_action['product_id'] = 0;
521
            }
522
523
            $action->addAction($add_action);
0 ignored issues
show
Documentation introduced by
$add_action is of type array<string,?,{"product_id":"?"}>, but the function expects a object<action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
524
        }
525
526
527
        // we add the add package action
528
        $action->addAction(array('action' => 'add',
0 ignored issues
show
Documentation introduced by
array('action' => 'add',...rsed_duration['month']) is of type array<string,?,{"action"...date":"?","month":"?"}>, but the function expects a object<action>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
529
            'module_package_id' => $modulepackage->get('id'),
530
            'product_id' => $modulepackage->get('product_id'),
531
            'start_date' => $start_date,
532
            'end_date' => $parsed_duration['end_date'],
533
            'month' => $parsed_duration['month']));
534
535
        return $action;
536
    }
537
538
    /**
539
     * Returns an array of the packages that an intranet has.
540
     * This can be modified with dbquery
541
     *
542
     * @return array Array with the modulepackages
543
     */
544
    public function getList()
545
    {
546
        if (!isset($this->dbquery) || !is_object($this->dbquery)) {
547
            throw new Exception("DBQuery needs to be initiated before use of getList in Intraface_modules_modulepackage_Manager->getList");
548
        }
549
550
        if ($this->dbquery->checkFilter('status')) {
551
            if ($this->dbquery->getFilter('status') == 'created_and_active') {
552
                $this->dbquery->setCondition('status_key = 1 OR status_key = 2');
553
            } elseif ($this->dbquery->getFilter('status') == 'active') {
554
                $this->dbquery->setCondition('status_key = 2');
555
            }
556
        }
557
558
        if ($this->dbquery->checkFilter('group_id')) {
559
            $this->dbquery->setCondition('module_package_group.id = '.(int)$this->dbquery->getFilter('group_id'));
560
        }
561
562
        if ($this->dbquery->checkFilter('sorting')) {
563
            if ($this->dbquery->getFilter('sorting') == 'end_date') {
564
                $this->dbquery->setSorting('intranet_module_package.end_date');
565
            }
566
        } else {
567
            $this->dbquery->setSorting('module_package_group.sorting_index, module_package_plan.plan_index, intranet_module_package.start_date');
568
        }
569
570
        $db = $this->dbquery->getRecordset('intranet_module_package.id, ' .
571
                    'intranet_module_package.module_package_id, ' .
572
                    'intranet_module_package.start_date, ' .
573
                    'intranet_module_package.end_date, ' .
574
                    'intranet_module_package.order_debtor_id, ' .
575
                    'intranet_module_package.status_key, ' .
576
                    'module_package_plan.plan, ' .
577
                    'module_package_group.group_name, ' .
578
                    'DATE_FORMAT(intranet_module_package.start_date, "%d-%m-%Y") AS dk_start_date, ' .
579
                    'DATE_FORMAT(intranet_module_package.end_date, "%d-%m-%Y") AS dk_end_date', '', false);
580
581
        $modulepackages = array();
582
        $i = 0;
583
584
        $status_types = $this->getStatusTypes();
585
        while ($db->nextRecord()) {
586
            $modulepackages[$i]['id'] = $db->f('id');
587
            $modulepackages[$i]['module_package_id'] = $db->f('module_package_id');
588
            $modulepackages[$i]['start_date'] = $db->f('start_date');
589
            $modulepackages[$i]['dk_start_date'] = $db->f('dk_start_date');
590
            $modulepackages[$i]['end_date'] = $db->f('end_date');
591
            $modulepackages[$i]['dk_end_date'] = $db->f('dk_end_date');
592
            $modulepackages[$i]['order_debtor_id'] = $db->f('order_debtor_id');
593
            $modulepackages[$i]['status_key'] = $db->f('status_key');
594
            $modulepackages[$i]['status'] = $status_types[$db->f('status_key')];
595
            $modulepackages[$i]['plan'] = $db->f('plan');
596
            $modulepackages[$i]['group'] = $db->f('group_name');
597
            $i++;
598
        }
599
600
        return $modulepackages;
601
    }
602
603
    /**
604
     * Returns the possible types of status'
605
     *
606
     * @return array status types
607
     */
608
    public static function getStatusTypes()
609
    {
610
        return array(0 => '_invalid_',
611
            1 => 'created',
612
            2 => 'active',
613
            3 => 'terminate',
614
            4 => 'used');
615
    }
616
}
617