1: <?php
2: namespace Menu\Items\Contents;
3:
4: use HtmlObject\Traits\Helpers;
5: use HtmlObject\Link as HtmlLink;
6: use Menu\Menu;
7: use Menu\Traits\Content;
8: use Underscore\Methods\StringsMethods;
9:
10: /**
11: * A Link in an Item
12: */
13: class Link extends HtmlLink
14: {
15: /**
16: * URL segments that you want to hide from the
17: * generated URL when using ->prefixParents()
18: *
19: * @var array
20: */
21: private $hidden = array(
22: '#',
23: 'javascript:',
24: );
25:
26: /**
27: * The link's URL
28: *
29: * @var string
30: */
31: protected $href;
32:
33: /**
34: * An array of properties to be injected as attributes
35: *
36: * @var array
37: */
38: protected $injectedProperties = array('href');
39:
40: /**
41: * Build a new Link
42: *
43: * @param string $url Its URL
44: * @param string $value Its text
45: * @param array $attributes Facultative attributes
46: */
47: public function __construct($url, $value = null, $attributes = array())
48: {
49: $this->attributes = $attributes;
50: $this->value = $value;
51: $this->href = $url;
52: }
53:
54: /**
55: * Change the Link's URL
56: *
57: * @param string $href An URL
58: *
59: * @return Link
60: */
61: public function href($href)
62: {
63: $this->href = $href;
64:
65: return $this;
66: }
67:
68: /**
69: * Get the link's href
70: *
71: * @return string the href
72: */
73: public function getUrl()
74: {
75: return $this->href;
76: }
77:
78: /**
79: * Break off a chain
80: *
81: * @return Item
82: */
83: public function stop()
84: {
85: return $this->getParent(1);
86: }
87:
88: /**
89: * Render the Link
90: *
91: * @return string
92: */
93: public function render()
94: {
95: $this->href = $this->getEvaluatedUrl();
96:
97: // Don't compote URL if special URL
98: if (!$this->isSpecialUrl()) {
99: $this->href = Menu::getContainer()->bound('url')
100: ? Menu::getContainer('url')->to($this->href)
101: : $this->href;
102: }
103:
104: return parent::render();
105: }
106:
107: ////////////////////////////////////////////////////////////////////
108: ////////////////////////////// HELPERS /////////////////////////////
109: ////////////////////////////////////////////////////////////////////
110:
111: /**
112: * Get the content type
113: *
114: * @return boolean
115: */
116: public function isLink()
117: {
118: return true;
119: }
120:
121: /**
122: * Whether the link is special or not
123: *
124: * @return boolean
125: */
126: public function isSpecialUrl()
127: {
128: foreach ($this->hidden as $hidden) {
129: if (StringsMethods::startsWith($this->href, $hidden)) return true;
130: }
131:
132: return false;
133: }
134:
135: ////////////////////////////////////////////////////////////////////
136: /////////////////////// PREFIXES AND SEGMENTS //////////////////////
137: ////////////////////////////////////////////////////////////////////
138:
139: /**
140: * Get the evaluated URL based on the prefix settings
141: *
142: * @return string
143: */
144: public function getEvaluatedUrl()
145: {
146: $segments = array();
147:
148: // If the URL is just an hash, don't do shit
149: if (!$this->getParent() or $this->isSpecialUrl()) {
150: return $this->href;
151: }
152:
153: // Prepend list prefix
154: $listPrefix = $this->getParent(1)->getOption('item_list.prefix');
155: if (!is_null($listPrefix)) {
156: $segments[] = $listPrefix;
157: }
158:
159: // Prepend parent item prefix
160: $prefixParents = $this->getParent(1)->getOption('item_list.prefix_parents');
161: if ($prefixParents) {
162: $segments += $this->getParentItemsUrls();
163: }
164:
165: // Prepend handler prefix
166: $prefixHandler = $this->getParent(1)->getOption('item_list.prefix_handler');
167: if ($prefixHandler) {
168: $segments[] = $this->getHandlerSegment();
169: }
170:
171: $segments[] = $this->href;
172:
173: return implode('/', $segments);
174: }
175:
176: /**
177: * Get all the parent Items
178: *
179: * @return array An array of Items
180: */
181: protected function getParentItems()
182: {
183: $parents = array();
184:
185: $list = $this->getParent(1);
186:
187: while ($list->getParent()) {
188: $parents[] = $list->getParent();
189:
190: $parent = $list->getParent(1);
191: $list = $parent ? $list->getParent(1) : null;
192: }
193:
194: return array_reverse($parents);
195: }
196:
197: /**
198: * Get all the parent Lists
199: *
200: * @return array An array of Lists
201: */
202: protected function getParentLists()
203: {
204: $parents = array();
205:
206: $list = $this->getParent(1);
207: $parent = $list->getParent() ?: null;
208: $parents[] = $list;
209:
210: while ($list and $parent) {
211: $parents[] = $parent;
212: $list = $parent ?: null;
213: }
214:
215: return array_reverse($parents);
216: }
217:
218: /**
219: * Get the handler of the Menu containing this link
220: *
221: * @return string
222: */
223: protected function getHandlerSegment()
224: {
225: $parentLists = $this->getParentLists();
226: $handler = array_pop($parentLists);
227:
228: return $handler->name;
229: }
230:
231: /**
232: * Get the URL of the parent Items
233: *
234: * @return array
235: */
236: protected function getParentItemsUrls()
237: {
238: $urls = array();
239:
240: foreach ($this->getParentItems() as $item) {
241: if (!is_object($item)) continue;
242:
243: if (
244: $item->value->isLink() and
245: !$item->value->isSpecialUrl() and
246: !is_null($item->value->href)) {
247: $urls[] = $item->value->href;
248: }
249: }
250:
251: return $urls;
252: }
253: }
254: