Completed
Push — master ( e76efc...a384bc )
by Jean-Christophe
04:08
created

HtmlGrid::setColWidth()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
rs 9.4285
cc 2
eloc 3
nc 2
nop 2
1
<?php
2
3
namespace Ajax\semantic\html\collections;
4
5
use Ajax\common\html\HtmlCollection;
6
use Ajax\semantic\html\content\HtmlGridRow;
7
use Ajax\semantic\html\base\constants\Wide;
8
use Ajax\semantic\html\base\constants\VerticalAlignment;
9
use Ajax\semantic\html\base\HtmlSemCollection;
10
use Ajax\semantic\html\base\traits\TextAlignmentTrait;
11
use Ajax\semantic\html\content\HtmlGridCol;
12
13
/**
14
 * Semantic Grid component
15
 * @see http://semantic-ui.com/collections/grid.html
16
 * @author jc
17
 * @version 1.001
18
 */
19
class HtmlGrid extends HtmlSemCollection {
20
	use TextAlignmentTrait;
21
	private $_createCols;
22
	private $_colSizing=true;
23
	private $_implicitRows=false;
24
25
	public function __construct($identifier, $numRows=1, $numCols=NULL, $createCols=true, $implicitRows=false) {
26
		parent::__construct($identifier, "div", "ui grid");
27
		$this->_implicitRows=$implicitRows;
28
		$this->_createCols=$createCols;
29
		if (isset($numCols)) {
30
			// if($this->_createCols){
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% 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...
31
			$this->_colSizing=false;
32
			// }
33
			$this->setWide($numCols);
34
		}
35
		if($createCols)
36
			$this->setRowsCount($numRows, $numCols);
37
	}
38
39
	public function asSegment() {
40
		return $this->addToPropertyCtrl("class", "segment", array ("segment" ));
41
	}
42
43
	public function asContainer() {
44
		return $this->addToPropertyCtrl("class", "container", array ("container" ));
45
	}
46
47
	/**
48
	 * Defines the grid width (alias for setWidth)
49
	 * @param int $wide
50
	 */
51 View Code Duplication
	public function setWide($wide) {
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...
52
		if(isset(Wide::getConstants()["W" . $wide])){
53
			$wide=Wide::getConstants()["W" . $wide];
54
			$this->addToPropertyCtrl("class", $wide, Wide::getConstants());
55
			return $this->addToPropertyCtrl("class", "column", array ("column" ));
56
		}
57
		return $this;
58
	}
59
	
60
	public function setColWidth($numCol,$width){
61
		foreach ($this->content as $row){
62
			$row->getCol($numCol)->setWidth($width);
63
		}
64
	}
65
66
	/**
67
	 * Defines the grid width
68
	 * @param int $width
69
	 * @return \Ajax\semantic\html\collections\HtmlGrid
70
	 */
71
	public function setWidth($width) {
72
		return $this->setWide($width);
73
	}
74
75
	/**
76
	 * Adds a row with $colsCount columns
77
	 * @param int $colsCount number of columns to create
78
	 * @return mixed
79
	 */
80
	public function addRow($colsCount=NULL) {
81
		$rowCount=$this->rowCount() + 1;
82
		$this->setRowsCount($rowCount, $colsCount, true);
83
		return $this->content[$rowCount - 1];
84
	}
85
86
	/**
87
	 * Adds a col
88
	 * @param int $width with of the column to add
89
	 * @return mixed|\Ajax\semantic\html\collections\HtmlGrid
90
	 */
91
	public function addCol($width=NULL) {
92
		$colCount=$this->colCount() + 1;
93
		$this->setColsCount($colCount, true, $width);
94
		if ($this->hasOnlyCols($this->count()))
95
			return $this->content[$colCount - 1];
96
		return $this;
97
	}
98
99
	/**
100
	 *
101
	 * @param array $sizes array of width of the columns to create
102
	 * @return \Ajax\semantic\html\collections\HtmlGrid
103
	 */
104
	public function addCols($sizes=array()) {
105
		foreach ( $sizes as $size ) {
106
			$this->addCol($size);
107
		}
108
		return $this;
109
	}
110
111
	/**
112
	 * Create $rowsCount rows
113
	 * @param int $rowsCount
114
	 * @param int $colsCount
115
	 * @return \Ajax\semantic\html\collections\HtmlGrid
116
	 */
117
	public function setRowsCount($rowsCount, $colsCount=NULL, $force=false) {
118
		$count=$this->count();
119
		if ($rowsCount < 2 && $force === false) {
120 View Code Duplication
			for($i=$count; $i < $colsCount; $i++) {
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...
121
				$this->addItem(new HtmlGridCol("col-" . $this->identifier . "-" . $i));
122
			}
123
		} else {
124
			if ($this->hasOnlyCols($count)) {
125
				$tmpContent=$this->content;
126
				$item=$this->addItem($colsCount);
127
				$item->setContent($tmpContent);
128
				$this->content=array ();
129
				$count=1;
130
			}
131
			for($i=$count; $i < $rowsCount; $i++) {
132
				$this->addItem($colsCount);
133
			}
134
		}
135
		return $this;
136
	}
137
138
	protected function hasOnlyCols($count) {
139
		return $count > 0 && $this->content[0] instanceof HtmlGridCol;
140
	}
141
142
	/**
143
	 * Defines the number of columns in the grid
144
	 * @param int $numCols
145
	 * @param boolean $toCreate
146
	 * @param int $width
147
	 * @return \Ajax\semantic\html\collections\HtmlGrid
148
	 */
149
	public function setColsCount($numCols, $toCreate=true, $width=NULL) {
150
		if (isset($width)===false) {
151
			$this->setWide($numCols);
152
		}
153
		if ($toCreate === true) {
154
			$count=$this->count();
155
			if ($count == 0 || $this->hasOnlyCols($count)) {
156 View Code Duplication
				for($i=$count; $i < $numCols; $i++) {
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...
157
					$this->addItem(new HtmlGridCol("col-" . $this->identifier . "-" . $i, $width));
158
				}
159
			} else {
160
				for($i=0; $i < $count; $i++) {
161
					$this->getItem($i)->setColsCount($numCols);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Ajax\common\html\HtmlDoubleElement as the method setColsCount() does only exist in the following sub-classes of Ajax\common\html\HtmlDoubleElement: Ajax\semantic\html\collections\HtmlGrid, Ajax\semantic\html\content\HtmlGridRow. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
162
				}
163
			}
164
		}
165
		return $this;
166
	}
167
168
	/**
169
	 * return the row at $index
170
	 * @param int $index
171
	 * @return \Ajax\semantic\html\collections\HtmlGridRow
172
	 */
173
	public function getRow($index) {
174
		return $this->getItem($index);
175
	}
176
177
	/**
178
	 * Returns the row count
179
	 * @return int
180
	 */
181
	public function rowCount() {
182
		$count=$this->count();
183
		if ($this->hasOnlyCols($count))
184
			return 0;
185
		return $count;
186
	}
187
188
	/**
189
	 * Returns the column count
190
	 * @return int
191
	 */
192
	public function colCount() {
193
		$count=$this->count();
194
		if ($this->hasOnlyCols($count))
195
			return $count;
196
		if ($count > 0)
197
			return $this->getItem(0)->count();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Ajax\common\html\HtmlDoubleElement as the method count() does only exist in the following sub-classes of Ajax\common\html\HtmlDoubleElement: Ajax\common\html\HtmlCollection, Ajax\common\html\html5\HtmlList, Ajax\semantic\html\base\HtmlSemCollection, Ajax\semantic\html\base\HtmlSemNavElement, Ajax\semantic\html\collections\HtmlBreadcrumb, Ajax\semantic\html\collections\HtmlGrid, Ajax\semantic\html\collections\form\HtmlForm, Ajax\semantic\html\collections\form\HtmlFormFields, Ajax\semantic\html\colle...menus\HtmlAccordionMenu, Ajax\semantic\html\collections\menus\HtmlIconMenu, Ajax\semantic\html\colle...nus\HtmlLabeledIconMenu, Ajax\semantic\html\collections\menus\HtmlMenu, Ajax\semantic\html\colle...enus\HtmlPaginationMenu, Ajax\semantic\html\content\HtmlGridRow, Ajax\semantic\html\content\table\HtmlTR, Ajax\semantic\html\content\table\HtmlTableContent, Ajax\semantic\html\elements\HtmlButtonGroups, Ajax\semantic\html\elements\HtmlIconGroups, Ajax\semantic\html\elements\HtmlLabelGroups, Ajax\semantic\html\elements\HtmlList, Ajax\semantic\html\elements\HtmlSegmentGroups, Ajax\semantic\html\elements\HtmlStep, Ajax\semantic\html\modules\HtmlAccordion, Ajax\semantic\html\modules\HtmlDropdown, Ajax\semantic\html\modules\HtmlShape, Ajax\semantic\html\modules\HtmlTab, Ajax\semantic\html\views\HtmlCardGroups. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
198
		return 0;
199
	}
200
201
	/**
202
	 * Returns the cell (HtmlGridCol) at position rrow,$col
203
	 * @param int $row
204
	 * @param int $col
205
	 * @return \Ajax\semantic\html\collections\HtmlGridCol
206
	 */
207
	public function getCell($row, $col) {
208
		if ($row < 2 && $this->hasOnlyCols($this->count()))
209
			return $this->getItem($col);
210
		$row=$this->getItem($row);
211
		if (isset($row)) {
212
			$col=$row->getItem($col);
213
		}
214
		return $col;
215
	}
216
217
	/**
218
	 * Adds dividers between columns ($vertically=false) or between rows ($vertically=true)
219
	 * @param boolean $vertically
220
	 * @return \Ajax\semantic\html\collections\HtmlGrid
221
	 */
222
	public function setDivided($vertically=false) {
223
		$value=($vertically === true) ? "vertically divided" : "divided";
224
		return $this->addToPropertyCtrl("class", $value, array ("divided" ));
225
	}
226
227
	/**
228
	 * Divides rows into cells
229
	 * @param boolean $internally true for internal cells
230
	 * @return \Ajax\semantic\html\collections\HtmlGrid
231
	 */
232
	public function setCelled($internally=false) {
233
		$value=($internally === true) ? "internally celled" : "celled";
234
		return $this->addToPropertyCtrl("class", $value, array ("celled","internally celled" ));
235
	}
236
237
	/**
238
	 * A grid can have its columns centered
239
	 */
240
	public function setCentered() {
241
		return $this->addToPropertyCtrl("class", "centered", array ("centered" ));
242
	}
243
244
	/**
245
	 * automatically resize all elements to split the available width evenly
246
	 * @return \Ajax\semantic\html\collections\HtmlGrid
247
	 */
248
	public function setEqualWidth() {
249
		return $this->addToProperty("class", "equal width");
250
	}
251
252
	/**
253
	 * Adds vertical or/and horizontal gutters
254
	 * @param string $value
255
	 * @return \Ajax\semantic\html\collections\HtmlGrid
256
	 */
257
	public function setPadded($value=NULL) {
258
		if (isset($value))
259
			$this->addToPropertyCtrl("class", $value, array ("vertically","horizontally" ));
260
		return $this->addToProperty("class", "padded");
261
	}
262
263
	/**
264
	 *
265
	 * @param boolean $very
266
	 * @return \Ajax\semantic\html\collections\HtmlGrid
267
	 */
268
	public function setRelaxed($very=false) {
269
		$value=($very === true) ? "very relaxed" : "relaxed";
270
		return $this->addToPropertyCtrl("class", $value, array ("relaxed","very relaxed" ));
271
	}
272
273
	public function setVerticalAlignment($value=VerticalAlignment::MIDDLE) {
274
		return $this->addToPropertyCtrl("class", $value . " aligned", VerticalAlignment::getConstantValues("aligned"));
275
	}
276
277
	/**
278
	 *
279
	 * {@inheritDoc}
280
	 *
281
	 * @see \Ajax\common\html\HtmlCollection::createItem()
282
	 */
283
	protected function createItem($value) {
284
		if ($this->_createCols === false)
285
			$value=null;
286
		$item=new HtmlGridRow($this->identifier . "-row-" . ($this->count() + 1), $value, $this->_colSizing, $this->_implicitRows);
287
		return $item;
288
	}
289
290
	/**
291
	 * Sets $values to the grid
292
	 * @param array $values
293
	 */
294
	public function setValues($values, $force=true) {
295
		$count=$this->count();
296
		$valuesSize=\sizeof($values);
297
		if ($this->_createCols === false || $force === true) {
298
			for($i=$count; $i < $valuesSize; $i++) {
299
				$colSize=\sizeof($values[$i]);
300
				$this->addItem(new HtmlGridRow($this->identifier . "-row-" . ($this->count() + 1), $colSize, $this->_colSizing, $this->_implicitRows));
301
			}
302
		}
303
		$count=\min(array ($this->count(),$valuesSize ));
304
		for($i=0; $i < $count; $i++) {
305
			$this->content[$i]->setValues($values[$i], $this->_createCols === false);
306
		}
307
	}
308
309
	/**
310
	 * stretch the row contents to take up the entire column height
311
	 * @return \Ajax\semantic\html\content\HtmlGridRow
312
	 */
313
	public function setStretched() {
314
		return $this->addToProperty("class", "stretched");
315
	}
316
317
	public function addDivider($afterColIndex, $vertical=true, $content=NULL) {
318
		$col=$this->getCell(0, $afterColIndex);
319
		return $col->addDivider($vertical, $content);
320
	}
321
}
322