403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/main/admin/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/main/admin/update_system_expert.php
<?php
//**********************************************************************/
//**    DO NOT MODIFY THIS FILE                                       **/
//**    MODIFICATION OF THIS FILE WILL ENTAIL SITE FAILURE            **/
//**********************************************************************/
/** @var array $arUpdateList */
/** @var array $arClientModules */

class UpdateSystemExpertHelper
{
	protected $updateList;
	protected $clientModules;

	public function __construct(array $updateList, array $clientModules)
	{
		$this->clientModules = $clientModules;
		$this->updateList = $updateList;
		$this->enrichUpdatesListByLastVersionsOfInstalledModules();
	}

	public function getUpdatesCount(): int
	{
		if (
			isset($this->updateList["MODULES"][0]["#"]["MODULE"])
			&& is_array($this->updateList["MODULES"][0]["#"]["MODULE"])
		)
		{
			return count($this->updateList["MODULES"][0]["#"]["MODULE"]);
		}

		return 0;
	}

	public function getUpdatesList(): array
	{
		if ($this->getUpdatesCount() > 0)
		{
			return $this->updateList["MODULES"][0]["#"]["MODULE"];
		}

		return [];
	}

	public function getClientModules(): array
	{
		return $this->clientModules;
	}

	public function escapeModuleId(string $moduleId): string
	{
		$moduleId = preg_replace("#[^A-Za-z0-9._-]#", "", $moduleId);

		return CUtil::JSEscape(htmlspecialcharsbx($moduleId));
	}

	public function getUpdateIdentifier(string $moduleId, string $version): string
	{
		return $moduleId . '|' . $version;
	}

	public function getJavascriptObjectWithDependencies(): string
	{
		$result = '';

		if (
			!isset($this->updateList['MODULES'][0]['#']['MODULE'])
			|| !is_array($this->updateList['MODULES'][0]['#']['MODULE'])
		)
		{
			return '';
		}
		foreach ($this->updateList['MODULES'][0]['#']['MODULE'] as $moduleDescription)
		{
			if (
				!isset($moduleDescription['#']['VERSION'])
				|| !is_array($moduleDescription['#']['VERSION'])
			)
			{
				continue;
			}
			$moduleName = $this->escapeModuleId($moduleDescription['@']['ID']);
			if (empty($moduleName))
			{
				continue;
			}
			$versionsList = $this->flattenModuleUpdates($moduleName, $moduleDescription['#']['VERSION']);
			if (empty($versionsList))
			{
				continue;
			}
			if (!empty($result))
			{
				$result .= ', ';
			}
			$result .= $versionsList;
		}

		return $result;
	}

	public function getJavascriptObjectWithUpdates()
	{
		$count = [];
		foreach ($this->getUpdatesList() as $moduleUpdates)
		{
			$moduleName = $this->escapeModuleId($moduleUpdates['@']['ID']);
			if (isset($moduleUpdates["#"]["VERSION"]) && is_array($moduleUpdates["#"]["VERSION"]))
			{
				$count[$moduleName] = count($moduleUpdates["#"]["VERSION"]);
			}
			else
			{
				$count[$moduleName] = 1;
			}
		}

		$result = '';
		foreach ($count as $moduleName => $cnt)
		{
			if (!empty($result))
			{
				$result .= ',';
			}
			$result .= '"' . $moduleName . '": ' . $cnt;
		}

		return $result;
	}

	protected function flattenModuleUpdates(string $moduleName, array $versions): string
	{
		$result = '';
		$previousVersion = null;

		foreach ($versions as $versionDescription)
		{
			if (!isset($versionDescription['@']['ID']))
			{
				continue;
			}
			$version = $versionDescription['@']['ID'];
			$identifier = $this->getUpdateIdentifier($moduleName, $version);
			$dependencies = [];
			if ($previousVersion)
			{
				$dependencies[] = $previousVersion;
			}
			$previousVersion = $identifier;
			if (!empty($result))
			{
				$result .= ',';
			}
			$result .= "\"" . $identifier . "\":[";
			if (
				isset($versionDescription['#']['VERSION_CONTROL'])
				&& is_array($versionDescription['#']['VERSION_CONTROL'])
			)
			{
				foreach ($versionDescription['#']['VERSION_CONTROL'] as $dependency)
				{
					if (isset($dependency['@']['MODULE']) && isset($dependency['@']['VERSION']))
					{
						$identifier = $this->getUpdateIdentifier(
							$dependency['@']['MODULE'],
							$dependency['@']['VERSION']
						);
						$dependencies[] = $identifier;
					}
				}
				$dependencies = array_unique($dependencies);
			}
			if (!empty($dependencies))
			{
				$result .= "\"" . implode('","', $dependencies) . "\"";
			}
			$result .= "]";
		}

		return $result;
	}

	private function enrichUpdatesListByLastVersionsOfInstalledModules(): void
	{
		$clientModules = $this->getClientModules();
		$presentModulesWithUpdates = [];
		if (isset($this->updateList['MODULES'][0]['#']['MODULE']))
		{
			foreach ($this->updateList['MODULES'][0]['#']['MODULE'] as $moduleUpdates)
			{
				$moduleId = $this->escapeModuleId($moduleUpdates["@"]["ID"]);
				$presentModulesWithUpdates[$moduleId] = $moduleId;
			}
		}
		else
		{
			$this->updateList['MODULES'][0]['#'] = [];
		}

		foreach ($clientModules as $moduleId => $version)
		{
			if (!isset($presentModulesWithUpdates[$moduleId]))
			{
				[$name, $description] = $this->getModuleInfo($moduleId);
				$this->updateList['MODULES'][0]['#']['MODULE'][] = [
					'@' => [
						'ID' => $moduleId,
						'NAME' => $name,
						'DESCRIPTION' => $description,
					],
					'#' => [],
				];
			}
		}
	}

	private function getModuleInfo($moduleId)
	{
		$module = CModule::CreateModuleObject($moduleId);
		$name = $moduleId;
		$description = '';
		if (is_object($module))
		{
			$name = $module->MODULE_NAME ?? $moduleId;
			$description = $module->MODULE_DESCRIPTION ?? '';
		}

		return [$name, $description];
	}
}

$expertUpdateHelper = new UpdateSystemExpertHelper($arUpdateList, $arClientModules);
$updatesCount = $expertUpdateHelper->getUpdatesCount();

?>
<!--suppress HtmlDeprecatedAttribute -->
<!--suppress HtmlFormInputWithoutLabel -->
<!--suppress JSPrimitiveTypeWrapperUsage -->
<!--suppress ES6ConvertVarToLetConst -->
<style>
	.conflicts_message {
		margin-top: 16px;
    }
	.conflicts_message.conflicts_message_hidden {
		display: none;
	}
	.conflicts_message .conflicts_message_title {
		font-weight: bold;
		margin-bottom: 8px;
	}
	#expert_install_conflicts_message {
		line-height: 150%;
    }
	#expert_install_conflicts_message a {
		text-decoration: none;
    }
</style>
<tr>
	<td colspan="2">
		<table border="0" cellspacing="0" cellpadding="0" width="100%">
			<tr>
				<td colspan="2"><?= GetMessage("SUP_SULL_CNT") ?>: <?= $updatesCount ?><BR><BR></td>
			</tr>
			<tr>
				<td>
					<input TYPE="button" ID="expert_install_updates_sel_button" NAME="expert_install_updates"<?= (($updatesCount <= 0) ? " disabled" : "") ?> value="<?= GetMessage("SUP_SULL_BUTTON") ?>" onclick="UpdateSystemExpertHelper.getInstance().handleInstallUpdatesButtonClicked()">
				</td>
				<td align="right">
					<input TYPE="button" value="<?= GetMessage('SUP_EXPORT_BUTTON') ?>" title="<?= GetMessage('SUP_EXPORT_TITLE') ?>" onclick="UpdateSystemExpertHelper.getInstance().handleExportButtonClicked()">
					<input TYPE="button" value="<?= GetMessage('SUP_IMPORT_BUTTON') ?>" title="<?= GetMessage('SUP_IMPORT_TITLE') ?>" onclick="UpdateSystemExpertHelper.getInstance().handleImportButtonClicked()">
				</td>
			</tr>
			<tr>
				<td colspan="2">
					<div id="expert_install_conflicts" class="conflicts_message conflicts_message_hidden">
						<div class="conflicts_message_title"><?=GetMessage('SUP_CONFLICT_POPUP_TITLE');?></div>
						<div id="expert_install_conflicts_message"></div>
					</div>
				</td>
			</tr>
		</table>
		<br>
		<table border="0" cellspacing="1" cellpadding="3" width="100%" class="internal" id="expert_table_updates_sel_list">
			<tr>
				<td class="heading"><INPUT TYPE="checkbox" NAME="select_all" id="expert_id_select_all" title="<?= GetMessage("SUP_SULL_CBT") ?>" onClick="UpdateSystemExpertHelper.getInstance().handleSelectAllRowsClicked()" checked></td>
				<td class="heading"><B><?= GetMessage("SUP_SULL_NAME") ?></B></td>
				<td class="heading"><B><?= GetMessage("SUP_SULL_TYPE") ?></B></td>
				<td class="heading"><B><?= GetMessage("SUP_SULL_REL_FROM") ?></B></td>
				<td class="heading"><B><?= GetMessage("SUP_SULL_REL_TO") ?></B></td>
				<td class="heading"><B><?= GetMessage("SUP_SULL_NOTE") ?></B></td>
			</tr>
			<?php
			$clientModules = $expertUpdateHelper->getClientModules();
			if ($updatesCount > 0)
			{
				foreach ($expertUpdateHelper->getUpdatesList() as $moduleUpdates)
				{
					$moduleId = $expertUpdateHelper->escapeModuleId($moduleUpdates["@"]["ID"]);
					$escapedModuleId = CUtil::JSEscape(htmlspecialcharsbx($moduleId));
					$versionFrom = null;
					if (array_key_exists($moduleId, $clientModules))
					{
						$versionFrom = $clientModules[$moduleId];
					}
					$availableVersions = [];
					if ($versionFrom)
					{
						$availableVersions[] = $versionFrom;
					}

					$strTitleTmp = $moduleUpdates["@"]["NAME"]." (".$moduleId.")\n".$moduleUpdates["@"]["DESCRIPTION"]."\n";
					if (isset($moduleUpdates["#"]["VERSION"]) && is_array($moduleUpdates["#"]["VERSION"]))
					{
						for ($j = 0, $cntj = count($moduleUpdates["#"]["VERSION"]); $j < $cntj; $j++)
						{
							$availableVersions[] = $moduleUpdates["#"]["VERSION"][$j]["@"]["ID"];
						}
					}
					$selectedVersionTo = null;
					if (!empty($availableVersions))
					{
						$versionsIndex = count($availableVersions);
						while ($versionsIndex > 0)
						{
							$versionsIndex--;
							if (is_numeric(mb_substr($availableVersions[$versionsIndex], 0, 1)))
							{
								$selectedVersionTo = $availableVersions[$versionsIndex];
								break;
							}
						}
					}
					$strTitleTmp = htmlspecialcharsbx(preg_replace("/<.+?>/i", "", $strTitleTmp));
					?>
					<tr title="<?= $strTitleTmp ?>">
						<td><a name="expert_module_<?= $escapedModuleId ?>"></a><INPUT TYPE="checkbox" NAME="select_module_<?= $escapedModuleId ?>" value="Y" onClick="UpdateSystemExpertHelper.getInstance().handleModuleCheckboxClicked()" checked id="id_expert_select_module_<?= $escapedModuleId ?>"></td>
						<td><label for="id_expert_select_module_<?= $escapedModuleId ?>"><?= str_replace("#NAME#", htmlspecialcharsbx($moduleUpdates["@"]["NAME"]), GetMessage("SUP_SULL_MODULE")) . " (" . htmlspecialcharsbx($moduleUpdates["@"]["ID"]) . ")" ?></label></td>
						<td><?= ($versionFrom ? GetMessage("SUP_SULL_REF_O") : GetMessage("SUP_SULL_REF_N")) ?></td>
						<td><?= $versionFrom;?></td>
						<td>
							<select id="id_expert_module_version_to_<?=$escapedModuleId;?>" name="module_version_to_<?=$escapedModuleId;?>" onchange="UpdateSystemExpertHelper.getInstance().handleSelectVersionChanged()">
								<?php foreach ($availableVersions as $version)
								{
									?>
									<option<?=(($selectedVersionTo === $version) ? " selected" : "")?>><?=htmlspecialcharsbx($version);?></option>
									<?php
								}
								?>
							</select>
						</td>
						<td><?php if(isset($moduleUpdates["#"]["VERSION"])):?><a href="javascript:ShowDescription('<?= $escapedModuleId ?>')"><?= GetMessage("SUP_SULL_NOTE_D") ?></a><?php endif ?></td>
					</tr>
					<?
				}
			}?>
		</table>
	</td>
</tr>
<script>
try
{
	UpdateIdentifier = function(module, version)
	{
		this.module = module;
		this.version = version;
	};
	UpdateIdentifier.createFromString = function(identifier)
	{
		var parts = identifier.split('|');

		return new UpdateIdentifier(parts[0], parts[1]);
	};
	UpdateIdentifier.prototype.getModule = function()
	{
		return this.module;
	};
	UpdateIdentifier.prototype.getVersion = function()
	{
		return this.version;
	};
	UpdateIdentifier.prototype.toString = function()
	{
		return this.module + '|' + this.version;
	};
	UpdateIdentifier.prototype.isModuleTheSame = function(identifier)
	{
		return this.getModule() === identifier.getModule();
	};
	UpdateIdentifier.prototype.isGreaterThan = function(identifier)
	{
		if (!this.isModuleTheSame(identifier))
		{
			return false;
		}

		return UpdateIdentifier.compareVersions(this.getVersion(), identifier.getVersion()) > 0;
	};
	UpdateIdentifier.prototype.isGreaterOrEqualThan = function(identifier)
	{
		if (!this.isModuleTheSame(identifier))
		{
			return false;
		}

		return UpdateIdentifier.compareVersions(this.getVersion(), identifier.getVersion()) >= 0;
	};
	UpdateIdentifier.prototype.isLowerThan = function(identifier)
	{
		if (!this.isModuleTheSame(identifier))
		{
			return false;
		}

		return UpdateIdentifier.compareVersions(this.getVersion(), identifier.getVersion()) < 0;
	};
	UpdateIdentifier.prototype.isLowerOrEqualThan = function(identifier)
	{
		if (!this.isModuleTheSame(identifier))
		{
			return false;
		}

		return UpdateIdentifier.compareVersions(this.getVersion(), identifier.getVersion()) <= 0;
	};
	UpdateIdentifier.compareVersions = function(first, second)
	{
		first = UpdateIdentifier.normalizeVersion(first);
		second = UpdateIdentifier.normalizeVersion(second);

		var firstParts = first.split('.').map(Number);
		var secondParts = second.split('.').map(Number);
		if (
			firstParts[0] === secondParts[0]
			&& firstParts[1] === secondParts[1]
			&& firstParts[2] === secondParts[2]
		)
		{
			return 0;
		}
		if (
			firstParts[0] > secondParts[0]
			||
			(
				firstParts[0] === secondParts[0]
				&& firstParts[1] > secondParts[1]
			)
			||
			(
				firstParts[0] === secondParts[0]
				&& firstParts[1] === secondParts[1]
				&& firstParts[2] > secondParts[2]
			)
		)
		{
			return 1;
		}

		return -1;
	};
	UpdateIdentifier.normalizeVersion = function(version) {
		var matches = version.match(/(\d+)\.(\d+)\.(\d+)/);
		if (matches !== null && matches.length && matches.length > 0)
		{
			return matches[0];
		}

		return version;
	};
	UpdateSystemExpertHelper = function(dependencies, updateCounts, clientModules)
	{
		this.dependencies = dependencies;
		this.updateCounts = updateCounts;
		this.clientModules = clientModules;
		this.installedUpdates = [];
		this.updatedModules = {};
	};
	UpdateSystemExpertHelper.messages = {
		CONFLICT_POPUP_TITLE: "<?=GetMessageJS('SUP_CONFLICT_POPUP_TITLE');?>",
		CONFLICT_MODULE_MESSAGE: "<?=GetMessageJS('SUP_CONFLICT_MODULE_MESSAGE');?>",
		SUP_CONFLICT_NOTHING_SELECTED: "<?=GetMessageJS('SUP_CONFLICT_NOTHING_SELECTED');?>",
		SUP_IMPORT_SUCCESS: "<?=GetMessageJS('SUP_IMPORT_SUCCESS');?>",
		SUP_IMPORT_ERROR: "<?=GetMessageJS('SUP_IMPORT_ERROR');?>",
	};
	UpdateSystemExpertHelper.getMessage = function(code, replacements)
	{
		var message = UpdateSystemExpertHelper.messages[code];
		if (!message)
		{
			return '';
		}
		if (!replacements || typeof(replacements) !== 'object')
		{
			return message;
		}
		Object.keys(replacements).forEach(function(replacement) {
			var globalRegexp = new RegExp(replacement, 'gi');
			message = message.replace(
				globalRegexp,
				function() {
					return replacements[replacement] ? String(replacements[replacement]) : '';
				}
			);
		});

		return message;
	};
	UpdateSystemExpertHelper.prototype.getSelectedUpdates = function()
	{
		var moduleNames = Object.keys(this.updateCounts);
		var selectedUpdates = [];
		var selectNode;
		var selectedIndex;
		var input;

		for (var i = 0, cnt = moduleNames.length; i < cnt; i++)
		{
			var moduleName = moduleNames[i];
			selectNode = document.getElementById('id_expert_module_version_to_' + moduleName);
			if (!selectNode || selectNode.tagName.toUpperCase() !== 'SELECT')
			{
				continue;
			}
			selectedIndex = selectNode.selectedIndex;
			if (selectedIndex === undefined || !selectNode.options)
			{
				continue;
			}
			input = document.getElementById('id_expert_select_module_' + moduleName);
			if (input && input.checked)
			{
				selectedUpdates.push(new UpdateIdentifier(moduleName, selectNode.options[selectedIndex].innerText));
			}
		}

		return selectedUpdates;
	};
	UpdateSystemExpertHelper.prototype.getUninstalledDependencies = function(selectedUpdates)
	{
		var uninstalledDependencies = {};

		Object.keys(this.dependencies).forEach(function(updateStringIdentifier) {
			var uninstalledModuleDependencies = [];
			var moduleDependencies = this.dependencies[updateStringIdentifier];
			moduleDependencies.forEach(function(dependencyStringIdentifier) {
				var dependencyIdentifier = UpdateIdentifier.createFromString(dependencyStringIdentifier);
				if (!this.hasModule(dependencyIdentifier.getModule()))
				{
					// skip modules that are not present on this server
					return;
				}
				if (this.isUpdateInstalled(dependencyIdentifier))
				{
					return;
				}
				if (!this.isUpdateSelected(dependencyIdentifier, selectedUpdates))
				{
					uninstalledModuleDependencies.push(dependencyIdentifier);
				}
			}.bind(this));
			if (uninstalledModuleDependencies.length > 0)
			{
				uninstalledDependencies[updateStringIdentifier] = uninstalledModuleDependencies;
			}
		}.bind(this));

		return uninstalledDependencies;
	};
	UpdateSystemExpertHelper.prototype.isUpdateSelected = function(identifier, selectedUpdates)
	{
		var result = false;

		selectedUpdates.forEach(function(installedIdentifier) {
			if (!result && installedIdentifier.isGreaterOrEqualThan(identifier))
			{
				result = true;
			}
		}.bind(this));

		return result;
	};
	UpdateSystemExpertHelper.prototype.isUpdateInstalled = function(identifier) {
		var moduleName = identifier.getModule();
		if (!this.clientModules[moduleName])
		{
			// module is not installed
			return false;
		}
		var installedIdentifier = new UpdateIdentifier(moduleName, this.clientModules[moduleName]);

		return installedIdentifier.isGreaterOrEqualThan(identifier);
	};
	UpdateSystemExpertHelper.prototype.hasModule = function(module)
	{
		return this.updateCounts.hasOwnProperty(module);
	};
	UpdateSystemExpertHelper.prototype.collapseMeaninglessDependencies = function(uninstalledDependencies, selectedUpdates)
	{
		var result = {};

		Object.keys(uninstalledDependencies).forEach(function(installUpdateStringIdentifier) {
			var installUpdateIdentifier = UpdateIdentifier.createFromString(installUpdateStringIdentifier);
			if (!this.isUpdateSelected(installUpdateIdentifier, selectedUpdates))
			{
				return;
			}
			var module = installUpdateIdentifier.getModule();
			if (!result[module])
			{
				result[module] = {
					update: null,
					requires: {},
				};
			}
			if (
				!result[module].update
				|| installUpdateIdentifier.isLowerThan(result[module].update)
			)
			{
				result[module].update = installUpdateIdentifier;
			}
			uninstalledDependencies[installUpdateStringIdentifier].forEach(function(dependencyIdentifier) {
				var requiredModule = dependencyIdentifier.getModule();
				if (
					!result[module].requires[requiredModule]
					|| dependencyIdentifier.isLowerThan(result[module].requires[requiredModule])
				)
				{
					result[module].requires[requiredModule] = dependencyIdentifier;
				}
			}.bind(this));
		}.bind(this));

		return result;
	};
	UpdateSystemExpertHelper.prototype.prepareDependencies = function(selectedUpdates)
	{
		return this.collapseMeaninglessDependencies(this.getUninstalledDependencies(selectedUpdates), selectedUpdates);
	};
	UpdateSystemExpertHelper.prototype.getConflictMessage = function()
	{
		var selectedUpdates = this.getSelectedUpdates();
		if (selectedUpdates.length === 0)
		{
			return UpdateSystemExpertHelper.getMessage('SUP_CONFLICT_NOTHING_SELECTED');
		}
		var dependencies = this.prepareDependencies(selectedUpdates);
		var modules = Object.keys(dependencies);
		if (modules.length <= 0)
		{
			return null;
		}

		var message = '';
		modules.forEach(function(module) {
			var requiredUpdates = Object.values(dependencies[module].requires);
			var requiredUpdatesMessage = '';
			requiredUpdates.forEach(function(requiredUpdate) {
				if (requiredUpdatesMessage.length > 0)
				{
					requiredUpdatesMessage += ', ';
				}
				requiredUpdatesMessage += '<a href="#expert_module_' + requiredUpdate.getModule() + '">' + requiredUpdate.getModule() + " " + requiredUpdate.getVersion() + '</a>';
			}.bind(this));
			message += UpdateSystemExpertHelper.getMessage('CONFLICT_MODULE_MESSAGE', {
				'#MODULE#': '<a href="#expert_module_' + module + '">' + module + " " + dependencies[module].update.getVersion() + '</a>',
				'#REQUIRES#': requiredUpdatesMessage
			})
			message += "<br>\n";
		}.bind(this));

		return message;
	};
	UpdateSystemExpertHelper.isObjectsEqual = function(obj1, obj2) {
		var props1 = Object.getOwnPropertyNames(obj1);
		var props2 = Object.getOwnPropertyNames(obj2);
		if (props1.length !== props2.length)
		{
			return false;
		}
		for (var i = 0; i < props1.length; i++)
		{
			var prop = props1[i];
			var bothAreObjects = typeof(obj1[prop]) === "object" && typeof(obj2[prop]) === "object";
			if (
				(!bothAreObjects && (obj1[prop] !== obj2[prop]))
				|| (bothAreObjects && !UpdateSystemExpertHelper.isObjectsEqual(obj1[prop], obj2[prop]))
			)
			{
				return false;
			}
		}

		return true;
	};
	UpdateSystemExpertHelper.runTests = function()
	{
		UpdateSystemExpertHelper.testGetUninstalledDependencies();
		UpdateSystemExpertHelper.testCollapseMeaninglessDependencies();
	}
	UpdateSystemExpertHelper.testGetUninstalledDependencies = function(isDebug)
	{
		var count = {
			success: 0,
			errors: 0,
		};
		var errors = [];
		var samples = {
			empty: {
				selectedUpdates: [],
				dependencies: {},
				updateCounts: {},
				uninstalledDependencies: {},
			},
			dependencyAbsent: {
				selectedUpdates: [
					UpdateIdentifier.createFromString("main|20.0.0")
				],
				dependencies: {
					"main|20.0.0": ["catalog|21.0.0"]
				},
				updateCounts: {
					main: 10
				},
				uninstalledDependencies: {},
			},
			lowerVersionIncludedInUninstalledDependencies: {
				selectedUpdates: [
					UpdateIdentifier.createFromString("main|19.999.999")
				],
				dependencies: {
					"main|20.0.0": ["ui|21.0.0"]
				},
				updateCounts: {
					main: 1,
					ui: 1
				},
				uninstalledDependencies: {
					"main|20.0.0": [UpdateIdentifier.createFromString("ui|21.0.0")]
				},
			},
			complex: {
				selectedUpdates: [
					UpdateIdentifier.createFromString("ui|20.0.0"),
					UpdateIdentifier.createFromString("iblock|20.0.0"),
					UpdateIdentifier.createFromString("main|21.0.0")
				],
				dependencies: {
					"ui|19.0.0": ["main|20.0.0"],
					"main|21.0.0": ["iblock|21.0.0"],
					"iblock|20.0.0": ["ui|20.0.0"]
				},
				updateCounts: {
					main: 1,
					ui: 1,
					iblock: 1
				},
				uninstalledDependencies: {
					"main|21.0.0": [UpdateIdentifier.createFromString("iblock|21.0.0")]
				},
			},
		};

		if (isDebug === true)
		{
			debugger;
		}
		Object.keys(samples).forEach(function(caseName) {
			var updateHelper = new UpdateSystemExpertHelper(samples[caseName].dependencies, samples[caseName].updateCounts)

			var uninstalledDependencies = updateHelper.getUninstalledDependencies(samples[caseName].selectedUpdates);

			if (!UpdateSystemExpertHelper.isObjectsEqual(uninstalledDependencies, samples[caseName].uninstalledDependencies))
			{
				count.errors++;
				errors.push({
					message: 'Error testGetUninstalledDependencies with case ' + caseName,
					actual: uninstalledDependencies,
					expected: samples[caseName].uninstalledDependencies
				});
			}
			else
			{
				count.success++;
			}
		});

		console.log(count);
		console.log(errors);
	};
	UpdateSystemExpertHelper.testCollapseMeaninglessDependencies = function(isDebug)
	{
		var count = {
			success: 0,
			errors: 0,
		};
		var errors = [];
		var samples = {
			empty: {
				selectedUpdates: [],
				uninstalledDependencies: {},
				collapsedDependencies: {}
			},
			removeAbsentUpdates: {
				selectedUpdates: [
					UpdateIdentifier.createFromString("main|20.0.0")
				],
				uninstalledDependencies: {
					"main|21.0.0": [UpdateIdentifier.createFromString("iblock|21.0.0")]
				},
				collapsedDependencies: {}
			},
			collapseToMinimumInstalledUpdates: {
				selectedUpdates: [
					UpdateIdentifier.createFromString("main|21.0.0")
				],
				uninstalledDependencies: {
					"main|21.0.0": [UpdateIdentifier.createFromString("iblock|21.0.0")],
					"main|20.0.0": [UpdateIdentifier.createFromString("ui|21.0.0")],
					"main|20.99.99": [UpdateIdentifier.createFromString("crm|21.0.0")]
				},
				collapsedDependencies: {
					main: {
						update: UpdateIdentifier.createFromString("main|20.0.0"),
						requires: {
							iblock: UpdateIdentifier.createFromString("iblock|21.0.0"),
							ui: UpdateIdentifier.createFromString("ui|21.0.0"),
							crm: UpdateIdentifier.createFromString("crm|21.0.0")
						}
					}
				}
			},
			collapseToMinimumRequiredUpdates: {
				selectedUpdates: [
					UpdateIdentifier.createFromString("main|21.0.0")
				],
				uninstalledDependencies: {
					"main|21.0.0": [
						UpdateIdentifier.createFromString("iblock|21.0.0"),
						UpdateIdentifier.createFromString("iblock|20.0.0"),
						UpdateIdentifier.createFromString("iblock|19.0.0")
					],
				},
				collapsedDependencies: {
					main: {
						update: UpdateIdentifier.createFromString("main|21.0.0"),
						requires: {
							iblock: UpdateIdentifier.createFromString("iblock|19.0.0")
						}
					}
				}
			},
			complex: {
				selectedUpdates: [
					UpdateIdentifier.createFromString("main|21.0.0"),
				],
				uninstalledDependencies: {
					"main|21.0.0": [
						UpdateIdentifier.createFromString("ui|21.0.0"),
						UpdateIdentifier.createFromString("iblock|20.0.0"),
						UpdateIdentifier.createFromString("iblock|19.0.0")
					],
					"main|20.0.0": [
						UpdateIdentifier.createFromString("iblock|21.0.0"),
						UpdateIdentifier.createFromString("ui|20.0.0"),
						UpdateIdentifier.createFromString("ui|19.0.0")
					]
				},
				collapsedDependencies: {
					main: {
						update: UpdateIdentifier.createFromString("main|20.0.0"),
						requires: {
							iblock: UpdateIdentifier.createFromString("iblock|19.0.0"),
							ui: UpdateIdentifier.createFromString("ui|19.0.0")
						}
					}
				}
			}
		}

		if (isDebug === true)
		{
			debugger;
		}
		Object.keys(samples).forEach(function(caseName) {
			var updateHelper = new UpdateSystemExpertHelper({}, {})

			var collapsedDependencies = updateHelper.collapseMeaninglessDependencies(
				samples[caseName].uninstalledDependencies,
				samples[caseName].selectedUpdates
			);

			if (!UpdateSystemExpertHelper.isObjectsEqual(collapsedDependencies, samples[caseName].collapsedDependencies))
			{
				count.errors++;
				errors.push({
					message: 'Error testCollapseMeaninglessDependencies with case ' + caseName,
					actual: collapsedDependencies,
					expected: samples[caseName].collapsedDependencies
				});
			}
			else
			{
				count.success++;
			}
		});

		console.log(count);
		console.log(errors);
	};
	UpdateSystemExpertHelper.getInstance = function()
	{
		if (!UpdateSystemExpertHelper.instance)
		{
			UpdateSystemExpertHelper.instance = new UpdateSystemExpertHelper(
				{<?=$expertUpdateHelper->getJavascriptObjectWithDependencies();?>},
				{<?=$expertUpdateHelper->getJavascriptObjectWithUpdates();?>},
				<?=json_encode($expertUpdateHelper->getClientModules());?>
			);
		}

		return UpdateSystemExpertHelper.instance;
	};
	UpdateSystemExpertHelper.prototype.processConflicts = function()
	{
		var conflictMessage = this.getConflictMessage();
		if (!conflictMessage)
		{
			this.enableInstallButton();
			this.hideConflictMessage();
			return;
		}

		this.disableInstallButton();
		this.showConflictMessage(conflictMessage);
	};
	UpdateSystemExpertHelper.prototype.showConflictMessage = function(conflictMessage)
	{
		document.getElementById('expert_install_conflicts').classList.remove('conflicts_message_hidden');
		document.getElementById('expert_install_conflicts_message').innerHTML = conflictMessage;
	};
	UpdateSystemExpertHelper.prototype.hideConflictMessage = function()
	{
		document.getElementById('expert_install_conflicts').classList.add('conflicts_message_hidden');
		document.getElementById('expert_install_conflicts_message').innerHTML = '';
	};
	UpdateSystemExpertHelper.prototype.disableInstallButton = function()
	{
		this.disableElement(document.getElementById('expert_install_updates_sel_button'));
	};
	UpdateSystemExpertHelper.prototype.enableInstallButton = function()
	{
		this.enableElement(document.getElementById('expert_install_updates_sel_button'));
	};
	UpdateSystemExpertHelper.prototype.handleSelectVersionChanged = function()
	{
		this.processConflicts();
	};
	UpdateSystemExpertHelper.prototype.handleModuleCheckboxClicked = function()
	{
		this.processConflicts();
	};
	UpdateSystemExpertHelper.prototype.handleInstallUpdatesButtonClicked = function()
	{
		var conflictMessage = this.getConflictMessage();
		if (conflictMessage)
		{
			this.showConflictMessage(conflictMessage);
			this.disableInstallButton();
			return;
		}

		var selectedModules = this.getSelectedModules();
		if (Object.keys(selectedModules).length > 0)
		{
			this.installUpdates(selectedModules);
		}
	};

	UpdateSystemExpertHelper.prototype.getSelectedModules = function()
	{
		var selectedModules = {};
		var selectedUpdates = this.getSelectedUpdates();

		selectedUpdates.forEach(function(updateTo) {
			var module = updateTo.getModule();
			selectedModules[module] = updateTo.getVersion();
		}.bind(this));

		return selectedModules;
	}

	UpdateSystemExpertHelper.prototype.handleExportButtonClicked = function()
	{
		var modules = this.getSelectedModules();
		if (Object.keys(modules).length === 0)
		{
			return;
		}

		const file = new File(
			[ JSON.stringify(modules) ],
			'updates.json',
			{ type: 'application/json' },
		);

		const link = document.createElement('a');
		link.href = URL.createObjectURL(file);
		link.download = 'updates.json';
		link.click();

		setTimeout(function () {
			URL.revokeObjectURL(link.href);
		}, 60 * 1000);
	};

	UpdateSystemExpertHelper.prototype.handleImportButtonClicked = function()
	{
		const input = document.createElement('input');
		input.setAttribute('type', 'file');
		input.setAttribute('accept', '.json');

		input.onchange = function () {
			input.files[0].text().then(function(text) {
				var modulesUpdates;
				try
				{
					modulesUpdates = JSON.parse(text);
				}
				catch (error)
				{
				}

				if (typeof modulesUpdates !== "object")
				{
					alert(UpdateSystemExpertHelper.getMessage('SUP_IMPORT_ERROR'));
					return;
				}

				var checkbox = document.getElementById('expert_id_select_all');
				checkbox.checked = false;
				this.handleSelectAllRowsClicked(false);

				Object.keys(modulesUpdates).forEach(function(module) {
					var moduleCheckbox = document.getElementById('id_expert_select_module_' + module);
					if (moduleCheckbox)
					{
						moduleCheckbox.checked = true;
					}

					var selectNode = document.getElementById('id_expert_module_version_to_' + module);
					if (selectNode && selectNode.tagName.toUpperCase() === 'SELECT')
					{
						for (var i = 0; i < selectNode.length; i++)
						{
							selectNode[i].selected = (selectNode[i].value == modulesUpdates[module]);
						}
					}
				});

				this.processConflicts();

				// reset file input
				input.value = '';

				setTimeout(function () {
					alert(UpdateSystemExpertHelper.getMessage('SUP_IMPORT_SUCCESS'));
				}, 100);

			}.bind(this));

		}.bind(this);

		input.click();
	}

	UpdateSystemExpertHelper.prototype.installUpdates = function(selectedModules)
	{
		SetProgressHint("<?= GetMessageJS("SUP_INITIAL") ?>");
		globalQuantity = 0;
		Object.keys(selectedModules).forEach(function(module) {
			globalQuantity += Number(this.updateCounts[module]);
		}.bind(this));
		cycleModules = true;
		cycleLangs = false;

		tabControl.SelectTab('tab1');

		this.selectedModulesToInstall = selectedModules;
		this.updatedModules = [];
		__InstallUpdates();
		SetProgressD();
	};
	UpdateSystemExpertHelper.prototype.isExpertModeEnabled = function()
	{
		return this.selectedModulesToInstall && Object.keys(this.selectedModulesToInstall).length > 0;
	};
	UpdateSystemExpertHelper.prototype.getInstallationData = function()
	{
		return 'expertModules=' + encodeURIComponent(JSON.stringify(this.selectedModulesToInstall));
	};
	UpdateSystemExpertHelper.prototype.handleInstallationCompleted = function()
	{
		this.selectedModulesToInstall = [];
		this.updatedModules = [];
	};
	UpdateSystemExpertHelper.prototype.handleSelectAllRowsClicked = function(processConflicts = true)
	{
		var checkbox = document.getElementById('expert_id_select_all');
		if (!checkbox)
		{
			return;
		}
		var isChecked = checkbox.checked;
		var modules = Object.keys(this.updateCounts);
		modules.forEach(function(module) {
			var moduleCheckbox = document.getElementById('id_expert_select_module_' + module);
			if (moduleCheckbox)
			{
				moduleCheckbox.checked = isChecked;
			}
		});

		if (processConflicts)
		{
			this.processConflicts();
		}
	};
	UpdateSystemExpertHelper.prototype.disableUpdatesTable = function()
	{
		this.disableInstallButton();
		var moduleNames = Object.keys(this.updateCounts);
		moduleNames.forEach(function(moduleName) {
			this.disableElement(document.getElementById('id_expert_select_module_' + moduleName));
		}.bind(this));
		this.disableElement(document.getElementById('expert_id_select_all'));
	};
	UpdateSystemExpertHelper.prototype.disableElement = function(element)
	{
		if (!element || !element.style)
		{
			return;
		}
		element.disabled = true;
		element.style.pointerEvents = "none";
	};
	UpdateSystemExpertHelper.prototype.enableElement = function(element)
	{
		if (!element || !element.style)
		{
			return;
		}
		element.disabled = false;
		element.style.pointerEvents = "";
	};

	BX.ready(function() {
		UpdateSystemExpertHelper.getInstance().processConflicts();
	});
}
catch (e)
{
	console.error('Expert mode is unavailable', e);
}
</script>

Youez - 2016 - github.com/yon3zu
LinuXploit