Passed
Push — master ( 700b0f...aafb0a )
by Björn
18:25 queued 10s
created

Table::__invoke()   F

Complexity

Conditions 23
Paths 2304

Size

Total Lines 49

Duplication

Lines 31
Ratio 63.27 %

Importance

Changes 0
Metric Value
dl 31
loc 49
rs 0
c 0
b 0
f 0
cc 23
nc 2304
nop 2

How to fix   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
 * BB's Zend Framework 2 Components
4
 * 
5
 * UI Components
6
 *
7
 * @package     [MyApplication]
8
 * @subpackage  BB's Zend Framework 2 Components
9
 * @subpackage  UI Components
10
 * @author      Björn Bartels <[email protected]>
11
 * @link        https://gitlab.bjoernbartels.earth/groups/zf2
12
 * @license     http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
13
 * @copyright   copyright (c) 2016 Björn Bartels <[email protected]>
14
 */
15
16
namespace UIComponents\View\Helper\Components;
17
18
use UIComponents\Template\Template;
19
20
/**
21
 *
22
 * render a (simple) HTML table
23
 *
24
 */
25
class Table extends Element 
26
{
27
    /** @var \UIComponents\Template\Template $template */
28
	public $template = null;
29
30
	/** @var array $data */
31
	public $data = array();
32
33
	/** @var array $options */
34
	public $options = array();
35
36
	/** @var array $tags */
37
	public $tags = array(
38
		"container" =>	"table",
39
		"row"		=>	"tr",
40
		"cell"		=>	"td",
41
		"headcell"	=>	"th"
42
	);
43
	
44
	/**
45
     * View helper entry point:
46
     * Retrieves helper and optionally sets component options to operate on
47
     *
48
     * @param  array|StdClass $config table configuration to operate on
49
     * @param  array|StdClass $options [optional] component options to operate on
50
     * @return self
51
     */
52
    public function __invoke($config = array(), $options = array())
53
    {
54 View Code Duplication
        if ( is_object($options) && method_exists($options, 'toArray') ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
55
            $options = $options->toArray();
56
        } else if ( is_object($options) ) {
57
            $options = (array)$options;
58
        }
59
        
60 View Code Duplication
        if ( is_object($config) && method_exists($config, 'toArray') ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
61
            $config = $config->toArray();
62
        } else if ( is_object($options) ) {
63
            $config = (array)$config;
64
        }
65
        
66
        $this->setOptions($config);
67
        
68
        if (isset($options['container']) && (null !== $options['container'])) {
69
            $this->setContainer($options['container']);
70
        }
71
    
72 View Code Duplication
        if (isset($options['tagname']) && (null !== $options['tagname'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
73
            $this->setTagname($options['tagname']);
74
        }
75 View Code Duplication
        if (isset($options['class']) && (null !== $options['class'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
76
            $this->setClassnames($options['class']);
77
        }
78 View Code Duplication
        if (isset($options['classnames']) && (null !== $options['classnames'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
79
            $this->setClassnames($options['classnames']);
80
        }
81
82 View Code Duplication
        if (isset($options['attr']) && (null !== $options['attr'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
83
            $this->setAttributes($options['attr']);
84
        }
85 View Code Duplication
        if (isset($options['attributes']) && (null !== $options['attributes'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
86
            $this->setAttributes($options['attributes']);
87
        }
88
89 View Code Duplication
        if (isset($options['content']) && (null !== $options['content'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
90
            $this->setContent($options['content']);
91
        }
92 View Code Duplication
        if (isset($options['children']) && (null !== $options['children'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
93
            $this->setContent($options['children']);
94
        }
95
        
96
        $this->tags = (object)$this->tags;
97
        
98
        $component = clone $this;
99
        return $component;
100
    }
101
102
    /**
103
     * generate framework classnames collection as zend-config object
104
     * 
105
     * @return string
106
     */
107
    public function render()
108
    {
109
    	return $this->buildMarkup();
110
    }
111
    
112
	/**
113
	 * generate table header HTML
114
	 * @param mixed $aHTMLTableColumns
115
	 * @return self
116
	 */
117
	public function buildHeaderCells ($aHTMLTableColumns) {
118
		$sHTMLTableHeader = "";
119
		$sHTMLTableColumnGroup = "";
120
		$aColumns = array();
121
		foreach ((array)$aHTMLTableColumns as $iColumn => $aColumn) {
122
			if ($aColumn["field"]) {
123
				$aColumns[] = $aColumn["field"];
124
				$sHTMLTableHeader .= "<".$this->tags->headcell." class=\"".$aColumn["field"]."\">".$aColumn["title"]."</".$this->tags->headcell.">";
125
				$sHTMLTableColumnGroup .= "<column class=\"".$aColumn["field"]."\" />";
126
			} else {
127
				$sHTMLTableHeader .= "<".$this->tags->headcell." class=\"col_".$iColumn."\">".$aColumn["title"]."</".$this->tags->headcell.">";
128
				$sHTMLTableColumnGroup .= "<column class=\"col_".$iColumn."\" />";
129
			}
130
		}
131
		$this->getTemplate()->set('s', 'HEADERCELLS', $sHTMLTableHeader);
132
		$this->getTemplate()->set('s', 'COLUMNGROUP', "<columns>".$sHTMLTableColumnGroup."</columns>");
133
		return ($this);
134
	}
135
		
136
	/**
137
	 * generate table footer HTML
138
	 * @param mixed $aHTMLTableColumns
139
	 * @return self
140
	 */
141
	public function buildFooterCells ($aHTMLTableColumns) {
142
		$sHTMLTableFooter = "";
143
		$aColumns = array();
144
		foreach ((array)$aHTMLTableColumns as $iColumn => $aColumn) {
145
			if ($aColumn["field"]) {
146
				$aColumns[] = $aColumn["field"];
147
				$sHTMLTableFooter .= "<".$this->tags->cell." class=\"".$aColumn["field"]."\">".$aColumn["title"]."</".$this->tags->cell.">";
148
			} else {
149
				$sHTMLTableFooter .= "<".$this->tags->cell." class=\"col_".$iColumn."\">".$aColumn["title"]."</".$this->tags->cell.">";
150
			}
151
		}
152
		$this->getTemplate()->set('s', 'FOOTERCELLS', $sHTMLTableFooter);
153
		return ($this);
154
	}
155
	
156
	/**
157
	 * generate table body HTML
158
	 * @param array $aRowData
159
	 * @param mixed $aHTMLTableColumns
160
	 * @return array
161
	 */
162
	public function buildBodyCells ($aRowData, $aHTMLTableColumns) {
163
		$aRows = array();
164
		foreach ( (array)$aRowData as $iRow => $oRowData ) {
165
			$sCells = "";
166
			foreach ((array)$aHTMLTableColumns as $iColumn => $aColumn) {
167
				$mCellValue = $oRowData[$aColumn["field"]];
168
				if (!empty($aColumn["callback"]) && function_exists($aColumn["callback"])) {
169
					$mCellValue = call_user_func($aColumn["callback"], $oRowData, $aColumn, $iColumn, $iRow);
170
				}
171
				if ( isset($aColumn["field"]) && isset($oRowData[$aColumn["field"]]) ) {
172
					$sClassname = $aColumn["field"];
173
				} else {
174
					$sClassname = "col_".$iColumn;
175
				}
176
				$sCells .= "<".$this->tags->cell." class=\"".$sClassname."\">".
177
					$mCellValue.
178
				"</".$this->tags->cell.">";
179
			}
180
			
181
			$aRows[] = $sCells;
182
		}
183
		
184
		foreach ($aRows as $iRow => $sRow) {
185
			$this->getTemplate()->set('d', 'ROWID', "row_".$aRowData[$iRow]["productID"]);
186
			$this->getTemplate()->set('d', 'BODYCELLS', $sRow);
187
			if (($iRow % 2) == 0) {
188
				$this->getTemplate()->set('d', 'CSS_CLASS', 'even');
189
			} else {
190
				$this->getTemplate()->set('d', 'CSS_CLASS', 'odd');
191
			}
192
			$this->getTemplate()->next();
193
		
194
		}
195
	}
196
	
197
	/**
198
	 * generate mini table mark-up template
199
	 * @return string
200
	 */
201
	public function buildMarkupTemplate () {
202
		$aHTML = array(
203
			"<".$this->tags->container.">",
204
				"<".$this->tags->row.">",
205
					"{HEADERCELLS}",
206
				"</".$this->tags->row.">",
207
					"<!-- BEGIN:BLOCK -->",
208
						"<".$this->tags->row.">",
209
							"{BODYCELLS}",
210
						"</".$this->tags->row.">",
211
					"<!-- END:BLOCK -->",
212
				"<".$this->tags->row.">",
213
					"{FOOTERCELLS}",
214
				"</".$this->tags->row.">",
215
			"</".$this->tags->container.">"
216
		);
217
		$sHTML = implode("", $aHTML);
218
		return $sHTML;
219
	}
220
	
221
	/**
222
	 * generate table mark-up
223
	 * @return string
224
	 */
225
	public function buildMarkup () {
226
		$sHTML = "";
0 ignored issues
show
Unused Code introduced by
$sHTML 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...
227
		
228
		$sTableID = $this->getOptions("formID");
229
		if (!$sTableID) {
230
			$sTableID = "table" . md5(microtime());
231
			$this->options["formID"] = $sTableID;
232
		}
233
		
234
		$this->getTemplate()->reset();
235
		$this->getTemplate()->set('s', 'TABLEID',			$sTableID );
236
		$this->buildHeaderCells( $this->getOptions("columns") );
237
		$this->buildFooterCells( $this->getOptions("footer") );
238
		$this->buildBodyCells( $this->getData(), $this->getOptions("columns") );
239
		$sTemplate = $this->getOptions("template");
240
		if ($sTemplate == "") {
241
			$sTemplate = $this->buildMarkupTemplate();
242
		}
243
		$sHTML = $this->getTemplate()->generate( $sTemplate, true );
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a integer.

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...
244
		return $sHTML;
245
	}
246
	
247
	/**
248
	 * generate table JSON data
249
	 * @return string
250
	 */
251
	public function buildData () {
252
		$sJSON = "[]";
253
		if (!empty($this->data)) {
254
			$sJSON = json_encode($this->data);
255
		}
256
		return $sJSON;
257
	}
258
	
259
	/**
260
	 * return template object
261
	 * @return Template
262
	 */
263
	public function getTemplate() {
264
		if ($this->template == null) {
265
			$this->setTemplate();
266
		}
267
		return $this->template;
268
	}
269
270
	/**
271
	 * generate template object
272
	 * @param Template $template
273
	 * @return ProductTable
274
	 */
275
	public function setTemplate( $template = null ) {
276
		if ($template == null) {
277
			$this->template = new Template;
278
		} else {
279
			$this->template = $template;
280
		}
281
		return ($this);
282
	}
283
	
284
	/**
285
	 * return table data
286
	 * @return mixed
287
	 */
288
	public function getData() {
289
		return $this->data;
290
	}
291
292
	/**
293
	 * set new table data
294
	 * @param mixed $data
295
	 * @return ProductTable
296
	 */
297
	public function setData( $data = null) {
298
		if ( is_array($data) ) {
299
			$this->data = $data;
300
		}
301
		return $this;
302
	}
303
304
	/**
305
	 * return option by key or complete option set
306
	 * @param	string $key	
307
	 * @return	mixed
308
	 */
309
	public function getOptions( $key = "" ) {
310
		if ( !empty($key) ) { 
311
			if ( isset($this->options[$key]) ) {
312
				return $this->options[$key];
313
			} else {
314
				return false;
315
			}
316
		}
317
		return $this->options;
318
	}
319
320
	/**
321
	 * @param object|array $options
322
	 * @return ProductTable
323
	 */
324
	public function setOptions($options) {
325
		if ( is_array($options) ) {
326
			$this->options = $options;
327
		} else if ( is_object($options) ) {
328
			$this->options = (array)$options;
329
		} else {
330
			throw new \Exception("invalid table options");
331
		}
332
		if ( isset($this->options["data"]) ) {
333
			$this->setData($this->getOptions("data"));
334
			unset( $this->options->data );
335
		}
336
		return $this;
337
	}
338
339
340
}