PageRenderTime 47ms CodeModel.GetById 29ms app.highlight 15ms RepoModel.GetById 0ms app.codeStats 0ms

/web/concrete/models/attribute/types/select/controller.php

https://github.com/shin2/concrete5
PHP | 586 lines | 491 code | 74 blank | 21 comment | 84 complexity | f259896ba9d3fde3450f3d63289e654d MD5 | raw file
  1<?php defined('C5_EXECUTE') or die("Access Denied.");
  2
  3class SelectAttributeTypeController extends AttributeTypeController  {
  4
  5	private $akSelectAllowMultipleValues;
  6	private $akSelectAllowOtherValues;
  7	private $akSelectOptionDisplayOrder;
  8
  9	protected $searchIndexFieldDefinition = 'X NULL';
 10	
 11	public function type_form() {
 12		$path1 = $this->getView()->getAttributeTypeURL('type_form.js');
 13		$path2 = $this->getView()->getAttributeTypeURL('type_form.css');
 14		$this->addHeaderItem(Loader::helper('html')->javascript($path1));
 15		$this->addHeaderItem(Loader::helper('html')->css($path2));
 16		$this->set('form', Loader::helper('form'));		
 17		$this->load();
 18		//$akSelectValues = $this->getSelectValuesFromPost();
 19		//$this->set('akSelectValues', $akSelectValues);
 20		
 21		if ($this->isPost()) {
 22			$akSelectValues = $this->getSelectValuesFromPost();
 23			$this->set('akSelectValues', $akSelectValues);
 24		} else if (isset($this->attributeKey)) {
 25			$options = $this->getOptions();
 26			$this->set('akSelectValues', $options);
 27		} else {
 28			$this->set('akSelectValues', array());
 29		}
 30	}
 31	
 32	protected function load() {
 33		$ak = $this->getAttributeKey();
 34		if (!is_object($ak)) {
 35			return false;
 36		}
 37		
 38		$db = Loader::db();
 39		$row = $db->GetRow('select akSelectAllowMultipleValues, akSelectOptionDisplayOrder, akSelectAllowOtherValues from atSelectSettings where akID = ?', $ak->getAttributeKeyID());
 40		$this->akSelectAllowMultipleValues = $row['akSelectAllowMultipleValues'];
 41		$this->akSelectAllowOtherValues = $row['akSelectAllowOtherValues'];
 42		$this->akSelectOptionDisplayOrder = $row['akSelectOptionDisplayOrder'];
 43
 44		$this->set('akSelectAllowMultipleValues', $this->akSelectAllowMultipleValues);
 45		$this->set('akSelectAllowOtherValues', $this->akSelectAllowOtherValues);			
 46		$this->set('akSelectOptionDisplayOrder', $this->akSelectOptionDisplayOrder);			
 47	}
 48
 49	public function duplicateKey($newAK) {
 50		$this->load();
 51		$db = Loader::db();
 52		$db->Execute('insert into atSelectSettings (akID, akSelectAllowMultipleValues, akSelectOptionDisplayOrder, akSelectAllowOtherValues) values (?, ?, ?, ?)', array($newAK->getAttributeKeyID(), $this->akSelectAllowMultipleValues, $this->akSelectOptionDisplayOrder, $this->akSelectAllowOtherValues));	
 53		$r = $db->Execute('select value, displayOrder, isEndUserAdded from atSelectOptions where akID = ?', $this->getAttributeKey()->getAttributeKeyID());
 54		while ($row = $r->FetchRow()) {
 55			$db->Execute('insert into atSelectOptions (akID, value, displayOrder, isEndUserAdded) values (?, ?, ?, ?)', array(
 56				$newAK->getAttributeKeyID(),
 57				$row['value'],
 58				$row['displayOrder'],
 59				$row['isEndUserAdded']
 60			));
 61		}
 62	}
 63	
 64	private function getSelectValuesFromPost() {
 65		$options = new SelectAttributeTypeOptionList();
 66		$displayOrder = 0;		
 67		foreach($_POST as $key => $value) {
 68			if( !strstr($key,'akSelectValue_') || $value=='TEMPLATE' ) continue; 
 69			$opt = false;
 70			// strip off the prefix to get the ID
 71			$id = substr($key, 14);
 72			// now we determine from the post whether this is a new option
 73			// or an existing. New ones have this value from in the akSelectValueNewOption_ post field
 74			if ($_POST['akSelectValueNewOption_' . $id] == $id) {
 75				$opt = new SelectAttributeTypeOption(0, $value, $displayOrder);
 76				$opt->tempID = $id;
 77			} else if ($_POST['akSelectValueExistingOption_' . $id] == $id) {
 78				$opt = new SelectAttributeTypeOption($id, $value, $displayOrder);
 79			}
 80			
 81			if (is_object($opt)) {
 82				$options->add($opt);
 83				$displayOrder++;
 84			}
 85		}
 86		
 87		return $options;
 88	}
 89	
 90	public function form() {
 91		$this->load();
 92		$options = $this->getSelectedOptions();
 93		$selectedOptions = array();
 94		foreach($options as $opt) {
 95			$selectedOptions[] = $opt->getSelectAttributeOptionID();
 96			$selectedOptionValues[$opt->getSelectAttributeOptionID()] = $opt->getSelectAttributeOptionValue();
 97		}
 98		$this->set('selectedOptionValues',$selectedOptionValues);
 99		$this->set('selectedOptions', $selectedOptions);
100		$this->addHeaderItem(Loader::helper('html')->javascript('jquery.ui.js'));
101		$this->addHeaderItem(Loader::helper('html')->css('jquery.ui.css'));
102	}
103	
104	public function search() {
105		$this->load();	
106		$selectedOptions = $this->request('atSelectOptionID');
107		if (!is_array($selectedOptions)) {
108			$selectedOptions = array();
109		}
110		$this->set('selectedOptions', $selectedOptions);
111	}
112	
113	public function deleteValue() {
114		$db = Loader::db();
115		$db->Execute('delete from atSelectOptionsSelected where avID = ?', array($this->getAttributeValueID()));
116	}
117
118	public function deleteKey() {
119		$db = Loader::db();
120		$db->Execute('delete from atSelectSettings where akID = ?', array($this->attributeKey->getAttributeKeyID()));
121		$r = $db->Execute('select ID from atSelectOptions where akID = ?', array($this->attributeKey->getAttributeKeyID()));
122		while ($row = $r->FetchRow()) {
123			$db->Execute('delete from atSelectOptionsSelected where atSelectOptionID = ?', array($row['ID']));
124		}
125		$db->Execute('delete from atSelectOptions where akID = ?', array($this->attributeKey->getAttributeKeyID()));
126	}
127
128	public function saveForm($data) {
129		$this->load();
130		
131		if ($this->akSelectAllowOtherValues && is_array($data['atSelectNewOption'])) {
132			$options = $this->getOptions();
133						
134			foreach($data['atSelectNewOption'] as $newoption) {
135				// check for duplicates
136				$existing = false;
137				foreach($options as $opt) {
138					if(strtolower(trim($newoption)) == strtolower(trim($opt->getSelectAttributeOptionValue()))) {
139						$existing = $opt;
140						break;
141					}
142				}
143				if($existing instanceof SelectAttributeTypeOption) {
144					$data['atSelectOptionID'][] = $existing->getSelectAttributeOptionID();
145				} else {
146					$optobj = SelectAttributeTypeOption::add($this->attributeKey, $newoption, 1);
147					$data['atSelectOptionID'][] = $optobj->getSelectAttributeOptionID();
148				}
149			}
150		}
151
152		if(is_array($data['atSelectOptionID'])) {
153			$data['atSelectOptionID'] = array_unique($data['atSelectOptionID']);
154		}		
155		$db = Loader::db();
156		$db->Execute('delete from atSelectOptionsSelected where avID = ?', array($this->getAttributeValueID()));
157		if (is_array($data['atSelectOptionID'])) {
158			foreach($data['atSelectOptionID'] as $optID) {
159				if ($optID > 0) {
160					$db->Execute('insert into atSelectOptionsSelected (avID, atSelectOptionID) values (?, ?)', array($this->getAttributeValueID(), $optID));
161					if ($this->akSelectAllowMultipleValues == false) {
162						break;
163					}
164				}
165			}
166		}
167	}
168	
169	// Sets select options for a particular attribute
170	// If the $value == string, then 1 item is selected
171	// if array, then multiple, but only if the attribute in question is a select multiple
172	// Note, items CANNOT be added to the pool (even if the attribute allows it) through this process.
173	public function saveValue($value) {
174		$db = Loader::db();
175		$this->load();
176		$options = array();		
177		
178		if (is_array($value) && $this->akSelectAllowMultipleValues) {
179			foreach($value as $v) {
180				$opt = SelectAttributeTypeOption::getByValue($v, $this->attributeKey);
181				if (is_object($opt)) {
182					$options[] = $opt;	
183				}
184			}
185		} else {
186			if (is_array($value)) {
187				$value = $value[0];
188			}
189			
190			$opt = SelectAttributeTypeOption::getByValue($value, $this->attributeKey);
191			if (is_object($opt)) {
192				$options[] = $opt;	
193			}
194		}
195		
196		$db->Execute('delete from atSelectOptionsSelected where avID = ?', array($this->getAttributeValueID()));
197		if (count($options) > 0) {
198			foreach($options as $opt) {
199				$db->Execute('insert into atSelectOptionsSelected (avID, atSelectOptionID) values (?, ?)', array($this->getAttributeValueID(), $opt->getSelectAttributeOptionID()));
200				if ($this->akSelectAllowMultipleValues == false) {
201					break;
202				}
203			}
204		}
205	}
206
207	
208	public function getDisplayValue() {
209		$list = $this->getSelectedOptions();
210		$html = '';
211		foreach($list as $l) {
212			$html .= $l . '<br/>';
213		}
214		return $html;
215	}
216
217	public function getDisplaySanitizedValue() {
218		$list = $this->getSelectedOptions();
219		$html = '';
220		foreach($list as $l) {
221			$html .= $l->getSelectAttributeOptionValue() . '<br/>';
222		}
223		return $html;
224	}
225	
226	public function validateForm($p) {
227		$this->load();
228		$options = $this->request('atSelectOptionID');
229		if ($this->akSelectAllowMultipleValues) {
230			return count($options) > 0;
231		} else {
232			if ($options[0] != false) {
233				return $options[0] > 0;
234			}
235		}
236		return false;
237	}
238	
239	public function searchForm($list) {
240		$options = $this->request('atSelectOptionID');
241		$optionText = array();
242		$db = Loader::db();
243		$tbl = $this->attributeKey->getIndexedSearchTable();
244		if (!is_array($options)) {
245			return $list;
246		}
247		foreach($options as $id) {
248			if ($id > 0) {
249				$opt = SelectAttributeTypeOption::getByID($id);
250				if (is_object($opt)) {
251					$optionText[] = $opt->getSelectAttributeOptionValue(true);
252					$optionQuery[] = $opt->getSelectAttributeOptionValue(false);
253				}
254			}
255		}
256		if (count($optionText) == 0) {
257			return false;
258		}
259		
260		$i = 0;
261		foreach($optionQuery as $val) {
262			$val = $db->quote('%||' . $val . '||%');
263			$multiString .= 'REPLACE(' . $tbl . '.ak_' . $this->attributeKey->getAttributeKeyHandle() . ', "\n", "||") like ' . $val . ' ';
264			if (($i + 1) < count($optionQuery)) {
265				$multiString .= 'OR ';
266			}
267			$i++;
268		}
269		$list->filter(false, '(' . $multiString . ')');
270		return $list;
271	}
272	
273	public function getValue() {
274		$list = $this->getSelectedOptions();
275		return $list;	
276	}
277	
278    public function getSearchIndexValue() {
279        $str = "\n";
280        $list = $this->getSelectedOptions();
281        foreach($list as $l) {
282            $l = (is_object($l) && method_exists($l,'__toString')) ? $l->__toString() : $l;
283            $str .= $l . "\n";
284        }
285        return $str;
286    }
287	
288	public function getSelectedOptions() {
289		if (!isset($this->akSelectOptionDisplayOrder)) {
290			$this->load();
291		}
292		$db = Loader::db();
293		switch($this->akSelectOptionDisplayOrder) {
294			case 'popularity_desc':
295				$options = $db->GetAll("select ID, value, displayOrder, (select count(s2.atSelectOptionID) from atSelectOptionsSelected s2 where s2.atSelectOptionID = ID) as total from atSelectOptionsSelected inner join atSelectOptions on atSelectOptionsSelected.atSelectOptionID = atSelectOptions.ID where avID = ? order by total desc, value asc", array($this->getAttributeValueID()));
296				break;
297			case 'alpha_asc':
298				$options = $db->GetAll("select ID, value, displayOrder from atSelectOptionsSelected inner join atSelectOptions on atSelectOptionsSelected.atSelectOptionID = atSelectOptions.ID where avID = ? order by value asc", array($this->getAttributeValueID()));
299				break;
300			default:
301				$options = $db->GetAll("select ID, value, displayOrder from atSelectOptionsSelected inner join atSelectOptions on atSelectOptionsSelected.atSelectOptionID = atSelectOptions.ID where avID = ? order by displayOrder asc", array($this->getAttributeValueID()));
302				break;
303		}
304		$db = Loader::db();
305		$list = new SelectAttributeTypeOptionList();
306		foreach($options as $row) {
307			$opt = new SelectAttributeTypeOption($row['ID'], $row['value'], $row['displayOrder']);
308			$list->add($opt);
309		}
310		return $list;
311	}
312	
313	public function action_load_autocomplete_values() {
314		$this->load();
315		$values = array();
316			// now, if the current instance of the attribute key allows us to do autocomplete, we return all the values
317		if ($this->akSelectAllowMultipleValues && $this->akSelectAllowOtherValues) {
318			$options = $this->getOptions($_GET['term'] . '%');
319			foreach($options as $opt) {
320				$values[] = $opt->getSelectAttributeOptionValue();
321			}
322		}
323		print Loader::helper('json')->encode($values);
324	}
325	
326	public function getOptionUsageArray($parentPage = false, $limit = 9999) {
327		$db = Loader::db();
328		$q = "select atSelectOptions.value, atSelectOptionID, count(atSelectOptionID) as total from Pages inner join CollectionVersions on (Pages.cID = CollectionVersions.cID and CollectionVersions.cvIsApproved = 1) inner join CollectionAttributeValues on (CollectionVersions.cID = CollectionAttributeValues.cID and CollectionVersions.cvID = CollectionAttributeValues.cvID) inner join atSelectOptionsSelected on (atSelectOptionsSelected.avID = CollectionAttributeValues.avID) inner join atSelectOptions on atSelectOptionsSelected.atSelectOptionID = atSelectOptions.ID where CollectionAttributeValues.akID = ? ";
329		$v = array($this->attributeKey->getAttributeKeyID());
330		if (is_object($parentPage)) {
331			$v[] = $parentPage->getCollectionID();
332			$q .= "and cParentID = ?";
333		}
334		$q .= " group by atSelectOptionID order by total desc limit " . $limit;
335		$r = $db->Execute($q, $v);
336		$list = new SelectAttributeTypeOptionList();
337		$i = 0;
338		while ($row = $r->FetchRow()) {
339			$opt = new SelectAttributeTypeOption($row['atSelectOptionID'], $row['value'], $i, $row['total']);
340			$list->add($opt);
341			$i++;
342		}		
343		return $list;
344	}
345	
346	/**
347	 * returns a list of available options optionally filtered by an sql $like statement ex: startswith%
348	 * @param string $like
349	 * @return SelectAttributeTypeOptionList
350	 */
351	public function getOptions($like = NULL) {
352		if (!isset($this->akSelectOptionDisplayOrder)) {
353			$this->load();
354		}
355		$db = Loader::db();
356		switch($this->akSelectOptionDisplayOrder) {
357			case 'popularity_desc':
358				if(isset($like) && strlen($like)) {
359					$r = $db->Execute('select ID, value, displayOrder, count(atSelectOptionsSelected.atSelectOptionID) as total 
360						from atSelectOptions left join atSelectOptionsSelected on (atSelectOptions.ID = atSelectOptionsSelected.atSelectOptionID) 
361						where akID = ? AND atSelectOptions.value LIKE ? group by ID order by total desc, value asc', array($this->attributeKey->getAttributeKeyID(),$like));
362				} else {
363					$r = $db->Execute('select ID, value, displayOrder, count(atSelectOptionsSelected.atSelectOptionID) as total 
364						from atSelectOptions left join atSelectOptionsSelected on (atSelectOptions.ID = atSelectOptionsSelected.atSelectOptionID) 
365						where akID = ? group by ID order by total desc, value asc', array($this->attributeKey->getAttributeKeyID()));
366				}
367				break;
368			case 'alpha_asc':
369				if(isset($like) && strlen($like)) {
370					$r = $db->Execute('select ID, value, displayOrder from atSelectOptions where akID = ? AND atSelectOptions.value LIKE ? order by value asc', array($this->attributeKey->getAttributeKeyID(),$like));
371				} else {
372					$r = $db->Execute('select ID, value, displayOrder from atSelectOptions where akID = ? order by value asc', array($this->attributeKey->getAttributeKeyID()));
373				}
374				break;
375			default:
376				if(isset($like) && strlen($like)) {
377					$r = $db->Execute('select ID, value, displayOrder from atSelectOptions where akID = ? AND atSelectOptions.value LIKE ? order by displayOrder asc', array($this->attributeKey->getAttributeKeyID(),$like));
378				} else {
379					$r = $db->Execute('select ID, value, displayOrder from atSelectOptions where akID = ? order by displayOrder asc', array($this->attributeKey->getAttributeKeyID()));
380				}
381				break;
382		}
383		$options = new SelectAttributeTypeOptionList();
384		while ($row = $r->FetchRow()) {
385			$opt = new SelectAttributeTypeOption($row['ID'], $row['value'], $row['displayOrder']);
386			$options->add($opt);
387		}
388		return $options;
389	}
390		
391	public function saveKey($data) {
392		$ak = $this->getAttributeKey();
393		
394		$db = Loader::db();
395
396		$initialOptionSet = $this->getOptions();
397		$selectedPostValues = $this->getSelectValuesFromPost();
398		
399		$akSelectAllowMultipleValues = $data['akSelectAllowMultipleValues'];
400		$akSelectAllowOtherValues = $data['akSelectAllowOtherValues'];
401		$akSelectOptionDisplayOrder = $data['akSelectOptionDisplayOrder'];
402		
403		if ($data['akSelectAllowMultipleValues'] != 1) {
404			$akSelectAllowMultipleValues = 0;
405		}
406		if ($data['akSelectAllowOtherValues'] != 1) {
407			$akSelectAllowOtherValues = 0;
408		}
409		if (!in_array($data['akSelectOptionDisplayOrder'], array('display_asc', 'alpha_asc', 'popularity_desc'))) {
410			$akSelectOptionDisplayOrder = 'display_asc';
411		}
412				
413		// now we have a collection attribute key object above.
414		$db->Replace('atSelectSettings', array(
415			'akID' => $ak->getAttributeKeyID(), 
416			'akSelectAllowMultipleValues' => $akSelectAllowMultipleValues, 
417			'akSelectAllowOtherValues' => $akSelectAllowOtherValues,
418			'akSelectOptionDisplayOrder' => $akSelectOptionDisplayOrder
419		), array('akID'), true);
420		
421		// Now we add the options
422		$newOptionSet = new SelectAttributeTypeOptionList();
423		$displayOrder = 0;
424		foreach($selectedPostValues as $option) {
425			$opt = $option->saveOrCreate($ak);
426			if ($akSelectOptionDisplayOrder == 'display_asc') {
427				$opt->setDisplayOrder($displayOrder);
428			}
429			$newOptionSet->add($opt);
430			$displayOrder++;
431		}
432		
433		// Now we remove all options that appear in the 
434		// old values list but not in the new
435		foreach($initialOptionSet as $iopt) {
436			if (!$newOptionSet->contains($iopt)) {
437				$iopt->delete();
438			}
439		}
440	}
441	
442}
443
444class SelectAttributeTypeOption extends Object {
445
446	public function __construct($ID, $value, $displayOrder, $usageCount = false) {
447		$this->ID = $ID;
448		$this->value = $value;
449		$this->th = Loader::helper('text');
450		$this->displayOrder = $displayOrder;	
451		$this->usageCount = $usageCount;	
452	}
453	
454	public function getSelectAttributeOptionID() {return $this->ID;}
455	public function getSelectAttributeOptionUsageCount() {return $this->usageCount;}
456	public function getSelectAttributeOptionValue($sanitize = true) {
457		if (!$sanitize) {
458			return $this->value;
459		} else {
460			return $this->th->entities($this->value);
461		}
462	}
463	public function getSelectAttributeOptionDisplayOrder() {return $this->displayOrder;}
464	public function getSelectAttributeOptionTemporaryID() {return $this->tempID;}
465	
466	public function __toString() {return $this->value;}
467	
468	public static function add($ak, $option, $isEndUserAdded = 0) {
469		$db = Loader::db();
470		// this works because displayorder starts at zero. So if there are three items, for example, the display order of the NEXT item will be 3.
471		$displayOrder = $db->GetOne('select count(ID) from atSelectOptions where akID = ?', array($ak->getAttributeKeyID()));			
472
473		$v = array($ak->getAttributeKeyID(), $displayOrder, $option, $isEndUserAdded);
474		$db->Execute('insert into atSelectOptions (akID, displayOrder, value, isEndUserAdded) values (?, ?, ?, ?)', $v);
475		
476		return SelectAttributeTypeOption::getByID($db->Insert_ID());
477	}
478	
479	public function setDisplayOrder($num) {
480		$db = Loader::db();
481		$db->Execute('update atSelectOptions set displayOrder = ? where ID = ?', array($num, $this->ID));
482	}
483	
484	public static function getByID($id) {
485		$db = Loader::db();
486		$row = $db->GetRow("select ID, displayOrder, value from atSelectOptions where ID = ?", array($id));
487		if (isset($row['ID'])) {
488			$obj = new SelectAttributeTypeOption($row['ID'], $row['value'], $row['displayOrder']);
489			return $obj;
490		}
491	}
492	
493	public static function getByValue($value, $ak = false) {
494		$db = Loader::db();
495		if (is_object($ak)) {
496			$row = $db->GetRow("select ID, displayOrder, value from atSelectOptions where value = ? and akID = ?", array($value, $ak->getAttributeKeyID()));
497		} else {
498			$row = $db->GetRow("select ID, displayOrder, value from atSelectOptions where value = ?", array($value));
499		}
500		if (isset($row['ID'])) {
501			$obj = new SelectAttributeTypeOption($row['ID'], $row['value'], $row['displayOrder']);
502			return $obj;
503		}
504	}
505	
506	public function delete() {
507		$db = Loader::db();
508		$db->Execute('delete from atSelectOptions where ID = ?', array($this->ID));
509		$db->Execute('delete from atSelectOptionsSelected where atSelectOptionID = ?', array($this->ID));
510	}
511	
512	public function saveOrCreate($ak) {
513		if ($this->tempID != false || $this->ID==0) {
514			return SelectAttributeTypeOption::add($ak, $this->value);
515		} else {
516			$db = Loader::db();
517			$db->Execute('update atSelectOptions set value = ? where ID = ?', array($this->value, $this->ID));
518			return SelectAttributeTypeOption::getByID($this->ID);
519		}
520	}
521	
522}
523
524class SelectAttributeTypeOptionList extends Object implements Iterator {
525
526	private $options = array();
527	
528	public function add(SelectAttributeTypeOption $opt) {
529		$this->options[] = $opt;
530	}
531	
532	public function rewind() {
533		reset($this->options);
534	}
535	
536	public function current() {
537		return current($this->options);
538	}
539	
540	public function key() {
541		return key($this->options);
542	}
543	
544	public function next() {
545		next($this->options);
546	}
547	
548	public function valid() {
549		return $this->current() !== false;
550	}
551	
552	public function count() {return count($this->options);}
553	
554	public function contains(SelectAttributeTypeOption $opt) {
555		foreach($this->options as $o) {
556			if ($o->getSelectAttributeOptionID() == $opt->getSelectAttributeOptionID()) {
557				return true;
558			}
559		}
560		
561		return false;
562	}
563	
564	public function get($index) {
565		return $this->options[$index];
566	}
567	
568	public function getOptions() {
569		return $this->options;
570	}
571	
572	public function __toString() {
573		$str = '';
574		$i = 0;
575		foreach($this->options as $opt) {
576			$str .= $opt->getSelectAttributeOptionValue();
577			$i++;
578			if ($i < count($this->options)) {
579				$str .= "\n";
580			}
581		}
582		return $str;
583	}
584
585
586}