Completed
Push — master ( 5b3666...b3a3fe )
by Jean-Christophe
04:35
created

HtmlMenu::setActiveItem()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 2
eloc 5
nc 2
nop 1
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\common\html\BaseHtml;
13
use Ajax\semantic\html\modules\HtmlPopup;
14
use Ajax\semantic\html\elements\HtmlIcon;
15
use Ajax\semantic\html\elements\html5\HtmlLink;
16
use Ajax\semantic\html\elements\HtmlInput;
17
use Ajax\semantic\html\elements\HtmlButton;
18
19
/**
20
 * Semantic Menu component
21
 * @see http://semantic-ui.com/collections/menu.html
22
 * @author jc
23
 * @version 1.001
24
 */
25
class HtmlMenu extends HtmlSemCollection {
26
	private $_itemHeader;
27
28
	public function __construct($identifier, $items=array()) {
29
		parent::__construct($identifier, "div", "ui menu");
30
		$this->addItems($items);
31
	}
32
33
	/**
34
	 * Sets the menu type
35
	 * @param string $type one of text,item
36
	 * @return \Ajax\semantic\html\collections\HtmlMenu
37
	 */
38
	public function setType($type="") {
39
		return $this->addToPropertyCtrl("class", $type, array ("","item","text" ));
40
	}
41
42
	public function setActiveItem($index) {
43
		$item=$this->getItem($index);
44
		if ($item !== null) {
45
			$item->addToProperty("class", "active");
46
		}
47
		return $this;
48
	}
49
50
	private function getItemToInsert($item) {
51
		if ($item instanceof HtmlInput || $item instanceof HtmlImg || $item instanceof HtmlIcon || $item instanceof HtmlButton || ($item instanceof HtmlDropdown && $this->propertyContains("class", "vertical")===false)) {
52
			$itemO=new HtmlSemDoubleElement("item-" . $this->identifier, "div", "");
53
			$itemO->setContent($item);
54
			$item=$itemO;
55
		}
56
		return $item;
57
	}
58
59
	private function afterInsert($item) {
60
		if (!$item instanceof HtmlMenu)
61
			$item->addToPropertyCtrl("class", "item", array ("item" ));
62
		else {
63
			$this->setSecondary();
64
		}
65
		return $item;
66
	}
67
68
	/**
69
	 *
70
	 * {@inheritDoc}
71
	 *
72
	 * @see \Ajax\common\html\html5\HtmlCollection::addItem()
73
	 */
74
	public function addItem($item) {
75
		$item=parent::addItem($this->getItemToInsert($item));
76
		return $this->afterInsert($item);
77
	}
78
79
	/**
80
	 *
81
	 * {@inheritDoc}
82
	 *
83
	 * @see \Ajax\common\html\HtmlCollection::insertItem()
84
	 */
85
	public function insertItem($item, $position=0) {
86
		$item=parent::insertItem($this->getItemToInsert($item), $position);
87
		return $this->afterInsert($item);
88
	}
89
90
	public function generateMenuAsItem($menu, $header=null) {
91
		$count=$this->count();
92
		$item=new HtmlSemDoubleElement("item-" . $this->identifier . "-" . $count, "div");
93
		if (isset($header)) {
94
			$headerItem=new HtmlSemDoubleElement("item-header-" . $this->identifier . "-" . $count, "div", "header");
95
			$headerItem->setContent($header);
96
			$item->addContent($headerItem);
97
			$this->_itemHeader=$headerItem;
98
		}
99
		$menu->setClass("menu");
100
		$item->addContent($menu);
101
		return $item;
102
	}
103
104
	public function addMenuAsItem($menu, $header=null) {
105
		return $this->addItem($this->generateMenuAsItem($menu, $header));
106
	}
107
108
	public function addPopupAsItem($value, $identifier, $content="") {
109
		$value=new HtmlSemDoubleElement($identifier, "a", "browse item", $value);
110
		$value->addContent(new HtmlIcon("", "dropdown"));
111
		$value=$this->addItem($value);
112
		$popup=new HtmlPopup($value, "popup-" . $this->identifier . "-" . $this->count(), $content);
113
		$popup->setFlowing()->setPosition("bottom left")->setOn("click");
114
		$this->wrap("", $popup);
115
		return $popup;
116
	}
117
118
	public function addDropdownAsItem($value, $items=NULL) {
119
		$dd=$value;
120
		if (\is_string($value)) {
121
			$dd=new HtmlDropdown("dropdown-" . $this->identifier . "-" . $this->count(), $value, $items);
122
		}
123
		return $this->addItem($dd);
124
	}
125
126
	/**
127
	 *
128
	 * {@inheritDoc}
129
	 *
130
	 * @see \Ajax\common\html\html5\HtmlCollection::createItem()
131
	 */
132
	protected function createItem($value) {
133
		$itemO=new HtmlLink("item-" . \sizeof($this->content), "", $value);
134
		return $itemO->setClass("item");
135
	}
136
137
	public function setInverted() {
138
		return $this->addToProperty("class", "inverted");
139
	}
140
141
	public function setSecondary() {
142
		return $this->addToProperty("class", "secondary");
143
	}
144
145
	public function setVertical() {
146
		return $this->addToPropertyCtrl("class", "vertical", array ("vertical" ));
147
	}
148
149
	public function setPosition($value="right") {
150
		return $this->addToPropertyCtrl("class", $value, array ("right","left" ));
151
	}
152
153
	public function setPointing($value=Direction::NONE) {
154
		return $this->addToPropertyCtrl("class", $value . " pointing", Direction::getConstantValues("pointing"));
155
	}
156
157
	public function asTab($vertical=false) {
158
		$this->apply(function (HtmlDoubleElement &$item) {
159
			$item->setTagName("a");
160
		});
161
		if ($vertical === true)
162
			$this->setVertical();
163
		return $this->addToProperty("class", "tabular");
164
	}
165
166
	public function asPagination() {
167
		$this->apply(function (HtmlDoubleElement &$item) {
168
			$item->setTagName("a");
169
		});
170
		return $this->addToProperty("class", "pagination");
171
	}
172
173
	public function setFixed() {
174
		return $this->addToProperty("class", "fixed");
175
	}
176
177
	public function setFluid() {
178
		return $this->addToProperty("class", "fluid");
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->addToProperty('class', 'fluid'); (Ajax\semantic\html\collections\menus\HtmlMenu) is incompatible with the return type of the parent method Ajax\semantic\html\base\...SemCollection::setFluid of type Ajax\semantic\html\base\HtmlSemDoubleElement.

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...
179
	}
180
181
	public function setCompact() {
182
		return $this->addToProperty("class", "compact");
183
	}
184
185
	/*
186
	 * (non-PHPdoc)
187
	 * @see \Ajax\bootstrap\html\base\BaseHtml::fromDatabaseObject()
188
	 */
189
	public function fromDatabaseObject($object, $function) {
190
		$return=$function($object);
191
		if (\is_array($return))
192
			$this->addItems($return);
193
		else
194
			$this->addItem($return);
195
	}
196
197
	/**
198
	 * Defines the menu width
199
	 * @param int $width
200
	 * @return \Ajax\semantic\html\collections\menus\HtmlMenu
201
	 */
202 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...
203
		if (\is_int($width)) {
204
			$width=Wide::getConstants()["W" . $width];
205
		}
206
		$this->addToPropertyCtrl("class", $width, Wide::getConstants());
207
		return $this->addToPropertyCtrl("class", "item", array ("item" ));
208
	}
209
210
	public function addImage($identifier, $src="", $alt="") {
211
		return $this->addItem(new HtmlImg($identifier, $src, $alt));
212
	}
213
214
	public static function vertical($identifier, $items=array()) {
215
		return (new HtmlMenu($identifier, $items))->setVertical();
216
	}
217
218
	public function getItemHeader() {
219
		return $this->_itemHeader;
220
	}
221
}