2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
39 require_once('include/EditView/SugarVCR.php');
41 * Data set for ListView
46 var $additionalDetails = true;
47 var $listviewName = null;
48 var $additionalDetailsAllow = null;
49 var $additionalDetailsAjax = true; // leave this true when using filter fields
50 var $additionalDetailsFieldToAdd = 'NAME'; // where the span will be attached to
53 * If you want overwrite the query for the count of the listview set this to your query
54 * otherwise leave it empty and it will use SugarBean::create_list_count_query
56 var $count_query = '';
59 * Constructor sets the limitName to look up the limit in $sugar_config
61 * @return ListViewData
63 function ListViewData() {
64 $this->limitName = 'list_max_entries_per_page';
65 $this->db = &DBManagerFactory::getInstance('listviews');
69 * checks the request for the order by and if that is not set then it checks the session for it
71 * @return array containing the keys orderBy => field being ordered off of and sortOrder => the sort order of that field
73 function getOrderBy($orderBy = '', $direction = '') {
74 if (!empty($orderBy) || !empty($_REQUEST[$this->var_order_by])) {
75 if(!empty($_REQUEST[$this->var_order_by])) {
77 $orderBy = $_REQUEST[$this->var_order_by];
78 if(!empty($_REQUEST['lvso']) && (empty($_SESSION['lvd']['last_ob']) || strcmp($orderBy, $_SESSION['lvd']['last_ob']) == 0) ){
79 $direction = $_REQUEST['lvso'];
82 $_SESSION[$this->var_order_by] = array('orderBy'=>$orderBy, 'direction'=> $direction);
83 $_SESSION['lvd']['last_ob'] = $orderBy;
86 $userPreferenceOrder = $GLOBALS['current_user']->getPreference('listviewOrder', $this->var_name);
87 if(!empty($_SESSION[$this->var_order_by])) {
88 $orderBy = $_SESSION[$this->var_order_by]['orderBy'];
89 $direction = $_SESSION[$this->var_order_by]['direction'];
90 } elseif (!empty($userPreferenceOrder)) {
91 $orderBy = $userPreferenceOrder['orderBy'];
92 $direction = $userPreferenceOrder['sortOrder'];
94 $orderBy = 'date_entered';
98 if(!empty($direction)) {
99 if(strtolower($direction) == "desc") {
105 return array('orderBy' => $orderBy, 'sortOrder' => $direction);
109 * gets the reverse of the sort order for use on links to reverse a sort order from what is currently used
111 * @param STRING (ASC or DESC) $current_order
112 * @return STRING (ASC or DESC)
114 function getReverseSortOrder($current_order){
115 return (strcmp(strtolower($current_order), 'asc') == 0)?'DESC':'ASC';
118 * gets the limit of how many rows to show per page
120 * @return INT (the limit)
122 function getLimit() {
123 return $GLOBALS['sugar_config'][$this->limitName];
127 * returns the current offset
129 * @return INT (current offset)
131 function getOffset() {
132 return (!empty($_REQUEST[$this->var_offset])) ? $_REQUEST[$this->var_offset] : 0;
136 * generates the base url without
137 * any files in the block variables will not be part of the url
139 * @return Array (the base url as an array)
141 protected function getBaseQuery()
145 $blockVariables = array('mass', 'uid', 'massupdate', 'delete', 'merge', 'selectCount',$this->var_order_by, $this->var_offset, 'lvso', 'sortOrder', 'orderBy', 'request_data', 'current_query_by_page');
146 foreach($beanList as $bean)
148 $blockVariables[] = 'Home2_'.strtoupper($bean).'_ORDER_BY';
150 $blockVariables[] = 'Home2_CASE_ORDER_BY';
152 // Added mostly for the unit test runners, which may not have these superglobals defined
153 $params = array_merge($_POST, $_GET);
154 $params = array_diff_key($params, array_flip($blockVariables));
160 * based off of a base name it sets base, offset, and order by variable names to retrieve them from requests and sessions
162 * @param unknown_type $baseName
164 function setVariableName($baseName, $where, $listviewName = null){
166 $module = (!empty($listviewName)) ? $listviewName: $_REQUEST['module'];
167 $this->var_name = $module .'2_'. strtoupper($baseName);
169 $this->var_order_by = $this->var_name .'_ORDER_BY';
170 $this->var_offset = $this->var_name . '_offset';
171 $timestamp = sugar_microtime();
172 $this->stamp = $timestamp;
174 $_SESSION[$module .'2_QUERY_QUERY'] = $where;
176 $_SESSION[strtoupper($baseName) . "_FROM_LIST_VIEW"] = $timestamp;
177 $_SESSION[strtoupper($baseName) . "_DETAIL_NAV_HISTORY"] = false;
180 function getTotalCount($main_query){
181 if(!empty($this->count_query)){
182 $count_query = $this->count_query;
184 $count_query = SugarBean::create_list_count_query($main_query);
186 $result = $this->db->query($count_query);
187 if($row = $this->db->fetchByAssoc($result)){
194 * takes in a seed and creates the list view query based off of that seed
195 * if the $limit value is set to -1 then it will use the default limit and offset values
197 * it will return an array with two key values
198 * 1. 'data'=> this is an array of row data
199 * 2. 'pageData'=> this is an array containg three values
200 * a.'ordering'=> array('orderBy'=> the field being ordered by , 'sortOrder'=> 'ASC' or 'DESC')
201 * b.'urls'=>array('baseURL'=>url used to generate other urls ,
202 * 'orderBy'=> the base url for order by
203 * //the following may not be set (so check empty to see if they are set)
204 * 'nextPage'=> the url for the next group of results,
205 * 'prevPage'=> the url for the prev group of results,
206 * 'startPage'=> the url for the start of the group,
207 * 'endPage'=> the url for the last set of results in the group
208 * c.'offsets'=>array(
209 * 'current'=>current offset
210 * 'next'=> next group offset
211 * 'prev'=> prev group offset
212 * 'end'=> the offset of the last group
213 * 'total'=> the total count (only accurate if totalCounted = true otherwise it is either the total count if less than the limit or the total count + 1 )
214 * 'totalCounted'=> if a count query was used to get the total count
216 * @param SugarBean $seed
217 * @param string $where
218 * @param int:0 $offset
219 * @param int:-1 $limit
220 * @param string[]:array() $filter_fields
221 * @param array:array() $params
222 * Potential $params are
223 $params['distinct'] = use distinct key word
224 $params['include_custom_fields'] = (on by default)
225 $params['custom_XXXX'] = append custom statements to query
226 * @param string:'id' $id_field
227 * @return array('data'=> row data, 'pageData' => page data information, 'query' => original query string)
229 function getListViewData($seed, $where, $offset=-1, $limit = -1, $filter_fields=array(),$params=array(),$id_field = 'id',$singleSelect=true) {
230 global $current_user;
231 SugarVCR::erase($seed->module_dir);
232 $this->seed =& $seed;
233 $totalCounted = empty($GLOBALS['sugar_config']['disable_count_query']);
234 $_SESSION['MAILMERGE_MODULE_FROM_LISTVIEW'] = $seed->module_dir;
235 if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup'){
236 $_SESSION['MAILMERGE_MODULE'] = $seed->module_dir;
239 $this->setVariableName($seed->object_name, $where, $this->listviewName);
241 $this->seed->id = '[SELECT_ID_LIST]';
243 // if $params tell us to override all ordering
244 if(!empty($params['overrideOrder']) && !empty($params['orderBy'])) {
245 $order = $this->getOrderBy(strtolower($params['orderBy']), (empty($params['sortOrder']) ? '' : $params['sortOrder'])); // retreive from $_REQUEST
248 $order = $this->getOrderBy(); // retreive from $_REQUEST
251 // still empty? try to use settings passed in $param
252 if(empty($order['orderBy']) && !empty($params['orderBy'])) {
253 $order['orderBy'] = $params['orderBy'];
254 $order['sortOrder'] = (empty($params['sortOrder']) ? '' : $params['sortOrder']);
257 //rrs - bug: 21788. Do not use Order by stmts with fields that are not in the query.
258 // Bug 22740 - Tweak this check to strip off the table name off the order by parameter.
259 // Samir Gandhi : Do not remove the report_cache.date_modified condition as the report list view is broken
260 $orderby = $order['orderBy'];
261 if (strpos($order['orderBy'],'.') && ($order['orderBy'] != "report_cache.date_modified")) {
262 $orderby = substr($order['orderBy'],strpos($order['orderBy'],'.')+1);
264 if ($orderby != 'date_entered' && !in_array($orderby, array_keys($filter_fields))) {
265 $order['orderBy'] = '';
266 $order['sortOrder'] = '';
269 if (empty($order['orderBy'])) {
272 $orderBy = $order['orderBy'] . ' ' . $order['sortOrder'];
273 //wdong, Bug 25476, fix the sorting problem of Oracle.
274 if (isset($params['custom_order_by_override']['ori_code']) && $order['orderBy'] == $params['custom_order_by_override']['ori_code'])
275 $orderBy = $params['custom_order_by_override']['custom_code'] . ' ' . $order['sortOrder'];
278 if (empty($params['skipOrderSave'])) { // don't save preferences if told so
279 $current_user->setPreference('listviewOrder', $order, 0, $this->var_name); // save preference
282 // If $params tells us to override for the special last_name, first_name sorting
283 if (!empty($params['overrideLastNameOrder']) && $order['orderBy'] == 'last_name') {
284 $orderBy = 'last_name '.$order['sortOrder'].', first_name '.$order['sortOrder'];
287 $ret_array = $seed->create_new_list_query($orderBy, $where, $filter_fields, $params, 0, '', true, $seed, $singleSelect);
288 $ret_array['inner_join'] = '';
289 if (!empty($this->seed->listview_inner_join)) {
290 $ret_array['inner_join'] = ' ' . implode(' ', $this->seed->listview_inner_join) . ' ';
293 if(!is_array($params)) $params = array();
294 if(!isset($params['custom_select'])) $params['custom_select'] = '';
295 if(!isset($params['custom_from'])) $params['custom_from'] = '';
296 if(!isset($params['custom_where'])) $params['custom_where'] = '';
297 if(!isset($params['custom_order_by'])) $params['custom_order_by'] = '';
298 $main_query = $ret_array['select'] . $params['custom_select'] . $ret_array['from'] . $params['custom_from'] . $ret_array['inner_join']. $ret_array['where'] . $params['custom_where'] . $ret_array['order_by'] . $params['custom_order_by'];
299 //C.L. - Fix for 23461
300 if(empty($_REQUEST['action']) || $_REQUEST['action'] != 'Popup') {
301 $_SESSION['export_where'] = $ret_array['where'];
304 $result = $this->db->query($main_query);
308 $limit = $this->getLimit();
310 $dyn_offset = $this->getOffset();
311 if($dyn_offset > 0 || !is_int($dyn_offset))$offset = $dyn_offset;
313 if(strcmp($offset, 'end') == 0){
314 $totalCount = $this->getTotalCount($main_query);
315 $offset = (floor(($totalCount -1) / $limit)) * $limit;
317 if($this->seed->ACLAccess('ListView')) {
318 $result = $this->db->limitQuery($main_query, $offset, $limit + 1);
335 while(($row = $this->db->fetchByAssoc($result)) != null)
339 $id_list .= ',\''.$row[$id_field].'\'';
340 $idIndex[$row[$id_field]][] = count($rows);
341 $rows[] = $seed->convertRow($row);
346 if (!empty($id_list))
348 $id_list = '('.substr($id_list, 1).')';
351 SugarVCR::store($this->seed->module_dir, $main_query);
353 //NOW HANDLE SECONDARY QUERIES
354 if(!empty($ret_array['secondary_select'])) {
355 $secondary_query = $ret_array['secondary_select'] . $ret_array['secondary_from'] . ' WHERE '.$this->seed->table_name.'.id IN ' .$id_list;
356 if(isset($ret_array['order_by']))
358 $secondary_query .= ' ' . $ret_array['order_by'];
361 $secondary_result = $this->db->query($secondary_query);
363 $ref_id_count = array();
364 while($row = $this->db->fetchByAssoc($secondary_result)) {
366 $ref_id_count[$row['ref_id']][] = true;
367 foreach($row as $name=>$value) {
368 //add it to every row with the given id
369 foreach($idIndex[$row['ref_id']] as $index){
370 $rows[$index][$name]=$value;
375 $rows_keys = array_keys($rows);
376 foreach($rows_keys as $key)
378 $rows[$key]['secondary_select_count'] = count($ref_id_count[$rows[$key]['ref_id']]);
382 // retrieve parent names
383 if(!empty($filter_fields['parent_name']) && !empty($filter_fields['parent_id']) && !empty($filter_fields['parent_type'])) {
384 foreach($idIndex as $id => $rowIndex) {
385 if(!isset($post_retrieve[$rows[$rowIndex[0]]['parent_type']])) {
386 $post_retrieve[$rows[$rowIndex[0]]['parent_type']] = array();
388 if(!empty($rows[$rowIndex[0]]['parent_id'])) $post_retrieve[$rows[$rowIndex[0]]['parent_type']][] = array('child_id' => $id , 'parent_id'=> $rows[$rowIndex[0]]['parent_id'], 'parent_type' => $rows[$rowIndex[0]]['parent_type'], 'type' => 'parent');
390 if(isset($post_retrieve)) {
391 $parent_fields = $seed->retrieve_parent_fields($post_retrieve);
392 foreach($parent_fields as $child_id => $parent_data) {
393 //add it to every row with the given id
394 foreach($idIndex[$child_id] as $index){
395 $rows[$index]['parent_name']= $parent_data['parent_name'];
404 while($row = current($rows)){
407 $dataIndex = count($data);
409 $temp->setupCustomFields($temp->module_dir);
410 $temp->loadFromRow($row);
411 if (empty($this->seed->assigned_user_id) && !empty($temp->assigned_user_id)) {
412 $this->seed->assigned_user_id = $temp->assigned_user_id;
414 if($idIndex[$row[$id_field]][0] == $dataIndex){
415 $pageData['tag'][$dataIndex] = $temp->listviewACLHelper();
417 $pageData['tag'][$dataIndex] = $pageData['tag'][$idIndex[$row[$id_field]][0]];
419 $data[$dataIndex] = $temp->get_list_view_data($filter_fields);
420 $detailViewAccess = $temp->ACLAccess('DetailView');
421 $editViewAccess = $temp->ACLAccess('EditView');
422 $pageData['rowAccess'][$dataIndex] = array('view' => $detailViewAccess, 'edit' => $editViewAccess);
423 $additionalDetailsAllow = $this->additionalDetails && $detailViewAccess && (file_exists(
424 'modules/' . $temp->module_dir . '/metadata/additionalDetails.php'
425 ) || file_exists('custom/modules/' . $temp->module_dir . '/metadata/additionalDetails.php'));
426 $additionalDetailsEdit = $editViewAccess;
427 if($additionalDetailsAllow) {
428 if($this->additionalDetailsAjax) {
429 $ar = $this->getAdditionalDetailsAjax($data[$dataIndex]['ID']);
432 $additionalDetailsFile = 'modules/' . $this->seed->module_dir . '/metadata/additionalDetails.php';
433 if(file_exists('custom/modules/' . $this->seed->module_dir . '/metadata/additionalDetails.php')){
434 $additionalDetailsFile = 'custom/modules/' . $this->seed->module_dir . '/metadata/additionalDetails.php';
436 require_once($additionalDetailsFile);
437 $ar = $this->getAdditionalDetails($data[$dataIndex],
438 (empty($this->additionalDetailsFunction) ? 'additionalDetails' : $this->additionalDetailsFunction) . $this->seed->object_name,
439 $additionalDetailsEdit);
441 $pageData['additionalDetails'][$dataIndex] = $ar['string'];
442 $pageData['additionalDetails']['fieldToAddTo'] = $ar['fieldToAddTo'];
450 if($count > $limit) {
451 $nextOffset = $offset + $limit;
455 $prevOffset = $offset - $limit;
456 if($prevOffset < 0)$prevOffset = 0;
458 $totalCount = $count + $offset;
460 if( $count >= $limit && $totalCounted){
461 $totalCount = $this->getTotalCount($main_query);
463 SugarVCR::recordIDs($this->seed->module_dir, array_keys($idIndex), $offset, $totalCount);
464 $module_names = array(
465 'Prospects' => 'Targets'
467 $endOffset = (floor(($totalCount - 1) / $limit)) * $limit;
468 $pageData['ordering'] = $order;
469 $pageData['ordering']['sortOrder'] = $this->getReverseSortOrder($pageData['ordering']['sortOrder']);
470 //get url parameters as an array
471 $pageData['queries'] = $this->generateQueries($pageData['ordering']['sortOrder'], $offset, $prevOffset, $nextOffset, $endOffset, $totalCounted);
472 //join url parameters from array to a string
473 $pageData['urls'] = $this->generateURLS($pageData['queries']);
474 $pageData['offsets'] = array( 'current'=>$offset, 'next'=>$nextOffset, 'prev'=>$prevOffset, 'end'=>$endOffset, 'total'=>$totalCount, 'totalCounted'=>$totalCounted);
475 $pageData['bean'] = array('objectName' => $seed->object_name, 'moduleDir' => $seed->module_dir, 'moduleName' => strtr($seed->module_dir, $module_names));
476 $pageData['stamp'] = $this->stamp;
477 $pageData['access'] = array('view' => $this->seed->ACLAccess('DetailView'), 'edit' => $this->seed->ACLAccess('EditView'));
478 $pageData['idIndex'] = $idIndex;
479 if(!$this->seed->ACLAccess('ListView')) {
480 $pageData['error'] = 'ACL restricted access';
485 if( isset($_REQUEST["searchFormTab"]) && $_REQUEST["searchFormTab"] == "advanced_search" ||
486 isset($_REQUEST["type_basic"]) && (count($_REQUEST["type_basic"] > 1) || $_REQUEST["type_basic"][0] != "") ||
487 isset($_REQUEST["module"]) && $_REQUEST["module"] == "MergeRecords")
489 $queryString = "-advanced_search";
491 else if (isset($_REQUEST["searchFormTab"]) && $_REQUEST["searchFormTab"] == "basic_search")
493 if($seed->module_dir == "Reports") $searchMetaData = SearchFormReports::retrieveReportsSearchDefs();
494 else $searchMetaData = SearchForm::retrieveSearchDefs($seed->module_dir);
496 $basicSearchFields = array();
498 if( isset($searchMetaData['searchdefs']) && isset($searchMetaData['searchdefs'][$seed->module_dir]['layout']['basic_search']) )
499 $basicSearchFields = $searchMetaData['searchdefs'][$seed->module_dir]['layout']['basic_search'];
501 foreach( $basicSearchFields as $basicSearchField)
503 $field_name = (is_array($basicSearchField) && isset($basicSearchField['name'])) ? $basicSearchField['name'] : $basicSearchField;
504 $field_name .= "_basic";
505 if( isset($_REQUEST[$field_name]) && ( !is_array($basicSearchField) || !isset($basicSearchField['type']) || $basicSearchField['type'] == 'text' || $basicSearchField['type'] == 'name') )
507 // Ensure the encoding is UTF-8
508 $queryString = htmlentities($_REQUEST[$field_name], null, 'UTF-8');
514 return array('data'=>$data , 'pageData'=>$pageData, 'query' => $queryString);
519 * generates urls as a string for use by the display layer
521 * @param array $queries
522 * @return array of urls orderBy and baseURL are always returned the others are only returned according to values passed in.
524 protected function generateURLS($queries)
526 foreach ($queries as $name => $value)
528 $queries[$name] = 'index.php?' . http_build_query($value);
530 $this->base_url = $queries['baseURL'];
535 * generates queries for use by the display layer
537 * @param int $sortOrder
539 * @param int $prevOffset
540 * @param int $nextOffset
541 * @param int $endOffset
542 * @param int $totalCounted
543 * @return array of queries orderBy and baseURL are always returned the others are only returned according to values passed in.
545 protected function generateQueries($sortOrder, $offset, $prevOffset, $nextOffset, $endOffset, $totalCounted)
548 $queries['baseURL'] = $this->getBaseQuery();
549 $queries['baseURL']['lvso'] = $sortOrder;
551 $queries['orderBy'] = $queries['baseURL'];
552 $queries['orderBy'][$this->var_order_by] = '';
556 $queries['nextPage'] = $queries['baseURL'];
557 $queries['nextPage'][$this->var_offset] = $nextOffset;
561 $queries['startPage'] = $queries['baseURL'];
562 $queries['startPage'][$this->var_offset] = 0;
566 $queries['prevPage'] = $queries['baseURL'];
567 $queries['prevPage'][$this->var_offset] = $prevOffset;
571 $queries['endPage'] = $queries['baseURL'];
572 $queries['endPage'][$this->var_offset] = $endOffset;
576 $queries['endPage'] = $queries['baseURL'];
577 $queries['endPage'][$this->var_offset] = 'end';
583 * generates the additional details span to be retrieved via ajax
585 * @param GUID id id of the record
586 * @return array string to attach to field
588 function getAdditionalDetailsAjax($id)
592 $jscalendarImage = SugarThemeRegistry::current()->getImageURL('info_inline.gif');
594 $extra = "<span id='adspan_" . $id . "' "
595 . "onclick=\"lvg_dtails('$id')\" "
596 . " style='position: relative;'><!--not_in_theme!--><img vertical-align='middle' class='info' border='0' alt='".$app_strings['LBL_ADDITIONAL_DETAILS']."' src='$jscalendarImage'></span>";
598 return array('fieldToAddTo' => $this->additionalDetailsFieldToAdd, 'string' => $extra);
602 * generates the additional details values
604 * @param unknown_type $fields
605 * @param unknown_type $adFunction
606 * @param unknown_type $editAccess
607 * @return array string to attach to field
609 function getAdditionalDetails($fields, $adFunction, $editAccess)
614 $results = $adFunction($fields);
616 $results['string'] = str_replace(array("'", "'"), '\'', $results['string']); // no xss!
618 if(trim($results['string']) == '')
620 $results['string'] = $app_strings['LBL_NONE'];
623 $extra = "<img alt='{$app_strings['LBL_INFOINLINE']}' style='padding: 0px 5px 0px 2px' border='0' onclick=\"SUGAR.util.getStaticAdditionalDetails(this,'";
625 $extra .= str_replace(array("\rn", "\r", "\n"), array('','','<br />'), $results['string']) ;
626 $extra .= "','<div style=\'float:left\'>{$app_strings['LBL_ADDITIONAL_DETAILS']}</div><div style=\'float: right\'>";
628 if($editAccess && !empty($results['editLink']))
630 $extra .= "<a title=\'{$app_strings['LBL_EDIT_BUTTON']}\' href={$results['editLink']}><img style=\'margin-left: 2px;\' border=\'0\' src=\'".SugarThemeRegistry::current()->getImageURL('edit_inline.png')."\'></a>";
633 $close = (!empty($results['viewLink'])) ? true : $close;
634 $extra .= (!empty($results['viewLink']) ? "<a title=\'{$app_strings['LBL_VIEW_BUTTON']}\' href={$results['viewLink']}><img style=\'margin-left: 2px;\' border=\'0\' src=".SugarThemeRegistry::current()->getImageURL('view_inline.png')."></a>" : '');
638 $extra .= "<a title=\'{$app_strings['LBL_ADDITIONAL_DETAILS_CLOSE_TITLE']}\' href=\'javascript: SUGAR.util.closeStaticAdditionalDetails();\'><img style=\'margin-left: 2px;\' border=\'0\' src=\'".SugarThemeRegistry::current()->getImageURL('close.png')."\'></a>";
642 $extra .= "',".$closeVal.")\" src='".SugarThemeRegistry::current()->getImageURL('info_inline.png')."' class='info'>";
644 return array('fieldToAddTo' => $results['fieldToAddTo'], 'string' => $extra);