PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/ModuleBuilder/MB/MBModule.php

https://bitbucket.org/cviolette/sugarcrm
PHP | 863 lines | 703 code | 94 blank | 66 comment | 95 complexity | db62117969740eb4bf8418c7caca92d6 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. <?php
  2. /*********************************************************************************
  3. * SugarCRM Community Edition is a customer relationship management program developed by
  4. * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it under
  7. * the terms of the GNU Affero General Public License version 3 as published by the
  8. * Free Software Foundation with the addition of the following permission added
  9. * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
  10. * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
  11. * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
  12. *
  13. * This program is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  15. * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Affero General Public License along with
  19. * this program; if not, see http://www.gnu.org/licenses or write to the Free
  20. * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21. * 02110-1301 USA.
  22. *
  23. * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
  24. * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
  25. *
  26. * The interactive user interfaces in modified source and object code versions
  27. * of this program must display Appropriate Legal Notices, as required under
  28. * Section 5 of the GNU Affero General Public License version 3.
  29. *
  30. * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
  31. * these Appropriate Legal Notices must retain the display of the "Powered by
  32. * SugarCRM" logo. If the display of the logo is not reasonably feasible for
  33. * technical reasons, the Appropriate Legal Notices must display the words
  34. * "Powered by SugarCRM".
  35. ********************************************************************************/
  36. define ( 'MB_TEMPLATES', 'include/SugarObjects/templates' ) ;
  37. define ( 'MB_IMPLEMENTS', 'include/SugarObjects/implements' ) ;
  38. require_once ('modules/ModuleBuilder/MB/MBVardefs.php') ;
  39. require_once ('modules/ModuleBuilder/MB/MBRelationship.php') ;
  40. require_once ('modules/ModuleBuilder/MB/MBLanguage.php') ;
  41. class MBModule
  42. {
  43. public $name = '' ;
  44. public $config = array (
  45. 'assignable' => 1 , 'acl' => 1 , 'has_tab' => 1 , 'studio' => 1 , 'audit' => 1 ) ;
  46. public $mbpublicdefs ;
  47. public $errors = array ( ) ;
  48. public $path = '' ;
  49. public $implementable = array (
  50. 'has_tab' => 'Navigation Tab' ) ;
  51. public $always_implement = array ( 'assignable' => 'Assignable' , 'acl' => 'Access Controls' , 'studio' => 'Studio Support' , 'audit' => 'Audit Table' ) ;
  52. public $iTemplate = array (
  53. 'assignable' ) ;
  54. public $config_md5 = null ;
  55. function __construct ($name , $path , $package , $package_key)
  56. {
  57. global $mod_strings;
  58. $this->config [ 'templates' ] = array ( 'basic' => 1 ) ;
  59. $this->name = MBModule::getDBName ( $name ) ;
  60. $this->key_name = $package_key . '_' . $name ;
  61. $this->package = $package ;
  62. $this->package_key = $package_key ;
  63. $this->package_path = $path ;
  64. $this->implementable = array (
  65. 'has_tab' => !empty($mod_strings[ 'LBL_NAV_TAB' ]) ? $mod_strings[ 'LBL_NAV_TAB' ] : false) ;
  66. $this->path = $this->getModuleDir () ;
  67. // $this->mbrelationship = new MBRelationship($this->name, $this->path, $this->key_name);
  68. $this->relationships = new UndeployedRelationships ( $this->path ) ;
  69. $this->mbvardefs = new MBVardefs ( $this->name, $this->path, $this->key_name ) ;
  70. $this->load () ;
  71. }
  72. function getDBName ($name)
  73. {
  74. return preg_replace ( "/[^\w]+/", "_", $name ) ;
  75. }
  76. function getModuleName()
  77. {
  78. return $this->name;
  79. }
  80. function getPackageName()
  81. {
  82. return $this->package;
  83. }
  84. /**
  85. * @return UndeployedRelationships
  86. */
  87. function getRelationships()
  88. {
  89. return $this->relationships;
  90. }
  91. /**
  92. * Loads the module based on the module name
  93. *
  94. */
  95. function load ()
  96. {
  97. if (file_exists ( $this->path . '/config.php' ))
  98. {
  99. include ($this->path . '/config.php') ;
  100. $this->config = $config ;
  101. }
  102. $label = (! empty ( $this->config [ 'label' ] )) ? $this->config [ 'label' ] : $this->name ;
  103. $this->mblanguage = new MBLanguage ( $this->name, $this->path, $label, $this->key_name ) ;
  104. foreach ( $this->iTemplate as $temp )
  105. {
  106. if (! empty ( $this->config [ $temp ] ))
  107. {
  108. $this->mbvardefs->iTemplates [ $temp ] = 1 ;
  109. $this->mblanguage->iTemplates [ $temp ] = $temp ;
  110. }
  111. }
  112. $this->mbvardefs->templates = $this->config [ 'templates' ] ;
  113. $this->mblanguage->templates = $this->config [ 'templates' ] ;
  114. $this->mbvardefs->load () ;
  115. $this->mblanguage->load () ;
  116. }
  117. function addTemplate ($template)
  118. {
  119. $this->config [ 'templates' ] [ $template ] = 1 ;
  120. }
  121. function getModuleDir ()
  122. {
  123. return $this->package_path . '/modules/' . $this->name ;
  124. }
  125. function removeTemplate ($template)
  126. {
  127. unset ( $this->config [ 'templates' ] [ $template ] ) ;
  128. }
  129. function getVardefs ($by_group = false)
  130. {
  131. $this->mbvardefs->updateVardefs ( $by_group ) ;
  132. return $this->mbvardefs->getVardefs () ;
  133. }
  134. function addField ($vardef)
  135. {
  136. $this->mbvardefs->addFieldVardef ( $vardef ) ;
  137. }
  138. function addFieldObject ($field)
  139. {
  140. $vardef = $field->get_field_def () ;
  141. $this->mbvardefs->mergeVardefs();
  142. $existingVardefs = $this->mbvardefs->getVardefs () ;
  143. //Merge with the existing vardef if it already exists
  144. if(!empty($existingVardefs['fields'][$vardef['name']])){
  145. $vardef = array_merge( $existingVardefs['fields'][$vardef['name']], $vardef);
  146. }
  147. if (! empty ( $vardef [ 'source' ] ) && $vardef [ 'source' ] == 'custom_fields')
  148. unset ( $vardef [ 'source' ] ) ;
  149. $this->mbvardefs->load();
  150. $this->addField ( $vardef ) ;
  151. $this->mbvardefs->save();
  152. }
  153. function deleteField ($name)
  154. {
  155. $this->mbvardefs->deleteField ( $name ) ;
  156. }
  157. function fieldExists ($name = '' , $type = '')
  158. {
  159. $vardefs = $this->getVardefs();
  160. if (! empty ( $vardefs ))
  161. {
  162. if (empty ( $type ) && empty ( $name ))
  163. return false ; else if (empty ( $type ))
  164. return ! empty ( $vardefs [ 'fields' ] [ $name ] ) ; else if (empty ( $name ))
  165. {
  166. foreach ( $vardefs [ 'fields' ] as $def )
  167. {
  168. if ($def [ 'type' ] == $type)
  169. return true ;
  170. }
  171. return false ;
  172. } else
  173. return (! empty ( $vardefs [ 'fields' ] [ $name ] ) && ($vardefs [ 'fields' ] [ $name ] [ 'type' ] == $type)) ;
  174. } else
  175. {
  176. return false ;
  177. }
  178. }
  179. function getModStrings ($language = 'en_us')
  180. {
  181. return $this->mblanguage->getModStrings ( $language ) ;
  182. }
  183. function setModStrings ($language = 'en_us' , $mod_strings)
  184. {
  185. $language .= '.lang.php' ;
  186. $this->mblanguage->strings [ $language ] = $mod_strings ;
  187. }
  188. function setLabel ($language = 'en_us' , $key , $value)
  189. {
  190. $language .= '.lang.php' ;
  191. $this->mblanguage->strings [ $language ] [ $key ] = $value ;
  192. //Ensure this key exists in all languages
  193. foreach ($this->mblanguage->strings as $lang => $values) {
  194. if (empty($values[$key])) {
  195. $this->mblanguage->strings[$lang][$key] = $value;
  196. }
  197. }
  198. }
  199. function deleteLabel ($language = 'en_us' , $key)
  200. {
  201. foreach ($this->mblanguage->strings as $lang => $values) {
  202. if (!empty($values[$key])) {
  203. unset($this->mblanguage->strings[$lang][$key]);
  204. }
  205. }
  206. }
  207. /**
  208. * Required for an MB module to work with Dynamic fields
  209. */
  210. function addLabel ( $displayLabel)
  211. {
  212. $this->setLabel('en_us', $this->getDBName($displayLabel, false), translate($displayLabel));
  213. $this->save();
  214. }
  215. function getLabel ($language = 'en_us' , $key)
  216. {
  217. $language .= '.lang.php' ;
  218. if (empty ( $this->mblanguage->strings [ $language ] [ $key ] ))
  219. {
  220. return '' ;
  221. }
  222. return $this->mblanguage->strings [ $language ] [ $key ] ;
  223. }
  224. function getAppListStrings ($language = 'en_us')
  225. {
  226. return $this->mblanguage->getAppListStrings ( $language ) ;
  227. }
  228. function setAppListStrings ($language = 'en_us' , $app_list_strings)
  229. {
  230. $language .= '.lang.php' ;
  231. $this->mblanguage->appListStrings [ $language ] = $app_list_strings ;
  232. }
  233. function setDropDown ($language = 'en_us' , $key , $value)
  234. {
  235. $language .= '.lang.php' ;
  236. $this->mblanguage->appListStrings [ $language ] [ $key ] = $value ;
  237. }
  238. function deleteDropDown ($language = 'en_us' , $key)
  239. {
  240. $language .= '.lang.php' ;
  241. unset ( $this->mblanguage->appListStrings [ $language ] [ $key ] ) ;
  242. }
  243. function save ()
  244. {
  245. $this->path = $this->getModuleDir () ;
  246. if (mkdir_recursive ( $this->path ))
  247. {
  248. $this->setConfigMD5 () ;
  249. $old_config_md5 = $this->config_md5 ;
  250. $this->saveConfig () ;
  251. $this->getVardefs () ;
  252. $this->mbvardefs->save ( $this->key_name ) ;
  253. // $this->mbrelationship->save ( $this->key_name ) ;
  254. $this->relationships->save () ;
  255. $this->copyMetaData () ;
  256. $this->copyDashlet () ;
  257. $this->copyViews() ;
  258. if (0 != strcmp ( $old_config_md5, $this->config_md5 ))
  259. {
  260. $this->mblanguage->reload () ;
  261. }
  262. $this->mblanguage->label = $this->config [ 'label' ] ;
  263. //pass in the key_name incase it has changed mblanguage will check if it is different and handle it accordingly
  264. $this->mblanguage->save ( $this->key_name ) ;
  265. if (! file_exists ( $this->package_path . "/icons/icon_" . ucfirst ( $this->key_name ) . ".gif" ))
  266. {
  267. $this->createIcon () ;
  268. }
  269. $this->errors = array_merge ( $this->errors, $this->mbvardefs->errors ) ;
  270. }
  271. }
  272. function copyDashlet() {
  273. $templates = array_reverse ( $this->config [ 'templates' ], true ) ;
  274. foreach ( $templates as $template => $a )
  275. {
  276. if (file_exists ( MB_TEMPLATES . '/' . $template . '/Dashlets/Dashlet' ))
  277. {
  278. $this->copyMetaRecursive ( MB_TEMPLATES . '/' . $template . '/Dashlets/Dashlet', $this->path . '/Dashlets/' . $this->key_name . 'Dashlet/' ) ;
  279. }
  280. }
  281. }
  282. function copyViews() {
  283. $templates = array_reverse ( $this->config [ 'templates' ], true ) ;
  284. foreach ( $templates as $template => $a )
  285. {
  286. if (file_exists ( MB_TEMPLATES . '/' . $template . '/views' ))
  287. {
  288. $this->copyMetaRecursive ( MB_TEMPLATES . '/' . $template . '/views', $this->path . '/views/' ) ;
  289. }
  290. }
  291. }
  292. function copyCustomFiles ( $from , $to )
  293. {
  294. $d = dir ( $from ) ;
  295. while ( $filename = $d->read () )
  296. {
  297. if (substr ( $filename, 0, 1 ) == '.')
  298. continue ;
  299. if ( $filename != 'metadata' && $filename != 'Dashlets' && $filename != 'relationships' && $filename != 'language' && $filename != 'config.php' && $filename != 'relationships.php' && $filename != 'vardefs.php' )
  300. copy_recursive ( "$from/$filename" , "$to/$filename" ) ;
  301. }
  302. }
  303. function copyMetaData ()
  304. {
  305. $templates = array_reverse ( $this->config [ 'templates' ], true ) ;
  306. foreach ( $templates as $template => $a )
  307. {
  308. if (file_exists ( MB_TEMPLATES . '/' . $template . '/metadata' ))
  309. {
  310. $this->copyMetaRecursive ( MB_TEMPLATES . '/' . $template . '/metadata', $this->path . '/metadata/' ) ;
  311. }
  312. }
  313. }
  314. function copyMetaRecursive ($from , $to , $overwrite = false)
  315. {
  316. if (! file_exists ( $from ))
  317. return ;
  318. if (is_dir ( $from ))
  319. {
  320. $findArray = array ( '<module_name>' , '<_module_name>' , '<MODULE_NAME>' , '<object_name>' , '<_object_name>' , '<OBJECT_NAME>' );
  321. $replaceArray = array ( $this->key_name , strtolower ( $this->key_name ) , strtoupper ( $this->key_name ) ,
  322. $this->key_name , strtolower ( $this->key_name ) , strtoupper ( $this->key_name ) );
  323. mkdir_recursive ( $to ) ;
  324. $d = dir ( $from ) ;
  325. while ( $e = $d->read () )
  326. {
  327. if (substr ( $e, 0, 1 ) == '.')
  328. continue ;
  329. $nfrom = $from . '/' . $e ;
  330. $nto = $to . '/' . str_replace ( 'm-n-', $this->key_name, $e ) ;
  331. if (is_dir ( $nfrom ))
  332. {
  333. $this->copyMetaRecursive ( $nfrom, $nto, $overwrite ) ;
  334. } else
  335. {
  336. if ($overwrite || ! file_exists ( $nto ))
  337. {
  338. $contents = file_get_contents ( $nfrom ) ;
  339. $contents = str_replace ( $findArray, $replaceArray, $contents ) ;
  340. $fw = sugar_fopen ( $nto, 'w' ) ;
  341. fwrite ( $fw, $contents ) ;
  342. fclose ( $fw ) ;
  343. }
  344. }
  345. }
  346. }
  347. }
  348. function saveConfig ()
  349. {
  350. $header = file_get_contents ( 'modules/ModuleBuilder/MB/header.php' ) ;
  351. if (! write_array_to_file ( 'config', $this->config, $this->path . '/config.php', 'w', $header ))
  352. {
  353. $this->errors [] = 'Could not save config to ' . $this->path . '/config.php' ;
  354. }
  355. $this->setConfigMD5 () ;
  356. }
  357. function setConfigMD5 ()
  358. {
  359. if (file_exists ( $this->path . '/config.php' ))
  360. $this->config_md5 = md5 ( base64_encode ( serialize ( $this->config ) ) ) ;
  361. }
  362. function build ($basepath)
  363. {
  364. $path = $basepath . '/modules/' . $this->key_name ;
  365. if (mkdir_recursive ( $path ))
  366. {
  367. $this->createClasses ( $path ) ;
  368. if( $this->config['importable'] || in_array ( 'person', array_keys($this->config[ 'templates' ]) ) )
  369. $this->createMenu ( $path ) ;
  370. $this->copyCustomFiles ( $this->path , $path ) ;
  371. $this->copyMetaRecursive ( $this->path . '/metadata/', $path . '/metadata/', true ) ;
  372. $this->copyMetaRecursive ( $this->path . '/Dashlets/' . $this->key_name . 'Dashlet/',
  373. $path . '/Dashlets/' . $this->key_name . 'Dashlet/', true ) ;
  374. $this->relationships->build ( $basepath ) ;
  375. $this->mblanguage->build ( $path ) ;
  376. }
  377. }
  378. function createClasses ($path)
  379. {
  380. $class = array ( ) ;
  381. $class [ 'name' ] = $this->key_name ;
  382. $class [ 'table_name' ] = strtolower ( $class [ 'name' ] ) ;
  383. $class [ 'extends' ] = 'Basic' ;
  384. $class [ 'requires' ] [] = MB_TEMPLATES . '/basic/Basic.php' ;
  385. $class [ 'requires' ] = array ( ) ;
  386. $class [ 'audited' ] = (! empty ( $this->config [ 'audit' ] )) ? 'true' : 'false' ;
  387. $class [ 'acl' ] = ! empty ( $this->config [ 'acl' ] ) ;
  388. $class [ 'templates' ] = "'basic'" ;
  389. foreach ( $this->iTemplate as $template )
  390. {
  391. if (! empty ( $this->config [ $template ] ))
  392. {
  393. $class [ 'templates' ] .= ",'$template'" ;
  394. }
  395. }
  396. foreach ( $this->config [ 'templates' ] as $template => $a )
  397. {
  398. if ($template == 'basic')
  399. continue ;
  400. $class [ 'templates' ] .= ",'$template'" ;
  401. $class [ 'extends' ] = ucFirst ( $template ) ;
  402. $class [ 'requires' ] [] = MB_TEMPLATES . '/' . $template . '/' . ucfirst ( $template ) . '.php' ;
  403. }
  404. $class [ 'importable' ] = $this->config [ 'importable' ] ;
  405. $this->mbvardefs->updateVardefs () ;
  406. $class [ 'fields' ] = $this->mbvardefs->vardefs [ 'fields' ] ;
  407. $class [ 'fields_string' ] = var_export_helper ( $this->mbvardefs->vardef [ 'fields' ] ) ;
  408. $relationship = array ( ) ;
  409. $class [ 'relationships' ] = var_export_helper ( $this->mbvardefs->vardef [ 'relationships' ] ) ;
  410. $smarty = new Sugar_Smarty ( ) ;
  411. $smarty->left_delimiter = '{{' ;
  412. $smarty->right_delimiter = '}}' ;
  413. $smarty->assign ( 'class', $class ) ;
  414. //write sugar generated class
  415. $fp = sugar_fopen ( $path . '/' . $class [ 'name' ] . '_sugar.php', 'w' ) ;
  416. fwrite ( $fp, $smarty->fetch ( 'modules/ModuleBuilder/tpls/MBModule/Class.tpl' ) ) ;
  417. fclose ( $fp ) ;
  418. //write vardefs
  419. $fp = sugar_fopen ( $path . '/vardefs.php', 'w' ) ;
  420. fwrite ( $fp, $smarty->fetch ( 'modules/ModuleBuilder/tpls/MBModule/vardef.tpl' ) ) ;
  421. fclose ( $fp ) ;
  422. if (! file_exists ( $path . '/' . $class [ 'name' ] . '.php' ))
  423. {
  424. $fp = sugar_fopen ( $path . '/' . $class [ 'name' ] . '.php', 'w' ) ;
  425. fwrite ( $fp, $smarty->fetch ( 'modules/ModuleBuilder/tpls/MBModule/DeveloperClass.tpl' ) ) ;
  426. fclose ( $fp ) ;
  427. }
  428. if (! file_exists ( $path . '/metadata' ))
  429. mkdir_recursive ( $path . '/metadata' ) ;
  430. if (! empty ( $this->config [ 'studio' ] ))
  431. {
  432. $fp = sugar_fopen ( $path . '/metadata/studio.php', 'w' ) ;
  433. fwrite ( $fp, $smarty->fetch ( 'modules/ModuleBuilder/tpls/MBModule/Studio.tpl' ) ) ;
  434. fclose ( $fp ) ;
  435. } else
  436. {
  437. if (file_exists ( $path . '/metadata/studio.php' ))
  438. unlink ( $path . '/metadata/studio.php' ) ;
  439. }
  440. }
  441. function createMenu ($path)
  442. {
  443. $smarty = new Sugar_Smarty ( ) ;
  444. $smarty->assign ( 'moduleName', $this->key_name ) ;
  445. $smarty->assign ( 'showvCard', in_array ( 'person', array_keys($this->config[ 'templates' ]) ) ) ;
  446. $smarty->assign ( 'showimport', $this->config['importable'] );
  447. //write sugar generated class
  448. $fp = sugar_fopen ( $path . '/' . 'Menu.php', 'w' ) ;
  449. fwrite ( $fp, $smarty->fetch ( 'modules/ModuleBuilder/tpls/MBModule/Menu.tpl' ) ) ;
  450. fclose ( $fp ) ;
  451. }
  452. function addInstallDefs (&$installDefs)
  453. {
  454. $name = $this->key_name ;
  455. $installDefs [ 'copy' ] [] = array ( 'from' => '<basepath>/SugarModules/modules/' . $name , 'to' => 'modules/' . $name ) ;
  456. $installDefs [ 'beans' ] [] = array ( 'module' => $name , 'class' => $name , 'path' => 'modules/' . $name . '/' . $name . '.php' , 'tab' => $this->config [ 'has_tab' ] ) ;
  457. $this->relationships->addInstallDefs ( $installDefs ) ;
  458. }
  459. function getNodes ()
  460. {
  461. $lSubs = array ( ) ;
  462. $psubs = $this->getProvidedSubpanels () ;
  463. foreach ( $psubs as $sub )
  464. {
  465. $subLabel = $sub ;
  466. if ($subLabel == 'default')
  467. {
  468. $subLabel = $GLOBALS [ 'mod_strings' ] [ 'LBL_DEFAULT' ] ;
  469. }
  470. $lSubs [] = array ( 'name' => $subLabel , 'type' => 'list' , 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view=ListView&view_module=' . $this->name . '&view_package=' . $this->package . '&subpanel=' . $sub . '&subpanelLabel=' . $subLabel . '&local=1' ) ;
  471. }
  472. $searchSubs = array ( ) ;
  473. $searchSubs [] = array ( 'name' => translate('LBL_BASIC_SEARCH') , 'type' => 'list' , 'action' => "module=ModuleBuilder&MB=true&action=editLayout&view=basic_search&view_module={$this->name}&view_package={$this->package}" ) ;
  474. $searchSubs [] = array ( 'name' => translate('LBL_ADVANCED_SEARCH') , 'type' => 'list' , 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view=advanced_search&view_module=' . $this->name . '&view_package=' . $this->package ) ;
  475. $dashlets = array( );
  476. $dashlets [] = array('name' => translate('LBL_DASHLETLISTVIEW') , 'type' => 'dashlet' , 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view=dashlet&view_module=' . $this->name . '&view_package=' . $this->package );
  477. $dashlets [] = array('name' => translate('LBL_DASHLETSEARCHVIEW') , 'type' => 'dashletsearch' , 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view=dashletsearch&view_module=' . $this->name . '&view_package=' . $this->package );
  478. $popups = array( );
  479. $popups [] = array('name' => translate('LBL_POPUPLISTVIEW') , 'type' => 'popuplistview' , 'action' => 'module=ModuleBuilder&action=editLayout&view=popuplist&view_module=' . $this->name . '&view_package=' . $this->package );
  480. $popups [] = array('name' => translate('LBL_POPUPSEARCH') , 'type' => 'popupsearch' , 'action' => 'module=ModuleBuilder&action=editLayout&view=popupsearch&view_module=' . $this->name . '&view_package=' . $this->package );
  481. $layouts = array (
  482. array ( 'name' => translate('LBL_EDITVIEW') , 'type' => 'edit' , 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view='.MB_EDITVIEW.'&view_module=' . $this->name . '&view_package=' . $this->package ) ,
  483. array ( 'name' => translate('LBL_DETAILVIEW') , 'type' => 'detail' , 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view='.MB_DETAILVIEW.'&view_module=' . $this->name . '&view_package=' . $this->package ) ,
  484. array ( 'name' => translate('LBL_LISTVIEW') , 'type' => 'list' , 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view='.MB_LISTVIEW.'&view_module=' . $this->name . '&view_package=' . $this->package ) ,
  485. array ( 'name' => translate('LBL_QUICKCREATE') , 'type' => MB_QUICKCREATE, 'action' => 'module=ModuleBuilder&MB=true&action=editLayout&view='.MB_QUICKCREATE.'&view_module=' . $this->name . '&view_package=' . $this->package ) ,
  486. array ( 'name' => translate('LBL_DASHLET') , 'type' => 'Folder', 'children' => $dashlets, 'action' => 'module=ModuleBuilder&MB=true&action=wizard&view=dashlet&view_module=' . $this->name . '&view_package=' . $this->package ),
  487. array ( 'name' => translate('LBL_POPUP') , 'type' => 'Folder', 'children' => $popups, 'action' => 'module=ModuleBuilder&MB=true&action=wizard&view=popup&view_module=' . $this->name . '&view_package=' . $this->package ),
  488. array ( 'name' => translate('LBL_SEARCH_FORMS') , 'action' => 'module=ModuleBuilder&MB=true&action=wizard&view=search&view_module=' . $this->name . '&view_package=' . $this->package , 'type' => 'folder' , 'children' => $searchSubs )
  489. ) ;
  490. $children = array (
  491. array ( 'name' => translate('LBL_FIELDS') , 'action' => 'module=ModuleBuilder&action=modulefields&view_module=' . $this->name . '&view_package=' . $this->package ) ,
  492. array ( 'name' => translate('LBL_LABELS') , 'action' => 'module=ModuleBuilder&action=modulelabels&view_module=' . $this->name . '&view_package=' . $this->package ) ,
  493. array ( 'name' => translate('LBL_RELATIONSHIPS') , 'action' => 'module=ModuleBuilder&action=relationships&view_module=' . $this->name . '&view_package=' . $this->package ) ,
  494. array ( 'name' => translate('LBL_LAYOUTS') , 'type' => 'Folder' , 'action' => "module=ModuleBuilder&action=wizard&view_module={$this->name}&view_package={$this->package}&MB=1" , 'children' => $layouts ) ,
  495. ) ;
  496. if (count ( $lSubs ) > 0)
  497. {
  498. $children [] = array ( 'name' => translate('LBL_AVAILABLE_SUBPANELS') , 'type' => 'folder' , 'children' => $lSubs ) ;
  499. }
  500. $nodes = array ( 'name' => $this->name , 'children' => $children , 'action' => 'module=ModuleBuilder&action=module&view_module=' . $this->name . '&view_package=' . $this->package ) ;
  501. return $nodes ;
  502. }
  503. function getProvidedSubpanels ()
  504. {
  505. $this->providedSubpanels = array () ;
  506. $subpanelDir = $this->getModuleDir () . '/metadata/subpanels/' ;
  507. if (file_exists ( $subpanelDir ))
  508. {
  509. $f = dir ( $subpanelDir ) ;
  510. require_once 'modules/ModuleBuilder/parsers/relationships/AbstractRelationships.php' ;
  511. while ( $g = $f->read () )
  512. {
  513. // sanity check to confirm that this is a usable subpanel...
  514. if (substr ( $g, 0, 1 ) != '.' && AbstractRelationships::validSubpanel ( $subpanelDir . $g ))
  515. {
  516. $subname = str_replace ( '.php', '', $g ) ;
  517. $this->providedSubpanels [ $subname ] = $subname ;
  518. }
  519. }
  520. }
  521. return $this->providedSubpanels;
  522. }
  523. function getTypes ()
  524. {
  525. $types = array ( ) ;
  526. $d = dir ( MB_TEMPLATES ) ;
  527. while ( $e = $d->read () )
  528. {
  529. if (substr ( $e, 0, 1 ) != '.')
  530. {
  531. $types [ $e ] = $e ;
  532. }
  533. }
  534. return $types ;
  535. }
  536. function rename ($new_name)
  537. {
  538. $old = $this->getModuleDir () ;
  539. $old_name = $this->key_name;
  540. $this->name = $new_name ;
  541. $this->key_name = $this->package_key . '_' . $this->name ;
  542. $new = $this->getModuleDir () ;
  543. if (file_exists ( $new ))
  544. {
  545. return false ;
  546. }
  547. $renamed = rename ( $old, $new ) ;
  548. if ($renamed)
  549. {
  550. $this->renameMetaData ( $new , $old_name) ;
  551. $this->renameLanguageFiles ( $new ) ;
  552. }
  553. return $renamed ;
  554. }
  555. function renameLanguageFiles ($new_dir , $duplicate = false)
  556. {
  557. $this->mblanguage->name = $this->name ;
  558. $this->mblanguage->path = $new_dir ;
  559. $this->mblanguage->generateAppStrings () ;
  560. $this->mblanguage->save ( $this->key_name, $duplicate, true) ;
  561. }
  562. /**
  563. * Rename module name in metadata
  564. * @param string $new_dir
  565. * @param string $old_name
  566. */
  567. public function renameMetaData ($new_dir, $old_name)
  568. {
  569. $GLOBALS [ 'log' ]->debug ( 'MBModule.php->renameMetaData: new_dir=' . $new_dir ) ;
  570. if (! file_exists ( $new_dir ))
  571. return ;
  572. $dir = dir ( $new_dir ) ;
  573. while ( $e = $dir->read () )
  574. {
  575. if (substr ( $e, 0, 1 ) != '.')
  576. {
  577. if (is_dir ( $new_dir . '/' . $e ))
  578. {
  579. $this->renameMetaData ( $new_dir . '/' . $e, $old_name) ;
  580. }
  581. if (is_file ( $new_dir . '/' . $e ))
  582. {
  583. $contents = file_get_contents ( $new_dir . '/' . $e ) ;
  584. $search_array = array(
  585. '/(\$module_name[ ]*=[ ]*\').*(\'[ ]*;)/',
  586. '/(\$_module_name[ ]*=[ ]*\').*(\'[ ]*;)/',
  587. '/(\$MODULE_NAME[ ]*=[ ]*\').*(\'[ ]*;)/',
  588. '/(\$object_name[ ]*=[ ]*\').*(\'[ ]*;)/',
  589. '/(\$_object_name[ ]*=[ ]*\').*(\'[ ]*;)/',
  590. '/(\$OBJECT_NAME[ ]*=[ ]*\').*(\'[ ]*;)/'
  591. );
  592. $replace_array = array(
  593. '$1' . $this->key_name . '$2',
  594. '$1' . strtolower ( $this->key_name ) . '$2',
  595. '$1' . strtoupper ( $this->key_name ) . '$2',
  596. '$1' . $this->key_name . '$2',
  597. '$1' . strtolower ( $this->key_name ) . '$2',
  598. '$1' . strtoupper ( $this->key_name ) . '$2',
  599. );
  600. $contents = preg_replace($search_array, $replace_array, $contents);
  601. $search_array = array(
  602. "{$old_name}_",
  603. "{$old_name}Dashlet"
  604. );
  605. $replace_array = array(
  606. $this->key_name . '_',
  607. $this->key_name . 'Dashlet'
  608. );
  609. $contents = str_replace($search_array, $replace_array, $contents );
  610. if ("relationships.php" == $e)
  611. {
  612. //bug 39598 Relationship Name Is Not Updated If Module Name Is Changed In Module Builder
  613. $contents = str_replace ( "'{$old_name}'", "'{$this->key_name}'" , $contents ) ;
  614. }
  615. $fp = sugar_fopen ( $new_dir . '/' . $e, 'w' ) ;
  616. fwrite ( $fp, $contents ) ;
  617. fclose ( $fp ) ;
  618. }
  619. }
  620. }
  621. }
  622. function copy ($new_name)
  623. {
  624. $old = $this->getModuleDir () ;
  625. $count = 0 ;
  626. $old_name = $this->key_name;
  627. $this->name = $new_name ;
  628. $this->key_name = $this->package_key . '_' . $this->name ;
  629. $new = $this->getModuleDir () ;
  630. while ( file_exists ( $new ) )
  631. {
  632. $count ++ ;
  633. $this->name = $new_name . $count ;
  634. $this->key_name = $this->package_key . '_' . $this->name ;
  635. $new = $this->getModuleDir () ;
  636. }
  637. $new = $this->getModuleDir () ;
  638. $copied = copy_recursive ( $old, $new ) ;
  639. if ($copied)
  640. {
  641. $this->renameMetaData ( $new , $old_name) ;
  642. $this->renameLanguageFiles ( $new, true ) ;
  643. }
  644. return $copied ;
  645. }
  646. function delete ()
  647. {
  648. return rmdir_recursive ( $this->getModuleDir () ) ;
  649. }
  650. function populateFromPost ()
  651. {
  652. foreach ( $this->implementable as $key => $value )
  653. {
  654. $this->config [ $key ] = ! empty ( $_REQUEST [ $key ] ) ;
  655. }
  656. foreach ( $this->always_implement as $key => $value )
  657. {
  658. $this->config [ $key ] = true ;
  659. }
  660. if (! empty ( $_REQUEST [ 'type' ] ))
  661. {
  662. $this->addTemplate ( $_REQUEST [ 'type' ] ) ;
  663. }
  664. if (! empty ( $_REQUEST [ 'label' ] ))
  665. {
  666. $this->config [ 'label' ] = $_REQUEST [ 'label' ] ;
  667. }
  668. $this->config [ 'importable' ] = ! empty( $_REQUEST[ 'importable' ] ) ;
  669. }
  670. function getAvailibleSubpanelDef ($panelName)
  671. {
  672. $filepath = $this->getModuleDir () . "/metadata/subpanels/{$panelName}.php" ;
  673. if (file_exists ( $filepath ))
  674. {
  675. include ($filepath) ;
  676. return $subpanel_layout ;
  677. }
  678. return array ( ) ;
  679. }
  680. function saveAvailibleSubpanelDef ($panelName , $layout)
  681. {
  682. $dir = $this->getModuleDir () . "/metadata/subpanels" ;
  683. $filepath = "$dir/{$panelName}.php" ;
  684. if (mkdir_recursive ( $dir ))
  685. {
  686. // preserve any $module_name entry if one exists
  687. if (file_exists ( $filepath ))
  688. {
  689. include ($filepath) ;
  690. }
  691. $module_name = (isset ( $module_name )) ? $module_name : $this->key_name ;
  692. $layout = "<?php\n" . '$module_name=\'' . $module_name . "';\n" . '$subpanel_layout = ' . var_export_helper ( $layout ) . ";" ;
  693. $GLOBALS [ 'log' ]->debug ( "About to save this file to $filepath" ) ;
  694. $GLOBALS [ 'log' ]->debug ( $layout ) ;
  695. $fw = sugar_fopen ( $filepath, 'w' ) ;
  696. fwrite ( $fw, $layout ) ;
  697. fclose ( $fw ) ;
  698. }
  699. }
  700. function getLocalSubpanelDef ($panelName)
  701. {
  702. }
  703. function createIcon ()
  704. {
  705. $icondir = $this->package_path . "/icons" ;
  706. mkdir_recursive ( $icondir ) ;
  707. $template = "" ;
  708. foreach ( $this->config [ 'templates' ] as $temp => $val )
  709. $template = $temp ;
  710. copy ( "themes/default/images/icon_$template.gif", "$icondir/icon_" . ucfirst ( $this->key_name ) . ".gif" ) ;
  711. copy ( "include/SugarObjects/templates/$template/icons/$template.gif", "$icondir/" . $this->key_name . ".gif" ) ;
  712. if (file_exists("include/SugarObjects/templates/$template/icons/Create$template.gif"))
  713. copy ( "include/SugarObjects/templates/$template/icons/Create$template.gif", "$icondir/Create" . $this->key_name . ".gif" ) ;
  714. if (file_exists("include/SugarObjects/templates/$template/icons/{$template}_32.gif"))
  715. copy ( "include/SugarObjects/templates/$template/icons/{$template}_32.gif", "$icondir/icon_" . $this->key_name . "_32.gif" ) ;
  716. }
  717. function removeFieldFromLayouts ( $fieldName )
  718. {
  719. // hardcoded list of types for now, as also hardcoded in a different form in getNodes
  720. // TODO: replace by similar mechanism to StudioModule to determine the list of available views for this module
  721. $views = array ( 'editview' , 'detailview' , 'listview' , 'basic_search' , 'advanced_search' , 'dashlet' , 'popuplist');
  722. foreach ($views as $type )
  723. {
  724. $parser = ParserFactory::getParser( $type , $this->name , $this->package ) ;
  725. if ($parser->removeField ( $fieldName ) )
  726. $parser->handleSave(false) ; // don't populate from $_REQUEST, just save as is...
  727. }
  728. //Remove the fields in subpanel
  729. $psubs = $this->getProvidedSubpanels() ;
  730. foreach ( $psubs as $sub )
  731. {
  732. $parser = ParserFactory::getParser( MB_LISTVIEW , $this->name, $this->package , $sub) ;
  733. if ($parser->removeField ( $fieldName ) )
  734. $parser->handleSave(false) ;
  735. }
  736. }
  737. /**
  738. * Returns an array of fields defs with all the link fields for this module.
  739. * @return array
  740. */
  741. public function getLinkFields(){
  742. $list = $this->relationships->getRelationshipList();
  743. $field_defs = array();
  744. foreach($list as $name){
  745. $rel = $this->relationships->get($name);
  746. $relFields = $rel->buildVardefs();
  747. $relDef = $rel->getDefinition();
  748. $relLabels = $rel->getLabels();
  749. $relatedModule = $this->key_name == $relDef['rhs_module'] ? $relDef['lhs_module'] : $relDef['rhs_module'];
  750. if (!empty($relFields[$this->key_name]))
  751. {
  752. //Massage the result of getVardefs to look like field_defs
  753. foreach($relFields[$this->key_name] as $def) {
  754. $def['module'] = $relatedModule;
  755. $def['translated_label'] = empty($relLabels[$this->key_name][$def['vname']]) ?
  756. $name : $relLabels[$this->key_name][$def['vname']];
  757. $field_defs[$def['name']] = $def;
  758. }
  759. }
  760. }
  761. return $field_defs;
  762. }
  763. }
  764. ?>