SuiteCRM-Core/modules/UpgradeWizard/upgradeMetaHelper.php
Dillon-Brown 2473298dc6 Squashed 'public/legacy/' changes from 817a12dc0c..f058c4c306
f058c4c306 Fix #9106 - Update securexss for backwards compatibility
05471a51f3 Update composer.lock
dee3305fce 7.11.19
0952712425 Fix Calender display issues in FullCalender 3.10
91bfb1cf3a Fix #7999 - Prevent securitygroups mass assign damage
e36e1a52f5 Fix #5624 - Make SWSPEditRoleButton::displayList compatible w. parent
8265b5e29b Fix #8571 - Remove duplicate code in users detailviewdefs
f63f05a4a2 Fix #8514 - Implement effective opcache file clearing
5e671f3b1b Fix #8461, #8462 - PHP files are potentially overwritten
0b18500b42 Fix #8700 - Various problems in PHPDocs throughout the codebase.
25dce7954d Fix #9067 - Fix the drop down width
28eecb4198 Add Additional api filter option `like`
8b5a152f7f Add filters in relationship API
7a92e5ec8a Add Relationship Beans in V8 API Response
c192ccdf2e Fix #9090 - User menu alignment
466f2d96e7 Fix #6051 - Modulebuilder labels edit fixes
fe5ed90fd9 Update JQuery JS Library to v3.6.0
e0382c1a6c Update FullCalendar JS Library to v3.10.2
86882a4d4f Update YUI JS Library to 2.9.1
540245494b Fix #8999 - Hardcoded 'by' label in calls
e4f3c6a2fb Fix #9034 - Business Hours does not work in non-english languages
b0a51cc667 Fix #8910 - Update the V8 Api to allow for upload of documents similar to notes
8408cd8e91 Fix #9010 - Add missing 'view task' label on calendar
faa46f5a4c Fix #8894 - Add missing label for calendar dashlet
5905f3d308 Fix #9032 - Prevent Notice Error During Import
5c9e8700ba Fix #8182 - Update updateTimeDateFields to handle undefined dates
fc3dd03386 Fix #9075 - Removing deleted related beans via link
039d9a69d2 Fix #8988 - Improve upon solution which doesn't cache incomplete beans
f562c57c8d Fix #7772 - Only index ElasticSearch when enabled
dd1a5bc244 Fix #9101 LangText exception breaking ElasticSearch
0c861d3f1a Fix #8472 - No or not complete Searchresults using elasticsearch engine
e4e884667c Fix #6800 - Elasticsearch: Elastic index name is hardcoded
e525634d7b Fix #8916 - Misspelled elasticsearch labels
28d7afaa59 Fix #9080 - Update config for google/apiclient at composer.json
66bd8998ec Fix #9060 - Project Form action should not be changed if delete is not confirmed
06195fe5f1 Fix #8676 - New Scheduled Reports does not run
89341758e2 Fix #2645 - Calendar quick create ignores required fields
a329377bc0 Deprecate PdfParser
e5c03ad198 Deprecate advanced open discovery (AOD)

git-subtree-dir: public/legacy
git-subtree-split: f058c4c3062e7fff72cc2b62440bf064a63e6843
2021-05-20 11:54:15 +01:00

406 lines
16 KiB
PHP
Executable file

<?php
/**
*
* SugarCRM Community Edition is a customer relationship management program developed by
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
*
* SuiteCRM is an extension to SugarCRM Community Edition developed by SalesAgility Ltd.
* Copyright (C) 2011 - 2018 SalesAgility Ltd.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by the
* Free Software Foundation with the addition of the following permission added
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along with
* this program; if not, see http://www.gnu.org/licenses or write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
* SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
* these Appropriate Legal Notices must retain the display of the "Powered by
* SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
* reasonably feasible for technical reasons, the Appropriate Legal Notices must
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM".
*/
require_once 'include/utils/sugar_file_utils.php';
class UpgradeMetaHelper
{
public $upgrade_dir;
public $debug_mode;
public $upgrade_modules;
public $customized_modules;
public $source_dir;
public $dest_dir ;
public $evparser;
public $dvparser;
public $path_to_master_copy;
/**
* UpgradeMetaHelper
* This is the constructor for the UpgradeMetaHelper class
* @param $dir The root upgrade directory (where to copy working files)
* @param $masterCopyDirectory The root master directory (where SugarCRM 5.x files reside)
* @param $debugMode Debug mode, default is false
*
*/
public function __construct($dir='upgrade', $masterCopyDirecotry='modules_50', $debugMode = false)
{
$this->upgrade_dir = $dir;
$this->debug_mode = $debugMode;
$this->upgrade_modules = $this->getModifiedModules();
if (count($this->upgrade_modules) > 0) {
$_SESSION['Upgraded_Modules'] = $this->upgrade_modules;
$this->create_upgrade_directory();
$this->path_to_master_copy = $masterCopyDirecotry;
$this->runParser();
}
$this->customized_modules = $this->getAllCustomizedModulesBeyondStudio();
if (count($this->customized_modules) > 0) {
$_SESSION['Customized_Modules'] = $this->customized_modules;
}
}
/**
* getModifiedModules
* This method returns a two-dimensional Array of Studio enabled
* modules that have been modified. The second Array index is an
* Array of files that do not match the md5 checksum for the module
* @return $return_array Two-dimensional Array of [module][modified file(s) Array]
*/
public function getModifiedModules()
{
$md5_string = array();
if (file_exists(clean_path(getcwd().'/files.md5'))) {
require(clean_path(getcwd().'/files.md5'));
}
$return_array = array();
$modules = $this->loadStudioModules();
foreach ($modules as $mod) {
$editView = "modules/$mod/EditView.html";
$detailView = "modules/$mod/DetailView.html";
$searchForm = "modules/$mod/SearchForm.html";
if (file_exists($editView) && isset($md5_string['./' . $editView])) {
$fileContents = file_get_contents($editView);
if (md5($fileContents) != $md5_string['./' . $editView]) {
$return_array[$mod][] = $editView;
}
}
if (file_exists($detailView) && isset($md5_string['./' . $detailView])) {
$fileContents = file_get_contents($detailView);
if (md5($fileContents) != $md5_string['./' . $detailView]) {
$return_array[$mod][] = $detailView;
}
}
if (file_exists($searchForm) && isset($md5_string['./' . $searchForm])) {
$fileContents = file_get_contents($searchForm);
if (md5($fileContents) != $md5_string['./' . $searchForm]) {
$return_array[$mod][] = $searchForm;
}
}
} //foreach
return $return_array;
}
public function saveMatchingFilesQueries($currStep, $value)
{
$upgrade_progress_dir = sugar_cached('upgrades/temp');
if (!is_dir($upgrade_progress_dir) && !mkdir($upgrade_progress_dir) && !is_dir($upgrade_progress_dir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $upgrade_progress_dir));
}
$file_queries_file = $upgrade_progress_dir.'/files_queries.php';
if (file_exists($file_queries_file)) {
include($file_queries_file);
} else {
if (function_exists('sugar_fopen')) {
sugar_fopen($file_queries_file, 'w+');
} else {
fopen($file_queries_file, 'wb+');
}
}
if (!isset($files_queries) || $files_queries == null) {
$files_queries = array();
}
$files_queries[$currStep]=$value;
if (is_writable($file_queries_file) && write_array_to_file(
"file_queries",
$file_queries,
$file_queries_file
)) {
//writing to the file
}
}
public function getAllCustomizedModulesBeyondStudio()
{
require_once('modules/UpgradeWizard/uw_utils.php');
$md5_string = array();
if (file_exists(clean_path(getcwd().'/files.md5'))) {
require(clean_path(getcwd().'/files.md5'));
}
$return_array = array();
$modules = $this->loadStudioModules();
$modulesAll = getAllModules(); //keep all modules as well
$allOtherModules = array_diff($modulesAll, $modules);
foreach ($modules as $mod) {
if (!is_dir('modules/'.$mod)) {
continue;
}
$editView = "modules/$mod/EditView.html";
$detailView ="modules/$mod/DetailView.html";
$exclude_files[]=$editView;
$exclude_files[]=$detailView;
$allModFiles = array();
$allModFiles = findAllFiles('modules/'.$mod, $allModFiles);
foreach ($allModFiles as $file) {
//$file_md5_ref = str_replace(clean_path(getcwd()),'',$file);
if (file_exists($file) && !in_array($file, $exclude_files)) {
if (isset($md5_string['./'.$file])) {
$fileContents = file_get_contents($file);
if (md5($fileContents) != $md5_string['./'.$file]) {
$return_array[$mod][] = $file;
} else {
//keep in the array to be deleted later
$_SESSION['removeMd5MatchingFiles'][] = $file;
}
}
}
}
} //foreach
//also check out other non-studio modules by taking the difference between
//allMOdules and
foreach ($allOtherModules as $mod) {
if (!is_dir('modules/'.$mod)) {
continue;
}
$allModFiles = array();
$allModFiles = findAllFiles('modules/'.$mod, $allModFiles);
foreach ($allModFiles as $file) {
//$file_md5_ref = str_replace(clean_path(getcwd()),'',$file);
if (file_exists($file)) {
if (isset($md5_string['./'.$file])) {
$fileContents = file_get_contents($file);
if (md5($fileContents) == $md5_string['./'.$file]) {
$_SESSION['removeMd5MatchingFiles'][] = $file;
}
}
}
}
}
//Also store in a file
//saveMatchingFilesQueries('removeMd5MatchingFiles',$_SESSION['removeMd5MatchingFiles']);
return $return_array;
}
/**
* Get all the customized modules. Compare the file md5s with the base md5s
* If a file has been modified then put the module in the list of customized
* modules. Show the list in the preflight check UI.
*/
public function getAllCustomizedModules()
{
require_once('files.md5');
$return_array = array();
$modules = getAllModules();
foreach ($modules as $mod) {
//find all files in each module if the files have been modified
//as compared to the base version then add the module to the
//customized modules array
$modFiles = findAllFiles(clean_path(getcwd())."/modules/$mod", array());
foreach ($modFiles as $file) {
$fileContents = file_get_contents($file);
$file = str_replace(clean_path(getcwd()), '', $file);
if ($md5_string['./' . $file]) {
if (md5($fileContents) != $md5_string['./' . $file]) {
//A file has been customized in the module. Put the module into the
// customized modules array.
echo 'Changed File'.$file;
$return_array[$mod];
break;
}
} else {
// This is a new file in user's version and indicates that module has been
//customized. Put the module in the customized array.
echo 'New File'.$file;
$return_array[$mod];
break;
}
}
} //foreach
return $return_array;
}
/**
* loadStudioModules
* This method returns an Array of all modules where a studio.php file is
* present in the metadata directory of the module
* @return $modules Array of modules that are studio enabled
*/
public function loadStudioModules()
{
$modules = array();
$d = dir('modules');
while ($e = $d->read()) {
if (substr($e, 0, 1) == '.' || !is_dir('modules/' . $e)) {
continue;
}
if (file_exists('modules/' . $e . '/metadata/studio.php')) {
$modules[] = $e;
}
}
return $modules;
}
/**
* runParser
* This method creates the EditView and DetailView parser intances
* and runs the parsing for the modules to upgrade
*
*/
public function runParser()
{
require_once('include/SugarFields/Parsers/EditViewMetaParser.php');
require_once('include/SugarFields/Parsers/DetailViewMetaParser.php');
require_once('include/SugarFields/Parsers/SearchFormMetaParser.php');
$this->evparser = new EditViewMetaParser();
$this->dvparser = new DetailViewMetaParser();
$this->svparser = new SearchFormMetaParser();
foreach ($this->upgrade_modules as $module_name=>$files) {
$this->parseFile($module_name, $files);
} //foreach
}
/**
* parseFile
* Hanldes parsing the files for given module where Studio or manual
* changes have been detected.
* @param $module_name The module to parse
* @param $files Array of files found to parse
*
*/
public function parseFile($module_name, $files)
{
global $beanList, $dictionary;
foreach ($files as $file) {
if (preg_match('/(EditView|DetailView|SearchForm|QuickCreate)(\.html|\.tpl)$/s', $file, $matches)) {
$view = $matches[1];
switch ($view) {
case 'EditView': $parser = $this->evparser; break;
case 'DetailView': $parser = $this->dvparser; break;
case 'SearchForm': $parser = $this->svparser; break;
}
$lowerCaseView = $view == 'SearchForm' ? 'search' : strtolower($view);
include('modules/'.$module_name.'/vardefs.php');
$bean_name = $beanList[$module_name];
$newFile = $this->upgrade_dir.'/modules/'.$module_name.'/metadata/'.$lowerCaseView.'defs.php';
$bean_name = $bean_name == 'aCase' ? 'Case' : $bean_name;
sugar_file_put_contents($newFile, $parser->parse(
$file,
$dictionary[$bean_name]['fields'],
$module_name,
true,
$this->path_to_master_copy.'/modules/'.$module_name.'/metadata/'.$lowerCaseView.'defs.php'
));
} //if
} //foreach
}
/**
* create_upgrade_directory
* Creates a directory called upgrade to house all the modules that are studio enabled.
* Also creates subdirectories for all studio enabled modules.
*
*/
public function create_upgrade_directory()
{
$dir = $this->upgrade_dir . '/modules';
if (!file_exists($this->upgrade_dir) && !mkdir($concurrentDirectory = $this->upgrade_dir,
0755) && !is_dir($concurrentDirectory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
}
if (!file_exists($dir) && !mkdir($dir, 0755) && !is_dir($dir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $dir));
}
foreach ($this->upgrade_modules as $module => $files) {
if (!file_exists($dir . '/' . $module) && !mkdir($concurrentDirectory = $dir . '/' . $module,
0755) && !is_dir($concurrentDirectory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
}
if (!file_exists($dir . '/' . $module . '/metadata') && !mkdir($concurrentDirectory = $dir . '/' . $module . '/metadata',
0755) && !is_dir($concurrentDirectory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
}
foreach ($files as $file) {
if (file_exists($file) && is_file($file)) {
copy($file, $this->upgrade_dir . '/' . $file);
} //if
} //foreach
}
}
/**
* verifyMetaData
* This function does some quick checks to make sure the metadataFile at
* least has an Array panel
*
* @param $metadataFile The path to the metadata file to verify
* @param $module The module to verify
* @param $view The view (EditView or DetailView)
* @return boolean true if verification check is okay; false otherwise
*/
public function verifyMetaData($metadataFile, $module, $view)
{
if (!file_exists($metadataFile) || !is_file($metadataFile)) {
return false;
}
include($metadataFile);
if (isset($viewdefs) && isset($viewdefs[$module][$view]['panels']) && is_array($viewdefs[$module][$view]['panels'])) {
return true;
}
if (isset($searchdefs) && isset($searchdefs[$module]) && is_array($searchdefs[$module])) {
return true;
}
return false;
}
}