2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2011 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 ********************************************************************************/
38 define('CONNECTOR_DISPLAY_CONFIG_FILE', 'custom/modules/Connectors/metadata/display_config.php');
39 require_once('include/connectors/ConnectorFactory.php');
41 function sources_sort_function($a, $b) {
42 if(isset($a['order']) && isset($b['order'])) {
43 if($a['order'] == $b['order']) {
47 return ($a['order'] < $b['order']) ? -1 : 1;
56 * Cached connectors data
59 protected static $connectors_cache;
62 * Get connector data by ID
64 * @param bool $refresh
65 * @return null|array Connector data
67 public static function getConnector(
72 $s = self::getConnectors($refresh);
73 return !empty($s[$id]) ? $s[$id] : null;
77 * Check if external accounts are enabled for this connector
80 public static function eapmEnabled($id, $refresh = false)
82 $data = self::getConnector($id, $refresh);
83 if(!$data || !isset($data["eapm"])) {
84 // TODO: if we don't know this connector, should we decide it's enabled or disabled?
87 return !empty($data["eapm"]["enabled"]);
92 * Returns an Array of the search field defintions Connector module to
93 * search entries from the connector. If the searchdefs.php file in the custom
94 * directory is not found, it defaults to using the mapping.php file entries to
95 * create a default version of the file.
97 * @param boolean $refresh boolean value to manually refresh the search definitions
98 * @return mixed $searchdefs Array of the search definitions
100 public static function getSearchDefs(
104 if($refresh || !file_exists('custom/modules/Connectors/metadata/searchdefs.php')) {
106 require('modules/Connectors/metadata/searchdefs.php');
108 if(!file_exists('custom/modules/Connectors/metadata')) {
109 mkdir_recursive('custom/modules/Connectors/metadata');
112 if(!write_array_to_file('searchdefs', $searchdefs, 'custom/modules/Connectors/metadata/searchdefs.php')) {
113 $GLOBALS['log']->fatal("Cannot write file custom/modules/Connectors/metadata/searchdefs.php");
118 require('custom/modules/Connectors/metadata/searchdefs.php');
125 * Returns an Array of the merge definitions used by the Connector module to
126 * merge values into the bean instance
128 * @param mixed $filter_sources Array optional Array value of sources to only use
129 * @return mixed $mergedefs Array of the merge definitions
131 public static function getViewDefs(
132 $filter_sources = array()
135 //Go through all connectors and get their mapping keys and merge them across each module
136 $connectors = self::getConnectors();
137 $modules_sources = self::getDisplayConfig();
138 $view_defs = array();
139 foreach($connectors as $id=>$ds) {
141 if(!empty($filter_sources) && !isset($filter_sources[$id])) {
145 if(file_exists('custom/' . $ds['directory'] . '/mapping.php')) {
146 require('custom/' . $ds['directory'] . '/mapping.php');
147 } else if(file_exists($ds['directory'] . '/mapping.php')) {
148 require($ds['directory'] . '/mapping.php');
151 if(!empty($mapping['beans'])) {
152 foreach($mapping['beans'] as $module=>$map) {
153 if(!empty($modules_sources[$module][$id])) {
154 if(!empty($view_defs['Connector']['MergeView'][$module])) {
155 $view_defs['Connector']['MergeView'][$module] = array_merge($view_defs['Connector']['MergeView'][$module], array_flip($map));
157 $view_defs['Connector']['MergeView'][$module] = array_flip($map);
164 if(!empty($view_defs['Connector']['MergeView'])) {
165 foreach($view_defs['Connector']['MergeView'] as $module=>$map) {
166 $view_defs['Connector']['MergeView'][$module] = array_keys($view_defs['Connector']['MergeView'][$module]);
176 * Returns an Array of the merge definitions used by the Connector module to
177 * merge values into the bean instance
179 * @deprecated This method has been replaced by getViewDefs
180 * @param boolean $refresh boolean value to manually refresh the mergeview definitions
181 * @return mixed $mergedefs Array of the merge definitions
183 public static function getMergeViewDefs(
187 if($refresh || !file_exists('custom/modules/Connectors/metadata/mergeviewdefs.php')) {
189 //Go through all connectors and get their mapping keys and merge them across each module
190 $connectors = self::getConnectors($refresh);
191 $modules_sources = self::getDisplayConfig();
192 $view_defs = array();
193 foreach($connectors as $id=>$ds) {
195 if(file_exists('custom/' . $ds['directory'] . '/mapping.php')) {
196 require('custom/' . $ds['directory'] . '/mapping.php');
197 } else if(file_exists($ds['directory'] . '/mapping.php')) {
198 require($ds['directory'] . '/mapping.php');
201 if(!empty($mapping['beans'])) {
202 foreach($mapping['beans'] as $module=>$map) {
203 if(!empty($modules_sources[$module][$id])) {
204 if(!empty($view_defs['Connector']['MergeView'][$module])) {
205 $view_defs['Connector']['MergeView'][$module] = array_merge($view_defs['Connector']['MergeView'][$module], array_flip($map));
207 $view_defs['Connector']['MergeView'][$module] = array_flip($map);
214 if(!empty($view_defs['Connector']['MergeView'])) {
215 foreach($view_defs['Connector']['MergeView'] as $module=>$map) {
216 $view_defs['Connector']['MergeView'][$module] = array_keys($view_defs['Connector']['MergeView'][$module]);
220 if(!file_exists('custom/modules/Connectors/metadata')) {
221 mkdir_recursive('custom/modules/Connectors/metadata');
224 if(!write_array_to_file('viewdefs', $view_defs, 'custom/modules/Connectors/metadata/mergeviewdefs.php')) {
225 $GLOBALS['log']->fatal("Cannot write file custom/modules/Connectors/metadata/mergeviewdefs.php");
230 require('custom/modules/Connectors/metadata/mergeviewdefs.php');
237 * Returns an Array of the connectors that have been loaded into the system
238 * along with attributes pertaining to each connector.
240 * @param boolean $refresh boolean flag indicating whether or not to force rewriting the file; defaults to false
241 * @returns mixed $connectors Array of the connector entries found
243 public static function getConnectors(
247 if ( isset($GLOBALS['sugar_config']['developer_mode']) ) {
251 if(!empty(self::$connectors_cache) && !$refresh) {
252 return self::$connectors_cache;
255 $src1 = 'modules/Connectors/connectors/sources';
256 $src2 = 'custom/modules/Connectors/connectors/sources';
257 $src3 = 'custom/modules/Connectors/metadata';
258 $src4 = 'custom/modules/Connectors/metadata/connectors.php';
260 //if this is a templated environment, then use utilities to get the proper paths
261 if(defined('TEMPLATE_URL')){
262 $src1 = SugarTemplateUtilities::getFilePath($src1);
263 $src2 = SugarTemplateUtilities::getFilePath($src2);
264 $src3 = SugarTemplateUtilities::getFilePath($src3);
265 $src4 = SugarTemplateUtilities::getFilePath($src4);
268 if($refresh || !file_exists($src4)) {
270 $sources = array_merge(self::getSources($src1), self::getSources($src2));
271 if(!file_exists($src3)) {
272 mkdir_recursive($src3);
274 if(file_exists($src4)) {
276 $sources = array_merge($sources, $connectors);
279 if(!self::saveConnectors($sources, $src4)) {
285 self::$connectors_cache = $connectors;
290 * Save connectors array to file
291 * @param array $connectors Source data to write
292 * @param string $toFile filename to use
293 * @return bool success
295 public static function saveConnectors($connectors, $toFile = '')
298 $toFile = 'custom/modules/Connectors/metadata/connectors.php';
299 if(defined('TEMPLATE_URL')) {
300 $toFile = SugarTemplateUtilities::getFilePath($toFile);
304 if(!write_array_to_file('connectors', $connectors, $toFile)) {
305 //Log error and return empty array
306 $GLOBALS['log']->fatal("Cannot write sources to file");
309 self::$connectors_cache = $connectors;
315 * Returns an Array of source entries found under the given directory
316 * @param String $directory The directory to search
317 * @return mixed $sources An Array of source entries
319 private static function getSources(
320 $directory = 'modules/Connectors/connectors/sources'
323 if(file_exists($directory)) {
326 $files = findAllFiles($directory, $files, false, 'config\.php');
327 $start = strrpos($directory, '/') == strlen($directory)-1 ? strlen($directory) : strlen($directory) + 1;
329 $sources_ordering = array();
330 foreach($files as $file) {
332 $end = strrpos($file, '/') - $start;
334 $source['id'] = str_replace('/', '_', substr($file, $start, $end));
335 $source['name'] = !empty($config['name']) ? $config['name'] : $source['id'];
336 $source['enabled'] = true;
337 $source['directory'] = $directory . '/' . str_replace('_', '/', $source['id']);
338 $order = isset($config['order']) ? $config['order'] : 99; //default to end using 99 if no order set
340 $instance = ConnectorFactory::getInstance($source['id']);
341 $source['eapm'] = empty($config['eapm'])?false:$config['eapm'];
342 $mapping = $instance->getMapping();
344 if(!empty($mapping['beans'])) {
345 foreach($mapping['beans'] as $module=>$mapping_entry) {
349 $source['modules'] = $modules;
350 $sources_ordering[$source['id']] = array('order'=>$order, 'source'=>$source);
353 usort($sources_ordering, 'sources_sort_function');
354 foreach($sources_ordering as $entry) {
355 $sources[$entry['source']['id']] = $entry['source'];
367 public static function getDisplayConfig(
371 if(!file_exists(CONNECTOR_DISPLAY_CONFIG_FILE) || $refresh) {
372 $sources = self::getConnectors();
373 $modules_sources = array();
375 //Make the directory for the config file
376 if(!file_exists('custom/modules/Connectors/metadata')) {
377 mkdir_recursive('custom/modules/Connectors/metadata');
380 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
381 //Log error and return empty array
382 $GLOBALS['log']->fatal("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE);
387 require(CONNECTOR_DISPLAY_CONFIG_FILE);
388 return $modules_sources;
393 * getModuleConnectors
395 * @param String $module the module to get the connectors for
396 * @param mixed $connectors Array of connectors mapped to the module or empty if none
399 public static function getModuleConnectors(
403 $modules_sources = self::getDisplayConfig();
404 if(!empty($modules_sources) && !empty($modules_sources[$module])){
406 foreach($modules_sources[$module] as $index => $id){
407 $sources[$id] = self::getConnector($id);
417 * Given a module name, checks to see if the module is enabled to be serviced by the connector module
418 * @param String $module String name of the module
419 * @return boolean $enabled boolean value indicating whether or not the module is enabled to be serviced by the connector module
421 public static function isModuleEnabled(
425 $modules_sources = self::getDisplayConfig();
426 return !empty($modules_sources) && !empty($modules_sources[$module]) ? true : false;
432 * Given a source id, checks to see if the source is enabled for at least one module
433 * @param String $source String name of the source
434 * @return boolean $enabled boolean value indicating whether or not the source is displayed in at least one module
436 public static function isSourceEnabled(
440 $modules_sources = self::getDisplayConfig();
441 foreach($modules_sources as $module=>$mapping) {
442 foreach($mapping as $s) {
452 * When a module has all of the sources removed from it we do not properly remove it from the viewdefs. This function
455 * @param String $module - the module in question
457 public static function cleanMetaDataFile(
461 $metadata_file = file_exists("custom/modules/{$module}/metadata/detailviewdefs.php") ? "custom/modules/{$module}/metadata/detailviewdefs.php" : "modules/{$module}/metadata/detailviewdefs.php";
462 require($metadata_file);
464 $insertConnectorButton = true;
469 self::removeHoverField($viewdefs, $module);
471 //Make the directory for the metadata file
472 if(!file_exists("custom/modules/{$module}/metadata")) {
473 mkdir_recursive("custom/modules/{$module}/metadata");
476 if(!write_array_to_file('viewdefs', $viewdefs, "custom/modules/{$module}/metadata/detailviewdefs.php")) {
477 $GLOBALS['log']->fatal("Cannot update file custom/modules/{$module}/metadata/detailviewdefs.php");
481 if(file_exists("{$GLOBALS['sugar_config']['cache_dir']}modules/{$module}/DetailView.tpl") && !unlink("{$GLOBALS['sugar_config']['cache_dir']}modules/{$module}/DetailView.tpl")) {
482 $GLOBALS['log']->fatal("Cannot delete file {$GLOBALS['sugar_config']['cache_dir']}modules/{$module}/DetailView.tpl");
489 * updateMetaDataFiles
490 * This method updates the metadata files (detailviewdefs.php) according to the settings in display_config.php
491 * @return $result boolean value indicating whether or not the method successfully completed.
493 public static function updateMetaDataFiles()
495 if(file_exists(CONNECTOR_DISPLAY_CONFIG_FILE)) {
496 $modules_sources = array();
498 require(CONNECTOR_DISPLAY_CONFIG_FILE);
500 $GLOBALS['log']->debug(var_export($modules_sources, true));
501 if(!empty($modules_sources)) {
502 foreach($modules_sources as $module=>$mapping) {
503 $metadata_file = file_exists("custom/modules/{$module}/metadata/detailviewdefs.php") ? "custom/modules/{$module}/metadata/detailviewdefs.php" : "modules/{$module}/metadata/detailviewdefs.php";
507 if( !file_exists($metadata_file) )
509 $GLOBALS['log']->info("Unable to update metadata file for module: {$module}");
513 require($metadata_file);
515 $insertConnectorButton = true;
520 self::removeHoverField($viewdefs, $module);
522 //Insert the hover field if available
523 if(!empty($mapping)) {
525 require_once('include/connectors/sources/SourceFactory.php');
526 require_once('include/connectors/formatters/FormatterFactory.php');
527 $shown_formatters = array();
528 foreach($mapping as $id) {
529 $source = SourceFactory::getSource($id, false);
530 if($source->isEnabledInHover() && $source->isRequiredConfigFieldsForButtonSet()) {
531 $shown_formatters[$id] = FormatterFactory::getInstance($id);
535 //Now we have to decide which field to put it on... use the first one for now
536 if(!empty($shown_formatters)) {
538 foreach($shown_formatters as $id=>$formatter) {
539 $added_field = false;
540 $formatter_mapping = $formatter->getSourceMapping();
542 $source = $formatter->getComponent()->getSource();
543 //go through the mapping and add the hover to every field define in the mapping
544 //1) check for hover fields
545 $hover_fields = $source->getFieldsWithParams('hover', true);
547 foreach($hover_fields as $key => $def){
548 if(!empty($formatter_mapping['beans'][$module][$key])){
549 $added_field = self::setHoverField($viewdefs, $module, $formatter_mapping['beans'][$module][$key], $id);
553 //2) check for first mapping field
554 if(!$added_field && !empty($formatter_mapping['beans'][$module])) {
555 foreach($formatter_mapping['beans'][$module] as $key => $val){
556 $added_field = self::setHoverField($viewdefs, $module, $val, $id);
566 //Log an error message
568 $GLOBALS['log']->fatal("Unable to place hover field link on metadata for module {$module}");
575 //Make the directory for the metadata file
576 if(!file_exists("custom/modules/{$module}/metadata")) {
577 mkdir_recursive("custom/modules/{$module}/metadata");
580 if(!write_array_to_file('viewdefs', $viewdefs, "custom/modules/{$module}/metadata/detailviewdefs.php")) {
581 $GLOBALS['log']->fatal("Cannot update file custom/modules/{$module}/metadata/detailviewdefs.php");
585 if(file_exists("{$GLOBALS['sugar_config']['cache_dir']}modules/{$module}/DetailView.tpl") && !unlink("{$GLOBALS['sugar_config']['cache_dir']}modules/{$module}/DetailView.tpl")) {
586 $GLOBALS['log']->fatal("Cannot delete file {$GLOBALS['sugar_config']['cache_dir']}modules/{$module}/DetailView.tpl");
595 public function removeHoverField(
600 require_once('include/SugarFields/Parsers/MetaParser.php');
601 $metaParser = new MetaParser();
602 if(!$metaParser->hasMultiplePanels($viewdefs[$module]['DetailView']['panels'])) {
603 $keys = array_keys($viewdefs[$module]['DetailView']['panels']);
604 if(!empty($keys) && count($keys) != 1) {
605 $viewdefs[$module]['DetailView']['panels'] = array('default'=>$viewdefs[$module]['DetailView']['panels']);
609 foreach($viewdefs[$module]['DetailView']['panels'] as $panel_id=>$panel) {
610 foreach($panel as $row_id=>$row) {
611 foreach($row as $field_id=>$field) {
612 if(is_array($field) && !empty($field['displayParams']['enableConnectors'])) {
614 unset($field['displayParams']['enableConnectors']);
615 unset($field['displayParams']['module']);
616 unset($field['displayParams']['connectors']);
617 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id] = $field;
625 public function setHoverField(
632 //Check for metadata files that aren't correctly created
633 require_once('include/SugarFields/Parsers/MetaParser.php');
634 $metaParser = new MetaParser();
635 if(!$metaParser->hasMultiplePanels($viewdefs[$module]['DetailView']['panels'])) {
636 $keys = array_keys($viewdefs[$module]['DetailView']['panels']);
637 if(!empty($keys) && count($keys) != 1) {
638 $viewdefs[$module]['DetailView']['panels'] = array('default'=>$viewdefs[$module]['DetailView']['panels']);
642 foreach($viewdefs[$module]['DetailView']['panels'] as $panel_id=>$panel) {
643 foreach($panel as $row_id=>$row) {
644 foreach($row as $field_id=>$field) {
645 $name = is_array($field) ? $field['name'] : $field;
646 if($name == $hover_field) {
647 if(is_array($field)) {
648 if(!empty($viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams'])) {
649 $newDisplayParam = $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams'];
650 $newDisplayParam['module'] = $module;
651 $newDisplayParam['enableConnectors'] = true;
652 if(!is_null($source_id) && !in_array($source_id, $newDisplayParam['connectors'])){
653 $newDisplayParam['connectors'][] = $source_id;
655 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams'] = $newDisplayParam;
657 $field['displayParams'] = array('enableConnectors'=>true, 'module'=>$module, 'connectors' => array(0 => $source_id));
658 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id] = $field;
662 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id] = array ('name'=>$field, 'displayParams'=>array('enableConnectors'=>true, 'module'=>$module, 'connectors' => array(0 => $source_id)));
673 * setDefaultHoverField
674 * Sets the hover field to the first element in the detailview screen
676 * @param Array $viewdefs the metadata of the detailview
677 * @param String $module the Module to which the hover field should be added to
678 * @return boolean True if field was added; false otherwise
680 private function setDefaultHoverField(
686 foreach($viewdefs[$module]['DetailView']['panels'] as $panel_id=>$panel) {
687 foreach($panel as $row_id=>$row) {
688 foreach($row as $field_id=>$field) {
689 if(is_array($field)) {
690 if(!empty($viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams'])) {
691 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams']['enableConnectors'] = true;
692 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams']['module'] = $module;
693 if(!is_null($source_id) && !in_array($source_id, $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams']['connectors'])){
694 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id]['displayParams']['connectors'][] = $source_id;
697 $field['displayParams'] = array('enableConnectors'=>true, 'module'=>$module, 'connectors' => array(0 => $source_id));
698 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id] = $field;
701 $viewdefs[$module]['DetailView']['panels'][$panel_id][$row_id][$field_id] = array ('name'=>$field, 'displayParams'=>array('enableConnectors'=>true, 'module'=>$module, 'connectors' => array(0 => $source_id)));
712 * getConnectorButtonScript
713 * This method builds the HTML code for the hover link field
715 * @param mixed $displayParams Array value of display parameters passed from the SugarField code
716 * @param mixed $smarty The Smarty object from the calling smarty code
717 * @return String $code The HTML code for the hover link
719 public static function getConnectorButtonScript(
724 $module = $displayParams['module'];
725 require_once('include/connectors/utils/ConnectorUtils.php');
726 $modules_sources = self::getDisplayConfig();
727 global $current_language, $app_strings;
728 $mod_strings = return_module_language($current_language, 'Connectors');
729 $menuParams = 'var menuParams = "';
730 $shown_sources = array();
731 if(!empty($module) && !empty($displayParams['connectors'])) {
732 foreach($displayParams['connectors'] as $id) {
733 if(!empty($modules_sources[$module]) && in_array($id, $modules_sources[$module])){
734 $shown_sources[] = $id;
738 if(empty($shown_sources)) {
742 require_once('include/connectors/formatters/FormatterFactory.php');
745 //If there is only one source, just show the icon or some standalone view
746 if(count($shown_sources) == 1) {
747 $formatter = FormatterFactory::getInstance($shown_sources[0]);
748 $formatter->setModule($module);
749 $formatter->setSmarty($smarty);
750 $formatter_code = $formatter->getDetailViewFormat();
751 if(!empty($formatter_code)) {
752 $iconFilePath = $formatter->getIconFilePath();
753 $iconFilePath = empty($iconFilePath) ? 'themes/default/images/MoreDetail.png' : $iconFilePath;
755 $code = '<img id="dswidget_img" border="0" src="' . $iconFilePath .'" alt="' . $shown_sources[0] .'" onmouseover="show_' . $shown_sources[0] . '(event);">';
756 $code .= "<script type='text/javascript' src='{sugar_getjspath file='include/connectors/formatters/default/company_detail.js'}'></script>";
757 $code .= $formatter->getDetailViewFormat();
758 $code .= $formatter_code;
764 $sourcesDisplayed = 0;
766 foreach($shown_sources as $id) {
767 $formatter = FormatterFactory::getInstance($id);
768 $formatter->setModule($module);
769 $formatter->setSmarty($smarty);
770 $buttonCode = $formatter->getDetailViewFormat();
771 if(!empty($buttonCode)) {
773 $singleIcon = $formatter->getIconFilePath();
774 $source = SourceFactory::getSource($id);
775 $config = $source->getConfig();
776 $name = !empty($config['name']) ? $config['name'] : $id;
777 //Create the menu item to call show_[source id] method in javascript
778 $menuParams .= '<a href=\'#\' style=\'width:150px\' class=\'menuItem\' onmouseover=\'hiliteItem(this,\"yes\");\' onmouseout=\'unhiliteItem(this);\' onclick=\'show_' . $id . '(event);\'>' . $name . '</a>';
779 $formatterCode .= $buttonCode;
783 if(!empty($formatterCode)) {
784 if($sourcesDisplayed > 1) {
785 $dswidget_img = SugarThemeRegistry::current()->getImageURL('MoreDetail.png');
786 $code = '<img id="dswidget_img" src="'.$dswidget_img.'" width="11" height="7" border="0" alt="connectors_popups" onmouseover="return showConnectorMenu2();" onmouseout="return nd(1000);">';
788 $dswidget_img = SugarThemeRegistry::current()->getImageURL('MoreDetail.png');
789 $singleIcon = empty($singleIcon) ? $dswidget_img : $singleIcon;
790 $code = '<img id="dswidget_img" border="0" src="' . $singleIcon . '" alt="connectors_popups" onmouseover="return showConnectorMenu2();" onmouseout="return nd(1000);">';
792 $code .= "{overlib_includes}\n";
793 $code .= "<script type='text/javascript' src='{sugar_getjspath file='include/connectors/formatters/default/company_detail.js'}'></script>\n";
794 $code .= "<script type='text/javascript'>\n";
795 $code .= "function showConnectorMenu2() {literal} { {/literal}\n";
798 $code .= $menuParams . "\n";
799 $code .= "return overlib(menuParams, CENTER, STICKY, MOUSEOFF, 3000, WIDTH, 110, FGCLASS, 'olOptionsFgClass', CGCLASS, 'olOptionsCgClass', BGCLASS, 'olBgClass', TEXTFONTCLASS, 'olFontClass', CAPTIONFONTCLASS, 'olOptionsCapFontClass', CLOSEFONTCLASS, 'olOptionsCloseFontClass');\n";
800 $code .= "{literal} } {/literal}\n";
801 $code .= "</script>\n";
802 $code .= $formatterCode;
811 * getConnectorStrings
812 * This method returns the language Strings for a given connector instance
814 * @param String $source_id String value of the connector id to retrive language strings for
815 * @param String $language optional String value for the language to use (defaults to $GLOBALS['current_language'])
817 public static function getConnectorStrings(
822 $lang = empty($language) ? $GLOBALS['current_language'] : $language;
823 $lang .= '.lang.php';
824 $dir = str_replace('_', '/', $source_id);
825 if(file_exists("custom/modules/Connectors/connectors/sources/{$dir}/language/{$lang}")) {
826 require("custom/modules/Connectors/connectors/sources/{$dir}/language/{$lang}");
827 return !empty($connector_strings) ? $connector_strings : array();
828 } else if(file_exists("modules/Connectors/connectors/sources/{$dir}/language/{$lang}")){
829 require("modules/Connectors/connectors/sources/{$dir}/language/{$lang}");
830 return !empty($connector_strings) ? $connector_strings : array();
832 $GLOBALS['log']->error("Unable to locate language string file for source {$source_id}");
840 * Install the name of the source (called from ModuleInstaller.php). Modifies the files in the custom
841 * directory to add the new source in.
843 * @param String $source String value of the id of the connector to install
844 * @return boolean $result boolean value indicating whether or not connector was installed
846 public static function installSource(
853 //Add the source to the connectors.php file
854 self::getConnectors(true);
856 //Get the display config file
857 self::getDisplayConfig();
858 //Update the display_config.php file to show this new source
859 $modules_sources = array();
860 require(CONNECTOR_DISPLAY_CONFIG_FILE);
861 foreach($modules_sources as $module=>$mapping) {
863 foreach($mapping as $id=>$src) {
864 if($src == $source) {
865 unset($modules_sources[$module][$id]);
871 //Make the directory for the config file
872 if(!file_exists('custom/modules/Connectors/metadata')) {
873 mkdir_recursive('custom/modules/Connectors/metadata');
876 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
877 //Log error and return empty array
878 $GLOBALS['log']->fatal("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE);
887 * @param String $source String value of the id of the connector to un-install
888 * @return boolean $result boolean value indicating whether or not connector was un-installed
890 public static function uninstallSource(
898 //Remove the source from the connectors.php file
899 self::getConnectors(true);
901 //Update the display_config.php file to remove this source
902 $modules_sources = array();
903 require(CONNECTOR_DISPLAY_CONFIG_FILE);
904 foreach($modules_sources as $module=>$mapping) {
905 foreach($mapping as $id=>$src) {
906 if($src == $source) {
907 unset($modules_sources[$module][$id]);
912 //Make the directory for the config file
913 if(!file_exists('custom/modules/Connectors/metadata')) {
914 mkdir_recursive('custom/modules/Connectors/metadata');
917 if(!write_array_to_file('modules_sources', $modules_sources, CONNECTOR_DISPLAY_CONFIG_FILE)) {
918 //Log error and return empty array
919 $GLOBALS['log']->fatal("Cannot write \$modules_sources to " . CONNECTOR_DISPLAY_CONFIG_FILE);
929 * hasWizardSourceEnabledForModule
930 * This is a private method that returns a boolean value indicating whether or not at least one
931 * source is enabled for a given module. By enabled we mean that the source has the neccessary
932 * configuration properties set as determined by the isRequiredConfigFieldsForButtonSet method. In
933 * addition, a check is made to ensure that it is a source that has been enabled for the wizard.
935 * @param String $module String value of module to check
936 * @return boolean $enabled boolean value indicating whether or not module has at least one source enabled
938 private static function hasWizardSourceEnabledForModule(
942 if(file_exists(CONNECTOR_DISPLAY_CONFIG_FILE)) {
943 require_once('include/connectors/sources/SourceFactory.php');
944 require(CONNECTOR_DISPLAY_CONFIG_FILE);
945 if(!empty($modules_sources) && !empty($modules_sources[$module])) {
946 foreach($modules_sources[$module] as $id) {
947 $source = SourceFactory::getSource($id, false);
948 if(!is_null($source) && $source->isEnabledInWizard() && $source->isRequiredConfigFieldsForButtonSet()) {