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

/modules/UpgradeWizard/upgradeMetaHelper.php

https://bitbucket.org/cviolette/sugarcrm
PHP | 393 lines | 241 code | 47 blank | 105 comment | 59 complexity | e8ec7f254fdb515c8e519d4535c3954d 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. class UpgradeMetaHelper{
  37. var $upgrade_dir;
  38. var $debug_mode;
  39. var $upgrade_modules;
  40. var $customized_modules;
  41. var $source_dir;
  42. var $dest_dir ;
  43. var $evparser;
  44. var $dvparser;
  45. var $path_to_master_copy;
  46. /**
  47. * UpgradeMetaHelper
  48. * This is the constructor for the UpgradeMetaHelper class
  49. * @param $dir The root upgrade directory (where to copy working files)
  50. * @param $masterCopyDirectory The root master directory (where SugarCRM 5.x files reside)
  51. * @param $debugMode Debug mode, default is false
  52. *
  53. */
  54. function UpgradeMetaHelper($dir='upgrade', $masterCopyDirecotry='modules_50', $debugMode = false) {
  55. $this->upgrade_dir = $dir;
  56. $this->debug_mode = $debugMode;
  57. $this->upgrade_modules = $this->getModifiedModules();
  58. if(count($this->upgrade_modules) > 0) {
  59. $_SESSION['Upgraded_Modules'] = $this->upgrade_modules;
  60. $this->create_upgrade_directory();
  61. $this->path_to_master_copy = $masterCopyDirecotry;
  62. $this->runParser();
  63. }
  64. $this->customized_modules = $this->getAllCustomizedModulesBeyondStudio();
  65. if(count($this->customized_modules) > 0) {
  66. $_SESSION['Customized_Modules'] = $this->customized_modules;
  67. }
  68. }
  69. /**
  70. * getModifiedModules
  71. * This method returns a two-dimensional Array of Studio enabled
  72. * modules that have been modified. The second Array index is an
  73. * Array of files that do not match the md5 checksum for the module
  74. * @return $return_array Two-dimensional Array of [module][modified file(s) Array]
  75. */
  76. function getModifiedModules() {
  77. $md5_string = array();
  78. if(file_exists(clean_path(getcwd().'/files.md5'))){
  79. require(clean_path(getcwd().'/files.md5'));
  80. }
  81. $return_array = array();
  82. $modules = $this->loadStudioModules();
  83. foreach($modules as $mod) {
  84. $editView = "modules/$mod/EditView.html";
  85. $detailView = "modules/$mod/DetailView.html";
  86. $searchForm = "modules/$mod/SearchForm.html";
  87. if(file_exists($editView) && isset($md5_string['./' . $editView])) {
  88. $fileContents = file_get_contents($editView);
  89. if(md5($fileContents) != $md5_string['./' . $editView]) {
  90. $return_array[$mod][] = $editView;
  91. }
  92. }
  93. if(file_exists($detailView) && isset($md5_string['./' . $detailView])) {
  94. $fileContents = file_get_contents($detailView);
  95. if(md5($fileContents) != $md5_string['./' . $detailView]) {
  96. $return_array[$mod][] = $detailView;
  97. }
  98. }
  99. if(file_exists($searchForm) && isset($md5_string['./' . $searchForm])) {
  100. $fileContents = file_get_contents($searchForm);
  101. if(md5($fileContents) != $md5_string['./' . $searchForm]) {
  102. $return_array[$mod][] = $searchForm;
  103. }
  104. }
  105. } //foreach
  106. return $return_array;
  107. }
  108. function saveMatchingFilesQueries($currStep,$value){
  109. $upgrade_progress_dir = sugar_cached('upgrades/temp');
  110. if(!is_dir($upgrade_progress_dir)){
  111. mkdir($upgrade_progress_dir);
  112. }
  113. $file_queries_file = $upgrade_progress_dir.'/files_queries.php';
  114. if(file_exists($file_queries_file)){
  115. include($file_queries_file);
  116. }
  117. else{
  118. if(function_exists('sugar_fopen')){
  119. sugar_fopen($file_queries_file, 'w+');
  120. }
  121. else{
  122. fopen($file_queries_file, 'w+');
  123. }
  124. }
  125. if(!isset($files_queries) || $files_queries == NULL){
  126. $files_queries = array();
  127. }
  128. $files_queries[$currStep]=$value;
  129. if(is_writable($file_queries_file) && write_array_to_file( "file_queries", $file_queries,
  130. $file_queries_file)) {
  131. //writing to the file
  132. }
  133. }
  134. function getAllCustomizedModulesBeyondStudio() {
  135. require_once('modules/UpgradeWizard/uw_utils.php');
  136. $md5_string = array();
  137. if(file_exists(clean_path(getcwd().'/files.md5'))){
  138. require(clean_path(getcwd().'/files.md5'));
  139. }
  140. $return_array = array();
  141. $modules = $this->loadStudioModules();
  142. $modulesAll = getAllModules(); //keep all modules as well
  143. $allOtherModules = array_diff($modulesAll,$modules);
  144. foreach($modules as $mod) {
  145. if(!is_dir('modules/'.$mod)) continue;
  146. $editView = "modules/$mod/EditView.html";
  147. $detailView ="modules/$mod/DetailView.html";
  148. $exclude_files[]=$editView;
  149. $exclude_files[]=$detailView;
  150. $allModFiles = array();
  151. $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
  152. foreach($allModFiles as $file){
  153. //$file_md5_ref = str_replace(clean_path(getcwd()),'',$file);
  154. if(file_exists($file) && !in_array($file,$exclude_files)){
  155. if(isset($md5_string['./'.$file])) {
  156. $fileContents = file_get_contents($file);
  157. if(md5($fileContents) != $md5_string['./'.$file]) {
  158. $return_array[$mod][] = $file;
  159. }
  160. else{
  161. //keep in the array to be deleted later
  162. $_SESSION['removeMd5MatchingFiles'][] = $file;
  163. }
  164. }
  165. }
  166. }
  167. } //foreach
  168. //also check out other non-studio modules by taking the difference between
  169. //allMOdules and
  170. foreach($allOtherModules as $mod) {
  171. if(!is_dir('modules/'.$mod)) continue;
  172. $allModFiles = array();
  173. $allModFiles = findAllFiles('modules/'.$mod,$allModFiles);
  174. foreach($allModFiles as $file){
  175. //$file_md5_ref = str_replace(clean_path(getcwd()),'',$file);
  176. if(file_exists($file)){
  177. if(isset($md5_string['./'.$file])) {
  178. $fileContents = file_get_contents($file);
  179. if(md5($fileContents) == $md5_string['./'.$file]) {
  180. $_SESSION['removeMd5MatchingFiles'][] = $file;
  181. }
  182. }
  183. }
  184. }
  185. }
  186. //Also store in a file
  187. //saveMatchingFilesQueries('removeMd5MatchingFiles',$_SESSION['removeMd5MatchingFiles']);
  188. return $return_array;
  189. }
  190. /**
  191. * Get all the customized modules. Compare the file md5s with the base md5s
  192. * If a file has been modified then put the module in the list of customized
  193. * modules. Show the list in the preflight check UI.
  194. */
  195. function getAllCustomizedModules() {
  196. require_once('files.md5');
  197. $return_array = array();
  198. $modules = getAllModules();
  199. foreach($modules as $mod) {
  200. //find all files in each module if the files have been modified
  201. //as compared to the base version then add the module to the
  202. //customized modules array
  203. $modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
  204. foreach($modFiles as $file){
  205. $fileContents = file_get_contents($file);
  206. $file = str_replace(clean_path(getcwd()),'',$file);
  207. if($md5_string['./' . $file]){
  208. if(md5($fileContents) != $md5_string['./' . $file]) {
  209. //A file has been customized in the module. Put the module into the
  210. // customized modules array.
  211. echo 'Changed File'.$file;
  212. $return_array[$mod];
  213. break;
  214. }
  215. }
  216. else{
  217. // This is a new file in user's version and indicates that module has been
  218. //customized. Put the module in the customized array.
  219. echo 'New File'.$file;
  220. $return_array[$mod];
  221. break;
  222. }
  223. }
  224. } //foreach
  225. return $return_array;
  226. }
  227. /**
  228. * loadStudioModules
  229. * This method returns an Array of all modules where a studio.php file is
  230. * present in the metadata directory of the module
  231. * @return $modules Array of modules that are studio enabled
  232. */
  233. function loadStudioModules() {
  234. $modules = array();
  235. $d = dir('modules');
  236. while($e = $d->read()){
  237. if(substr($e, 0, 1) == '.' || !is_dir('modules/' . $e))continue;
  238. if(file_exists('modules/' . $e . '/metadata/studio.php')){
  239. $modules[] = $e;
  240. }
  241. }
  242. return $modules;
  243. }
  244. /**
  245. * runParser
  246. * This method creates the EditView and DetailView parser intances
  247. * and runs the parsing for the modules to upgrade
  248. *
  249. */
  250. function runParser() {
  251. require_once('include/SugarFields/Parsers/EditViewMetaParser.php');
  252. require_once('include/SugarFields/Parsers/DetailViewMetaParser.php');
  253. require_once('include/SugarFields/Parsers/SearchFormMetaParser.php');
  254. $this->evparser = new EditViewMetaParser();
  255. $this->dvparser = new DetailViewMetaParser();
  256. $this->svparser = new SearchFormMetaParser();
  257. foreach($this->upgrade_modules as $module_name=>$files) {
  258. $this->parseFile($module_name, $files);
  259. } //foreach
  260. }
  261. /**
  262. * parseFile
  263. * Hanldes parsing the files for given module where Studio or manual
  264. * changes have been detected.
  265. * @param $module_name The module to parse
  266. * @param $files Array of files found to parse
  267. *
  268. */
  269. function parseFile($module_name, $files) {
  270. global $beanList, $dictionary;
  271. foreach($files as $file) {
  272. if(preg_match('/(EditView|DetailView|SearchForm|QuickCreate)(\.html|\.tpl)$/s', $file, $matches)) {
  273. $view = $matches[1];
  274. switch($view) {
  275. case 'EditView' : $parser = $this->evparser; break;
  276. case 'DetailView' : $parser = $this->dvparser; break;
  277. case 'SearchForm' : $parser = $this->svparser; break;
  278. }
  279. $lowerCaseView = $view == 'SearchForm' ? 'search' : strtolower($view);
  280. include('modules/'.$module_name.'/vardefs.php');
  281. $bean_name = $beanList[$module_name];
  282. $newFile = $this->upgrade_dir.'/modules/'.$module_name.'/metadata/'.$lowerCaseView.'defs.php';
  283. $evfp = fopen($newFile,'w');
  284. $bean_name = $bean_name == 'aCase' ? 'Case' : $bean_name;
  285. fwrite($evfp, $parser->parse($file,
  286. $dictionary[$bean_name]['fields'],
  287. $module_name,
  288. true,
  289. $this->path_to_master_copy.'/modules/'.$module_name.'/metadata/'.$lowerCaseView.'defs.php'));
  290. fclose($evfp);
  291. } //if
  292. } //foreach
  293. }
  294. /**
  295. * create_upgrade_directory
  296. * Creates a directory called upgrade to house all the modules that are studio enabled.
  297. * Also creates subdirectories for all studio enabled modules.
  298. *
  299. */
  300. function create_upgrade_directory() {
  301. $dir = $this->upgrade_dir.'/modules';
  302. if(!file_exists($this->upgrade_dir)) {
  303. mkdir($this->upgrade_dir, 0755);
  304. }
  305. if(!file_exists($dir)) {
  306. mkdir($dir, 0755);
  307. }
  308. foreach($this->upgrade_modules as $module=>$files){
  309. if(!file_exists($dir.'/'.$module)) {
  310. mkdir($dir.'/'.$module, 0755);
  311. }
  312. if(!file_exists($dir.'/'.$module.'/metadata')) {
  313. mkdir($dir.'/'.$module.'/metadata', 0755);
  314. }
  315. foreach($files as $file) {
  316. if(file_exists($file) && is_file($file)) {
  317. copy($file, $this->upgrade_dir.'/'.$file);
  318. } //if
  319. } //foreach
  320. }
  321. }
  322. /**
  323. * verifyMetaData
  324. * This function does some quick checks to make sure the metadataFile at
  325. * least has an Array panel
  326. *
  327. * @param $metadataFile The path to the metadata file to verify
  328. * @param $module The module to verify
  329. * @param $view The view (EditView or DetailView)
  330. * @return boolean true if verification check is okay; false otherwise
  331. */
  332. function verifyMetaData($metadataFile, $module, $view) {
  333. if(!file_exists($metadataFile) || !is_file($metadataFile)) {
  334. return false;
  335. }
  336. include($metadataFile);
  337. if(isset($viewdefs) && isset($viewdefs[$module][$view]['panels']) && is_array($viewdefs[$module][$view]['panels'])) {
  338. return true;
  339. }
  340. if(isset($searchdefs) && isset($searchdefs[$module]) && is_array($searchdefs[$module])) {
  341. return true;
  342. }
  343. return false;
  344. }
  345. }
  346. ?>