GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

AbstractTable   B
last analyzed

Complexity

Total Complexity 49

Size/Duplication

Total Lines 431
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 14

Importance

Changes 0
Metric Value
wmc 49
lcom 2
cbo 14
dl 0
loc 431
rs 8.48
c 0
b 0
f 0

25 Methods

Rating   Name   Duplication   Size   Complexity  
A isTableInit() 0 4 1
A setOptions() 0 9 2
A getParamAdapter() 0 4 1
A setParamAdapter() 0 14 3
A getData() 0 11 3
A getSource() 0 4 1
A setSource() 0 17 4
A getAdapter() 0 4 1
A setAdapter() 0 5 1
B render() 0 21 7
A initializable() 0 20 4
A initQuickSearch() 0 4 1
A initFilters() 0 4 1
A setHeaders() 0 9 2
A getHeaders() 0 4 1
A getHeader() 0 11 3
A addHeader() 0 6 1
A getRow() 0 7 2
A setRow() 0 5 1
A getRender() 0 7 2
A setRender() 0 4 1
A __toString() 0 4 1
A getOptions() 0 9 3
A getForm() 0 4 1
A getFilter() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like AbstractTable 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 AbstractTable, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * ZfTable ( Module for Zend Framework 2)
4
 *
5
 * @copyright Copyright (c) 2013 Piotr Duda [email protected]
6
 * @license   MIT License
7
 */
8
9
namespace ZfTable;
10
11
use ZfTable\Table\TableInterface;
12
use ZfTable\Params\AdapterInterface as ParamAdapterInterface;
13
use ZfTable\Params\AdapterArrayObject;
14
use ZfTable\Table\Exception;
15
use ZfTable\Options\ModuleOptions;
16
17
use ZfTable\Form\TableForm;
18
use ZfTable\Form\TableFilter;
19
20
abstract class AbstractTable extends AbstractElement implements TableInterface
21
{
22
23
    /**
24
     * Collection on headers objects
25
     * @var array
26
     */
27
    protected $headersObjects;
28
29
    /**
30
     * List of headers with title and width option
31
     * @var array
32
     */
33
    protected $headers;
34
35
    /**
36
     * Database adapter
37
     * @var \Zend\Db\Adapter\Adapter
38
     */
39
    protected $adapter;
40
41
    /**
42
     *
43
     * @var Source\SourceInterface
44
     */
45
    protected $source;
46
47
    /**
48
     *
49
     * @var Row
50
     */
51
    protected $row;
52
53
    /**
54
     * Data after execute of query
55
     * @var array | \Zend\Paginator\Paginator
56
     */
57
    protected $data;
58
59
    /**
60
     * Render object responsible for rendering
61
     * @var Render
62
     */
63
    protected $render;
64
65
    /**
66
     * Params adapter which responsible for universal mapping parameters from diffrent
67
     * source (default params, Data Table params, JGrid params)
68
     * @var ParamAdapterInterface
69
     */
70
    protected $paramAdapter;
71
72
    /**
73
     * Flag to know if table has been initializable
74
     * @var boolean
75
     */
76
    private $tableInit = false;
77
78
79
    /**
80
     * Default classes for table
81
     * @var array
82
     */
83
    protected $class = array('table', 'table-bordered', 'table-condensed', 'table-hover', 'table-striped', 'dataTable');
84
85
    /**
86
     * Array configuration of table
87
     * @var array
88
     */
89
    protected $config;
90
91
92
    /**
93
     * Options base ond ModuleOptions and config array
94
     * @var Options\ModuleOptions
95
     */
96
    protected $options = null;
97
98
99
    /**
100
     * Check if table has benn initializable
101
     * @return boolean
102
     */
103
    public function isTableInit()
104
    {
105
        return $this->tableInit;
106
    }
107
108
    /**
109
     * Set module options
110
     *
111
     * @param  array|\Traversable|ModuleOptions $options
112
     * @return AbstractTable
113
     */
114
    public function setOptions($options)
115
    {
116
        if (!$options instanceof ModuleOptions) {
117
            $options = new ModuleOptions($options);
118
        }
119
120
        $this->options = $options;
121
        return $this;
122
    }
123
124
    /**
125
     * Return Params adapter
126
     *
127
     * which responsible for universal mapping parameters from different
128
     * source (default params, Data Table params, JGrid params)
129
     *
130
     * @return ParamAdapterInterface
131
     */
132
    public function getParamAdapter()
133
    {
134
        return $this->paramAdapter;
135
    }
136
137
138
139
    /**
140
     *
141
     * @param $params
142
     * @throws Exception\InvalidArgumentException
143
     */
144
    public function setParamAdapter($params)
145
    {
146
        if ($params instanceof Params\AdapterInterface) {
147
            $this->paramAdapter = $params;
148
        } elseif ($params instanceof \Zend\Stdlib\Parameters) {
0 ignored issues
show
Bug introduced by
The class Zend\Stdlib\Parameters does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
149
            $this->paramAdapter = new AdapterArrayObject($params);
150
        } else {
151
            throw new Exception\InvalidArgumentException(
152
                'Parameter must be instance of AdapterInterface or \Zend\Stdlib\Parameters'
153
            );
154
        }
155
        $this->paramAdapter->setTable($this);
0 ignored issues
show
Bug introduced by
The method setTable does only exist in ZfTable\Params\AdapterArrayObject, but not in ZfTable\Params\AdapterInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
156
        $this->paramAdapter->init();
0 ignored issues
show
Bug introduced by
The method init does only exist in ZfTable\Params\AdapterArrayObject, but not in ZfTable\Params\AdapterInterface.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
157
    }
158
159
    /**
160
     *
161
     * @return array | \Zend\Paginator\Paginator
162
     * @throws Exception\LogicException
163
     */
164
    public function getData()
165
    {
166
        if (!$this->data) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->data of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
167
            $source = $this->getSource();
168
            if (!$source) {
169
                throw new Exception\LogicException('Source data is required');
170
            }
171
            return $source->getData();
172
        }
173
        return array();
174
    }
175
176
    /**
177
     *
178
     * @return Source\SourceInterface
179
     */
180
    public function getSource()
181
    {
182
        return $this->source;
183
    }
184
185
    /**
186
     *
187
     * @param \Zend\Db\Sql\Select |  $source
188
     * @return AbstractTable
189
     * @throws Exception\LogicException
190
     */
191
    public function setSource($source)
192
    {
193
194
        if ($source instanceof \Zend\Db\Sql\Select) {
0 ignored issues
show
Bug introduced by
The class Zend\Db\Sql\Select does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
195
            $source = new Source\SqlSelect($source);
196
        } elseif ($source instanceof \Doctrine\ORM\QueryBuilder) {
0 ignored issues
show
Bug introduced by
The class Doctrine\ORM\QueryBuilder does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
197
            $source = new Source\DoctrineQueryBuilder($source);
198
        } elseif (is_array($source)) {
199
            $source = new Source\ArrayAdapter($source);
0 ignored issues
show
Documentation introduced by
$source is of type array, but the function expects a object<ArrayObject>.

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...
200
        } else {
201
            throw new Exception\LogicException('This type of source is undefined');
202
        }
203
204
        $source->setTable($this);
205
        $this->source = $source;
206
        return $this;
207
    }
208
209
    /**
210
     * Get database adapter
211
     *
212
     * @return \Zend\Db\Adapter\Adapter
213
     */
214
    public function getAdapter()
215
    {
216
        return $this->adapter;
217
    }
218
219
    /**
220
     * Set database adapter
221
     *
222
     * @param \Zend\Db\Adapter\Adapter $adapter
223
     * @return $this
224
     */
225
    public function setAdapter($adapter)
226
    {
227
        $this->adapter = $adapter;
228
        return $this;
229
    }
230
231
    /**
232
     * Rendering table
233
     *
234
     * @param string $type (html | dataTableAjaxInit | dataTableJson)
235
     * @param null $template
236
     * @throws Exception\InvalidArgumentException
237
     * @return string
238
     */
239
    public function render($type = 'html', $template = null)
240
    {
241
        if (!$this->isTableInit()) {
242
            $this->initializable();
243
        }
244
245
        if ($type == 'html') {
246
            return $this->getRender()->renderTableAsHtml();
247
        } elseif ($type == 'dataTableAjaxInit') {
248
            return $this->getRender()->renderDataTableAjaxInit();
249
        } elseif ($type == 'dataTableJson') {
250
            return $this->getRender()->renderDataTableJson();
251
        } elseif ($type == 'custom') {
252
            return $this->getRender()->renderCustom($template);
253
        } elseif ($type == 'newDataTableJson') {
254
            return $this->getRender()->renderNewDataTableJson();
255
        } else {
256
            throw new Exception\InvalidArgumentException(sprintf('Invalid type %s', $type));
257
        }
258
259
    }
260
261
    /**
262
     * Init configuration like setting header, decorators, filters and others
263
     *
264
     * (call in render method as well)
265
     */
266
    protected function initializable()
267
    {
268
        if (!$this->getParamAdapter()) {
269
            throw new Exception\LogicException('Param Adapter is required');
270
        }
271
272
        if (!$this->getSource()) {
273
            throw new Exception\LogicException('Source data is required');
274
        }
275
276
        $this->init = true;
0 ignored issues
show
Bug introduced by
The property init does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
277
278
        if (count($this->headers)) {
279
            $this->setHeaders($this->headers);
280
        }
281
282
        $this->init();
283
284
        $this->initFilters($this->getSource()->getSource());
285
    }
286
287
288
    /**
289
     * @deprecated since version 2.0
290
     *
291
     * Function replace by initFilters
292
     */
293
    protected function initQuickSearch()
294
    {
295
296
    }
297
298
    /**
299
     * Init filters for quick search or filters for each column
300
     * @param \Zend\Db\Sql\Select $query
301
     */
302
    protected function initFilters($query)
303
    {
304
305
    }
306
307
    /**
308
     *
309
     * @param array $headers
310
     * @return $this
311
     */
312
    public function setHeaders(array $headers)
313
    {
314
        $this->headers = $headers;
315
        foreach ($headers as $name => $options) {
316
            $this->addHeader($name, $options);
317
        }
318
319
        return $this;
320
    }
321
322
    /**
323
     * Return array of headers
324
     *
325
     * @return array
326
     */
327
    public function getHeaders()
328
    {
329
        return $this->headers;
330
    }
331
332
    /**
333
     *
334
     * @param string $name type
335
     * @return Header | boolean
336
     * @throws Exception\LogicException
337
     */
338
    public function getHeader($name)
339
    {
340
        if (!count($this->headersObjects)) {
341
            throw new Exception\LogicException('Table hasn\'t got defined headers');
342
        }
343
344
        if (!isset($this->headersObjects[$name])) {
345
            throw new \RuntimeException('Header name doesnt exist');
346
        }
347
        return $this->headersObjects[$name];
348
    }
349
350
    /**
351
     * Add new header
352
     *
353
     * @param string $name
354
     * @param array $options
355
     */
356
    public function addHeader($name, $options)
357
    {
358
        $header = new Header($name, $options);
359
        $header->setTable($this);
360
        $this->headersObjects[$name] = $header;
361
    }
362
363
    /**
364
     * Get Row object
365
     *
366
     * @return Row
367
     */
368
    public function getRow()
369
    {
370
        if (!$this->row) {
371
            $this->row = new Row($this);
372
        }
373
        return $this->row;
374
    }
375
376
    /**
377
     * Set row object
378
     *
379
     * @param $row Row
380
     * @return $this
381
     */
382
    public function setRow($row)
383
    {
384
        $this->row = $row;
385
        return $this;
386
    }
387
388
    /**
389
     * Get Render object
390
     *
391
     * @return Render
392
     */
393
    public function getRender()
394
    {
395
        if (!$this->render) {
396
            $this->render = new Render($this);
397
        }
398
        return $this->render;
399
    }
400
401
    /**
402
     * Get render object
403
     * @param \ZfTable\Render $render
404
     */
405
    public function setRender(Render $render)
406
    {
407
        $this->render = $render;
408
    }
409
410
    /**
411
     * Rendering table
412
     */
413
    public function __toString()
414
    {
415
        return $this->render();
416
    }
417
418
    /**
419
     *
420
     * @return ModuleOptions
421
     * @throws \Exception
422
     */
423
    public function getOptions()
424
    {
425
        if (is_array($this->config)) {
426
            $this->config = new ModuleOptions($this->config);
0 ignored issues
show
Documentation Bug introduced by
It seems like new \ZfTable\Options\ModuleOptions($this->config) of type object<ZfTable\Options\ModuleOptions> is incompatible with the declared type array of property $config.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
427
        } elseif (!$this->config instanceof  ModuleOptions) {
428
            throw new \Exception('Config class problem');
429
        }
430
        return $this->config;
431
    }
432
433
    /**
434
     *
435
     * @return TableForm
436
     */
437
    public function getForm()
438
    {
439
        return new TableForm(array_keys($this->headers));
440
    }
441
442
    /**
443
     *
444
     * @return TableFilter
445
     */
446
    public function getFilter()
447
    {
448
        return new TableFilter(array_keys($this->headers));
449
    }
450
}
451