Completed
Push — master ( 3ad5ef...acbd35 )
by Jean-Christophe
03:30
created

HtmlMenu   B

Complexity

Total Complexity 46

Size/Duplication

Total Lines 220
Duplicated Lines 6.82 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 46
lcom 1
cbo 12
dl 15
loc 220
rs 8.3999
c 3
b 1
f 0

29 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A setType() 0 3 1
A setActiveItem() 0 7 2
B getItemToInsert() 0 7 7
A afterInsert() 0 8 3
A addItem() 0 7 2
A insertItem() 0 4 1
A generateMenuAsItem() 0 16 3
A addMenuAsItem() 0 3 1
A addPopupAsItem() 0 9 1
A addDropdownAsItem() 8 8 2
A createItem() 0 6 1
A setInverted() 0 3 1
A setSecondary() 0 7 2
A setVertical() 0 3 1
A setPosition() 0 3 1
A setPointing() 0 3 1
A asTab() 0 8 2
A asPagination() 0 6 1
A setFixed() 0 3 1
A setFluid() 0 3 1
A setCompact() 0 3 1
A fromDatabaseObject() 0 7 2
A setWidth() 7 7 2
A addImage() 0 3 1
A vertical() 0 3 1
A getItemHeader() 0 3 1
A setHasContainer() 0 3 1
A run() 0 5 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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

1
<?php
2
3
namespace Ajax\semantic\html\collections\menus;
4
5
use Ajax\common\html\HtmlDoubleElement;
6
use Ajax\semantic\html\base\constants\Direction;
7
use Ajax\semantic\html\base\HtmlSemCollection;
8
use Ajax\semantic\html\base\HtmlSemDoubleElement;
9
use Ajax\semantic\html\base\constants\Wide;
10
use Ajax\common\html\html5\HtmlImg;
11
use Ajax\semantic\html\modules\HtmlDropdown;
12
use Ajax\semantic\html\modules\HtmlPopup;
13
use Ajax\semantic\html\elements\HtmlIcon;
14
use Ajax\semantic\html\elements\HtmlInput;
15
use Ajax\semantic\html\elements\HtmlButton;
16
use Ajax\semantic\html\base\traits\AttachedTrait;
17
use Ajax\semantic\html\content\HtmlMenuItem;
18
use Ajax\JsUtils;
19
use Ajax\semantic\html\elements\HtmlButtonGroups;
20
use Ajax\semantic\html\elements\HtmlLabel;
21
22
/**
23
 * Semantic Menu component
24
 * @see http://semantic-ui.com/collections/menu.html
25
 * @author jc
26
 * @version 1.001
27
 */
28
class HtmlMenu extends HtmlSemCollection {
29
	use AttachedTrait;
30
	private $_itemHeader;
31
32
	public function __construct($identifier, $items=array()) {
33
		parent::__construct($identifier, "div", "ui menu");
34
		$this->addItems($items);
35
	}
36
37
	/**
38
	 * Sets the menu type
39
	 * @param string $type one of text,item
40
	 * @return \Ajax\semantic\html\collections\HtmlMenu
41
	 */
42
	public function setType($type="") {
43
		return $this->addToPropertyCtrl("class", $type, array ("","item","text" ));
44
	}
45
46
	public function setActiveItem($index) {
47
		$item=$this->getItem($index);
48
		if ($item !== null) {
49
			$item->addToProperty("class", "active");
50
		}
51
		return $this;
52
	}
53
54
	private function getItemToInsert($item) {
55
		if ($item instanceof HtmlInput || $item instanceof HtmlImg || $item instanceof HtmlIcon || $item instanceof HtmlButtonGroups || $item instanceof HtmlButton || $item instanceof HtmlLabel) {
56
			$itemO=new HtmlMenuItem("item-" . $this->identifier . "-" . \sizeof($this->content) , $item);
57
			$item=$itemO;
58
		}
59
		return $item;
60
	}
61
62
	private function afterInsert($item) {
63
		if (!$item instanceof HtmlMenu && $item->propertyContains("class", "header")===false)
64
			$item->addToPropertyCtrl("class", "item", array ("item" ));
65
		else {
66
			$this->setSecondary();
67
		}
68
		return $item;
69
	}
70
71
	/**
72
	 *
73
	 * {@inheritDoc}
74
	 *
75
	 * @see \Ajax\common\html\html5\HtmlCollection::addItem()
76
	 */
77
	public function addItem($item) {
78
		$number=$item;
79
		$item=parent::addItem($this->getItemToInsert($item));
80
		if(\is_int($number))
81
			$item->setProperty("data-page", $number);
82
		return $this->afterInsert($item);
83
	}
84
85
	/**
86
	 *
87
	 * {@inheritDoc}
88
	 *
89
	 * @see \Ajax\common\html\HtmlCollection::insertItem()
90
	 */
91
	public function insertItem($item, $position=0) {
92
		$item=parent::insertItem($this->getItemToInsert($item), $position);
93
		return $this->afterInsert($item);
94
	}
95
96
	public function generateMenuAsItem($menu, $header=null) {
97
		$count=$this->count();
98
		$item=new HtmlSemDoubleElement("item-" . $this->identifier . "-" . $count, "div");
99
		if (isset($header)) {
100
			$headerItem=new HtmlSemDoubleElement("item-header-" . $this->identifier . "-" . $count, "div", "header");
101
			$headerItem->setContent($header);
102
			$item->addContent($headerItem);
103
			$this->_itemHeader=$headerItem;
104
		}
105
		if(\is_array($menu)){
106
			$menu=new HtmlMenu("menu-" . $this->identifier . "-" . $count,$menu);
107
		}
108
		$menu->setClass("menu");
109
		$item->addContent($menu);
110
		return $item;
111
	}
112
113
	public function addMenuAsItem($menu, $header=null) {
114
		return $this->addItem($this->generateMenuAsItem($menu, $header));
115
	}
116
117
	public function addPopupAsItem($value, $identifier, $content="") {
118
		$value=new HtmlSemDoubleElement($identifier, "a", "browse item", $value);
119
		$value->addContent(new HtmlIcon("", "dropdown"));
120
		$value=$this->addItem($value);
121
		$popup=new HtmlPopup($value, "popup-" . $this->identifier . "-" . $this->count(), $content);
122
		$popup->setFlowing()->setPosition("bottom left")->setOn("click");
123
		$this->wrap("", $popup);
124
		return $popup;
125
	}
126
127 View Code Duplication
	public function addDropdownAsItem($value, $items=NULL) {
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...
128
		$dd=$value;
129
		if (\is_string($value)) {
130
			$dd=new HtmlDropdown("dropdown-" . $this->identifier . "-" . $this->count(), $value, $items);
131
		}
132
		$this->addItem($dd);
133
		return $dd;
134
	}
135
136
	/**
137
	 *
138
	 * {@inheritDoc}
139
	 *
140
	 * @see \Ajax\common\html\html5\HtmlCollection::createItem()
141
	 */
142
	protected function createItem($value) {
143
		$itemO=new HtmlMenuItem($this->identifier."-item-" . \sizeof($this->content),"");
144
		$itemO->setTagName("a");
145
		$itemO->setContent($value);
146
		return $itemO;
147
	}
148
149
	public function setInverted() {
150
		return $this->addToProperty("class", "inverted");
151
	}
152
153
	public function setSecondary($value=true) {
154
		if($value)
155
			$this->addToProperty("class", "secondary");
156
		else
157
			$this->removePropertyValue("class", "secondary");
158
		return $this;
159
	}
160
161
	public function setVertical() {
162
		return $this->addToPropertyCtrl("class", "vertical", array ("vertical" ));
163
	}
164
165
	public function setPosition($value="right") {
166
		return $this->addToPropertyCtrl("class", $value, array ("right","left" ));
167
	}
168
169
	public function setPointing($value=Direction::NONE) {
170
		return $this->addToPropertyCtrl("class", $value . " pointing", Direction::getConstantValues("pointing"));
171
	}
172
173
	public function asTab($vertical=false) {
174
		$this->apply(function (HtmlDoubleElement &$item) {
175
			$item->setTagName("a");
176
		});
177
		if ($vertical === true)
178
			$this->setVertical();
179
		return $this->addToProperty("class", "tabular");
180
	}
181
182
	public function asPagination() {
183
		$this->apply(function (HtmlDoubleElement &$item) {
184
			$item->setTagName("a");
185
		});
186
		return $this->addToProperty("class", "pagination");
187
	}
188
189
	public function setFixed() {
190
		return $this->addToProperty("class", "fixed");
191
	}
192
193
	public function setFluid() {
194
		return $this->addToProperty("class", "fluid");
195
	}
196
197
	public function setCompact() {
198
		return $this->addToProperty("class", "compact");
199
	}
200
201
	/*
202
	 * (non-PHPdoc)
203
	 * @see \Ajax\bootstrap\html\base\BaseHtml::fromDatabaseObject()
204
	 */
205
	public function fromDatabaseObject($object, $function) {
206
		$return=$function($object);
207
		if (\is_array($return))
208
			$this->addItems($return);
209
		else
210
			$this->addItem($return);
211
	}
212
213
	/**
214
	 * Defines the menu width
215
	 * @param int $width
216
	 * @return \Ajax\semantic\html\collections\menus\HtmlMenu
217
	 */
218 View Code Duplication
	public function setWidth($width) {
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...
219
		if (\is_int($width)) {
220
			$width=Wide::getConstants()["W" . $width];
221
		}
222
		$this->addToPropertyCtrl("class", $width, Wide::getConstants());
223
		return $this->addToPropertyCtrl("class", "item", array ("item" ));
224
	}
225
226
	public function addImage($identifier, $src="", $alt="") {
227
		return $this->addItem(new HtmlImg($identifier, $src, $alt));
228
	}
229
230
	public static function vertical($identifier, $items=array()) {
231
		return (new HtmlMenu($identifier, $items))->setVertical();
232
	}
233
234
	public function getItemHeader() {
235
		return $this->_itemHeader;
236
	}
237
238
	public function setHasContainer(){
239
		return $this->wrapContent("<div class='ui container'>","</div>");
240
	}
241
242
	public function run(JsUtils $js){
243
		$this->onClick('if(!$(this).hasClass("dropdown")&&!$(this).hasClass("no-active")){$(this).addClass("active").siblings().removeClass("active");}',false,false);
244
		$result= parent::run($js);
245
		return $result->setItemSelector(".item");
246
	}
247
}