1: <?php
2:
3: namespace Alpha\View\Widget;
4:
5: use Alpha\Util\Config\ConfigProvider;
6: use Alpha\Util\Logging\Logger;
7: use Alpha\Util\Security\SecurityUtils;
8: use Alpha\Util\Http\Session\SessionProviderFactory;
9: use Alpha\Util\Http\Request;
10: use Alpha\Model\Type\Relation;
11: use Alpha\Exception\IllegalArguementException;
12: use Alpha\Controller\Controller;
13: use Alpha\Controller\Front\FrontController;
14:
15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
57: class RecordSelector
58: {
59: 60: 61: 62: 63: 64: 65:
66: private $relationObject = null;
67:
68: 69: 70: 71: 72: 73: 74:
75: private $label;
76:
77: 78: 79: 80: 81: 82: 83: 84:
85: private $accessingClassName;
86:
87: 88: 89: 90: 91: 92: 93:
94: private $onloadJS = '';
95:
96: 97: 98: 99: 100: 101: 102:
103: private $name;
104:
105: 106: 107: 108: 109: 110: 111:
112: private static $logger = null;
113:
114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125:
126: public function __construct($relation, $label = '', $name = '', $accessingClassName = '')
127: {
128: self::$logger = new Logger('RecordSelector');
129: self::$logger->debug('>>__construct(relation=['.$relation.'], label=['.$label.'], name=['.$name.'], accessingClassName=['.$accessingClassName.'])');
130:
131: if (!$relation instanceof Relation) {
132: throw new IllegalArguementException('Invalid Relation object provided to the RecordSelector constructor!');
133: }
134:
135: $this->relationObject = $relation;
136: $this->label = $label;
137: $this->name = $name;
138: $this->accessingClassName = $accessingClassName;
139:
140: self::$logger->debug('<<__construct');
141: }
142:
143: 144: 145: 146: 147: 148: 149: 150: 151: 152:
153: public function render($expanded = false, $buttons = true)
154: {
155: self::$logger->debug('>>render(expanded=['.$expanded.'], buttons=['.$buttons.'])');
156:
157: $config = ConfigProvider::getInstance();
158: $sessionProvider = $config->get('session.provider.name');
159: $session = SessionProviderFactory::getInstance($sessionProvider);
160:
161: $fieldname = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt($this->name)) : $this->name);
162:
163: $html = '';
164:
165:
166: if ($this->relationObject->getRelationType() == 'MANY-TO-ONE') {
167:
168: $inputBoxValue = $this->relationObject->getRelatedClassDisplayFieldValue();
169:
170: $html .= '<div class="form-group">';
171: $html .= '<label for="'.$this->name.'_display">'.$this->label.'</label>';
172:
173: $html .= '<input type="text" size="70" class="form-control" name="'.$this->name.'_display" id="'.$this->name.'_display" value="'.$inputBoxValue.'" disabled/>';
174:
175: $js = " if(window.jQuery) {
176: window.jQuery.dialog = new BootstrapDialog({
177: title: 'Please select',
178: message: 'Loading...',
179: onshow: function(dialogRef){
180: dialogRef.getModalBody().load('".$config->get('app.url')."/recordselector/12m/'+document.getElementById('".$fieldname."').value+'/".$this->name.'/'.urlencode($this->relationObject->getRelatedClass()).'/'.$this->relationObject->getRelatedClassField().'/'.$this->relationObject->getRelatedClassDisplayField()."');
181: },
182: buttons: [
183: {
184: icon: 'glyphicon glyphicon-remove',
185: label: 'Cancel',
186: cssClass: 'btn btn-default btn-xs',
187: action: function(dialogItself){
188: dialogItself.close();
189: }
190: }
191: ]
192: });
193: window.jQuery.dialog.open();
194: }";
195:
196: $tmp = new Button($js, 'Select', 'relBut', '', 'glyphicon-check');
197: $html .= '<div class="centered lower">'.$tmp->render().'</div>';
198:
199:
200: $html .= '<input type="hidden" name="'.$fieldname.'" id="'.$fieldname.'" value="'.$this->relationObject->getValue().'"/>';
201:
202: if ($this->relationObject->getRule() != '') {
203: $html .= '<input type="hidden" id="'.$fieldname.'_msg" value="'.$this->relationObject->getHelper().'"/>';
204: $html .= '<input type="hidden" id="'.$fieldname.'_rule" value="'.$this->relationObject->getRule().'"/>';
205: }
206:
207: $html .= '</div>';
208: }
209:
210:
211: if ($this->relationObject->getRelationType() == 'ONE-TO-MANY') {
212: $objects = $this->relationObject->getRelatedObjects();
213:
214: if (count($objects) > 0) {
215:
216: if ($this->name == 'tags' && $this->relationObject->getRelatedClass() == 'TagObject') {
217: $html .= '<p><strong>'.$this->label.':</strong>';
218:
219: foreach ($objects as $tag) {
220: $html .= ' <a href="'.$config->get('app.url').'/search/'.$tag->get('content').'">'.$tag->get('content').'</a>';
221: }
222:
223: $html .= '</p>';
224: } else {
225: $html .= '<div><strong>'.$this->label.':</strong>';
226: if ($buttons) {
227: $html .= '<div class="spread">';
228: $tmp = new Button("document.getElementById('relation_field_".$this->name."').style.display = '';", 'Show', $this->name.'DisBut', '', 'glyphicon-list');
229: $html .= $tmp->render();
230: $tmp = new Button("document.getElementById('relation_field_".$this->name."').style.display = 'none';", 'Hide', $this->name.'HidBut', '', 'glyphicon-minus');
231: $html .= $tmp->render();
232: $html .= '</div>';
233: }
234: $html .= '</div>';
235:
236: $html .= '<div id="relation_field_'.$this->name.'" style="display:'.($expanded ? '' : 'none').';">';
237:
238: $customViewControllerName = Controller::getCustomControllerName(get_class($objects[0]), 'view');
239: $customEditControllerName = Controller::getCustomControllerName(get_class($objects[0]), 'edit');
240:
241: $request = new Request(array('method' => 'GET'));
242: $URI = $request->getURI();
243:
244: foreach ($objects as $obj) {
245:
246:
247: if (mb_strpos($URI, '/tk/') !== false) {
248: $viewURL = FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.get_class($obj).'&ActiveRecordOID='.$obj->getOID());
249: $editURL = FrontController::generateSecureURL('act=Alpha\Controller\ActiveRecordController&ActiveRecordType='.get_class($obj).'&ActiveRecordOID='.$obj->getOID().'&view=edit');
250: } else {
251: if (isset($customViewControllerName)) {
252: if ($config->get('app.use.mod.rewrite')) {
253: $viewURL = $config->get('app.url').$customViewControllerName.'/oid/'.$obj->getOID();
254: } else {
255: $viewURL = $config->get('app.url').'controller/'.$customViewControllerName.'.php?oid='.$obj->getOID();
256: }
257: } else {
258: $viewURL = $config->get('app.url').'alpha/controller/Detail.php?bo='.get_class($obj).'&oid='.$obj->getOID();
259: }
260: if (isset($customEditControllerName)) {
261: if ($config->get('app.use.mod.rewrite')) {
262: $editURL = $config->get('app.url').$customEditControllerName.'/oid/'.$obj->getOID();
263: } else {
264: $editURL = $config->get('app.url').'controller/'.$customEditControllerName.'.php?oid='.$obj->getOID();
265: }
266: } else {
267: $editURL = $config->get('app.url').'alpha/controller/Edit.php?bo='.get_class($obj).'&oid='.$obj->getOID();
268: }
269: }
270:
271: 272: 273: 274:
275: $headerFields = $this->relationObject->getRelatedClassHeaderFields();
276: if (count($headerFields) > 0) {
277: foreach ($headerFields as $field) {
278: $label = $obj->getDataLabel($field);
279: $value = $obj->get($field);
280:
281: if ($field == 'created_by' || $field == 'updated_by') {
282: $person = new PersonObject();
283: $person->load($value);
284: $value = $person->getDisplayName();
285: }
286:
287: $html .= '<em>'.$label.': </em>'.$value.' ';
288: }
289:
290: if ($obj->getCreateTS() != $obj->getUpdateTS()) {
291: try {
292: $html .= '<em>'.$obj->getDataLabel('updated_ts').': </em>'.$obj->get('updated_ts');
293: } catch (IllegalArguementException $e) {
294: $html .= '<em>Updated: </em>'.$obj->get('updated_ts');
295: }
296: }
297: } else {
298: $html .= '<em>'.$obj->getDataLabel('OID').': </em>'.$obj->get('OID');
299: }
300:
301: $value = str_replace("\n", '<br>', $obj->get($this->relationObject->getRelatedClassDisplayField()));
302: $html .= '<p>'.$value.'</p>';
303:
304: $html .= '<div class="centered">';
305: $html .= '<a href="'.$viewURL.'">View</a>';
306:
307: if ($session->get('currentUser') != null && $session->get('currentUser')->getOID() == $obj->getCreatorId()) {
308: $html .= ' <a href="'.$editURL.'">Edit</a>';
309: }
310: $html .= '</div>';
311: }
312: $html .= '</div>';
313: }
314: }
315: }
316:
317:
318: if ($this->relationObject->getRelationType() == 'MANY-TO-MANY') {
319:
320: $inputBoxValue = $this->relationObject->getRelatedClassDisplayFieldValue($this->accessingClassName);
321:
322: $inputBoxValue = str_replace(',', "\n", $inputBoxValue);
323:
324: $html .= '<div class="form-group">';
325: $html .= '<label for="'.$this->name.'_display">'.$this->label.'</label>';
326:
327: $html .= '<textarea id="'.$this->name.'_display" class="form-control" rows="5" readonly>';
328: $html .= $inputBoxValue;
329: $html .= '</textarea>';
330:
331: $fieldname1 = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt($this->name)) : $this->name);
332: $fieldname2 = ($config->get('security.encrypt.http.fieldnames') ? base64_encode(SecurityUtils::encrypt($this->name.'_OID')) : $this->name.'_OID');
333:
334: $js = "if(window.jQuery) {
335: BootstrapDialog.show({
336: title: 'Please select',
337: message: 'Loading...',
338: onshow: function(dialogRef){
339: dialogRef.getModalBody().load('".$config->get('app.url')."/recordselector/m2m/'+document.getElementById('".$fieldname2."').value+'/".$this->name.'/'.urlencode($this->relationObject->getRelatedClass('left')).'/'.$this->relationObject->getRelatedClassDisplayField('left').'/'.urlencode($this->relationObject->getRelatedClass('right')).'/'.$this->relationObject->getRelatedClassDisplayField('right').'/'.urlencode($this->accessingClassName)."/'+document.getElementById('".$fieldname1."').value);
340: },
341: buttons: [
342: {
343: icon: 'glyphicon glyphicon-remove',
344: label: 'Cancel',
345: cssClass: 'btn btn-default btn-xs',
346: action: function(dialogItself){
347: dialogItself.close();
348: }
349: },
350: {
351: icon: 'glyphicon glyphicon-ok',
352: label: 'Okay',
353: cssClass: 'btn btn-default btn-xs',
354: action: function(dialogItself) {
355: setParentFieldValues();
356: $('[id=\'".$this->name."_display\']').blur();
357: dialogItself.close();
358: }
359: }
360: ]
361: });
362: }";
363:
364: $tmp = new Button($js, 'Select', 'relBut', '', 'glyphicon-check');
365: $html .= '<div class="centered lower">'.$tmp->render().'</div>';
366:
367: $html .= '</div>';
368:
369:
370: $html .= '<input type="hidden" name="'.$fieldname2.'" id="'.$fieldname2.'" value="'.$this->relationObject->getValue().'"/>';
371:
372:
373: if ($this->relationObject->getSide($this->accessingClassName) == 'left') {
374: $lookupOIDs = $this->relationObject->getLookup()->loadAllFieldValuesByAttribute('leftID', $this->relationObject->getValue(), 'rightID', 'DESC');
375: } else {
376: $lookupOIDs = $this->relationObject->getLookup()->loadAllFieldValuesByAttribute('rightID', $this->relationObject->getValue(), 'leftID', 'DESC');
377: }
378:
379: $html .= '<input type="hidden" name="'.$fieldname1.'" id="'.$fieldname1.'" value="'.implode(',', $lookupOIDs).'"/>';
380: }
381:
382: self::$logger->debug('<<__render [html]');
383:
384: return $html;
385: }
386:
387: 388: 389: 390: 391: 392: 393: 394: 395: 396:
397: public function renderSelector($fieldname, $lookupOIDs = array())
398: {
399: self::$logger->debug('>>renderSelector(fieldname=['.$fieldname.'], lookupOIDs=['.var_export($lookupOIDs, true).'])');
400:
401: $config = ConfigProvider::getInstance();
402:
403: $html = '<script language="JavaScript">
404: var selectedOIDs = new Object();
405:
406: function toggelOID(oid, displayValue, isSelected) {
407: if(isSelected)
408: selectedOIDs[oid] = displayValue;
409: else
410: delete selectedOIDs[oid];
411: }
412:
413: function setParentFieldValues() {
414: var OIDs;
415: var displayValues;
416:
417: for(key in selectedOIDs) {
418: if(OIDs == null)
419: OIDs = key;
420: else
421: OIDs = OIDs + \',\' + key;
422:
423: if(displayValues == null)
424: displayValues = selectedOIDs[key];
425: else
426: displayValues = displayValues + \'\\n\' + selectedOIDs[key];
427: }
428:
429: if(OIDs == null) {
430: document.getElementById(\''.$fieldname.'\').value = "00000000000";
431: document.getElementById(\''.$fieldname.'_display\').value = "";
432: }else{
433: document.getElementById(\''.$fieldname.'\').value = OIDs;
434: document.getElementById(\''.$fieldname.'_display\').value = displayValues;
435: }
436: }
437:
438: </script>';
439:
440: if ($this->relationObject->getRelationType() == 'MANY-TO-MANY') {
441: $classNameLeft = $this->relationObject->getRelatedClass('left');
442: $classNameRight = $this->relationObject->getRelatedClass('right');
443:
444: if ($this->accessingClassName == $classNameLeft) {
445: $tmpObject = new $classNameRight();
446: $fieldName = $this->relationObject->getRelatedClassDisplayField('right');
447: $fieldLabel = $tmpObject->getDataLabel($fieldName);
448: $oidLabel = $tmpObject->getDataLabel('OID');
449:
450: $objects = $tmpObject->loadAll(0, 0, 'OID', 'ASC', true);
451:
452: self::$logger->debug('['.count($objects).'] related ['.$classNameLeft.'] objects loaded');
453: } else {
454: $tmpObject = new $classNameLeft();
455: $fieldName = $this->relationObject->getRelatedClassDisplayField('left');
456: $fieldLabel = $tmpObject->getDataLabel($fieldName);
457: $oidLabel = $tmpObject->getDataLabel('OID');
458:
459: $objects = $tmpObject->loadAll(0, 0, 'OID', 'ASC', true);
460:
461: self::$logger->debug('['.count($objects).'] related ['.$classNameLeft.'] objects loaded');
462: }
463:
464: $html .= '<table cols="3" class="table table-bordered">';
465: $html .= '<tr>';
466: $html .= '<th>'.$oidLabel.'</th>';
467: $html .= '<th>'.$fieldLabel.'</th>';
468: $html .= '<th>Connect?</th>';
469: $html .= '</tr>';
470:
471: foreach ($objects as $obj) {
472: $html .= '<tr>';
473: $html .= '<td width="20%">';
474: $html .= $obj->getOID();
475: $html .= '</td>';
476: $html .= '<td width="60%">';
477: $html .= $obj->get($fieldName);
478: $html .= '</td>';
479: $html .= '<td width="20%">';
480:
481: if (in_array($obj->getOID(), $lookupOIDs)) {
482: $this->onloadJS .= 'toggelOID(\''.$obj->getOID().'\',\''.$obj->get($fieldName).'\',true);';
483: $html .= '<input name = "'.$obj->getOID().'" type="checkbox" checked onclick="toggelOID(\''.$obj->getOID().'\',\''.$obj->get($fieldName).'\',this.checked);"/>';
484: } else {
485: $html .= '<input name = "'.$obj->getOID().'" type="checkbox" onclick="toggelOID(\''.$obj->getOID().'\',\''.$obj->get($fieldName).'\',this.checked);"/>';
486: }
487: $html .= '</td>';
488: $html .= '</tr>';
489: }
490: $html .= '</table>';
491: } else {
492: $className = $this->relationObject->getRelatedClass();
493:
494: $tmpObject = new $className();
495: $label = $tmpObject->getDataLabel($this->relationObject->getRelatedClassDisplayField());
496: $oidLabel = $tmpObject->getDataLabel('OID');
497:
498: $objects = $tmpObject->loadAll(0, 0, 'OID', 'DESC');
499:
500: $html = '<table cols="3" width="100%" class="bordered">';
501: $html .= '<tr>';
502: $html .= '<th>'.$oidLabel.'</th>';
503: $html .= '<th>'.$label.'</th>';
504: $html .= '<th>Connect?</th>';
505: $html .= '</tr>';
506:
507: foreach ($objects as $obj) {
508: $html .= '<tr>';
509: $html .= '<td width="20%">';
510: $html .= $obj->getOID();
511: $html .= '</td>';
512: $html .= '<td width="60%">';
513: $html .= $obj->get($this->relationObject->getRelatedClassDisplayField());
514: $html .= '</td>';
515: $html .= '<td width="20%">';
516: if ($obj->getOID() == $this->relationObject->getValue()) {
517: $html .= '<img src="'.$config->get('app.url').'/images/icons/accept_ghost.png"/>';
518: } else {
519: $tmp = new Button("document.getElementById('".$fieldname."').value = '".$obj->getOID()."'; document.getElementById('".$fieldname."_display').value = '".$obj->get($this->relationObject->getRelatedClassDisplayField())."'; $('[Id=".$fieldname."_display]').blur(); window.jQuery.dialog.close();", '', 'selBut', $config->get('app.url').'/images/icons/accept.png');
520: $html .= $tmp->render();
521: }
522: $html .= '</td>';
523: $html .= '</tr>';
524: }
525: $html .= '</table>';
526: }
527:
528: $html .= '<script type="text/javascript">'.
529: '$(document).ready(function() {';
530:
531: $html .= $this->onloadJS;
532:
533: $html .= '});</script>';
534:
535: self::$logger->debug('<<renderSelector[html]');
536:
537: return $html;
538: }
539: }
540: