diff --git a/app/autoload.php b/app/autoload.php
new file mode 100644
index 0000000..2256f74
--- /dev/null
+++ b/app/autoload.php
@@ -0,0 +1,11 @@
+validateWritablePath($cachePath)) {
- throw new Exception('Cache dir is not writable.');
+ throw new \Exception('Cache dir is not writable.');
}
}
}
diff --git a/app/code/Deploy/Instance.php b/app/code/Deploy/Instance.php
index 1a840ee..67c632e 100644
--- a/app/code/Deploy/Instance.php
+++ b/app/code/Deploy/Instance.php
@@ -1,6 +1,13 @@
$instancePath) {
$this->instanceList[$groupName][] = is_int($instancePath)
? $instancePath
- : new Deploy_Instance($instanceName, $instancePath);
+ : new Instance($instanceName, $instancePath);
}
}
diff --git a/app/code/Design.php b/app/code/Design.php
index 7342523..af355cd 100644
--- a/app/code/Design.php
+++ b/app/code/Design.php
@@ -1,6 +1,13 @@
loadCache(self::STATIC_HASH_CACHE_ID);
if (!$content) {
$content = $this->generateStaticHash();
diff --git a/app/code/File/Filesystem.php b/app/code/File/Filesystem.php
index 495cbbe..48ba244 100644
--- a/app/code/File/Filesystem.php
+++ b/app/code/File/Filesystem.php
@@ -1,4 +1,11 @@
getHashedFileName($name) . '.patch';
$patchPath = $this->_uploadPath . $newFileName[$fileId];
if (move_uploaded_file($_FILES[$fileElementName]['tmp_name'][$fileId], $patchPath)) {
- require_once 'app/code/Patch/Converter.php';
- $converter = new Patch_Converter();
+ $converter = new Converter();
$converter->preparePatch($patchPath);
} else {
$error[$fileId][] = 'Unable to move uploaded file from tmp folder.';
diff --git a/app/code/Patch/AbstractChecker.php b/app/code/Patch/AbstractChecker.php
new file mode 100644
index 0000000..8827643
--- /dev/null
+++ b/app/code/Patch/AbstractChecker.php
@@ -0,0 +1,73 @@
+instanceManager = $instanceManager;
+ }
+
+ /**
+ * Return patch status for each configured version.
+ *
+ * @param string $patch
+ * @return array
+ */
+ public function check(string $patch)
+ {
+ $result = [];
+ foreach ($this->instanceManager->getInstanceList() as $groupName => $groupInstanceList) {
+ foreach ($groupInstanceList as $instance) {
+ if (is_int($instance)) {
+ for ($i = 0; $i < $instance; $i++) {
+ $result[$groupName][] = ['instance_name' => 'n/a', 'result' => 'n/a'];
+ }
+ } elseif ($instance->getInstanceType() == Instance::INSTANCE_TYPE_INVALID) {
+ $result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'result' => 'n/a'];
+ } else {
+ $result[$groupName][] = [
+ 'instance_name' => $instance->getInstanceName(),
+ 'result' => $this->getResult($instance, $patch)
+ ];
+ }
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Get status of the patch
+ *
+ * @param Instance $instance
+ * @param string $patch
+ * @return array|string
+ */
+ abstract public function getResult(Instance $instance, string $patch);
+}
diff --git a/app/code/Patch/Check/Strategy/AbstractStrategy.php b/app/code/Patch/Check/Strategy/AbstractStrategy.php
index 010017d..d65ffe6 100644
--- a/app/code/Patch/Check/Strategy/AbstractStrategy.php
+++ b/app/code/Patch/Check/Strategy/AbstractStrategy.php
@@ -1,4 +1,13 @@
executeCommand($this->getCommand($patchPath, $instancePath));
if (!$result) {
- return Patch_Checker::PATCH_APPLY_RESULT_SUCCESSFUL;
+ return Checker::PATCH_APPLY_RESULT_SUCCESSFUL;
}
$result = $this->executeCommand($this->getCommand($patchPath, $instancePath, true));
if (!$result) {
- return Patch_Checker::PATCH_APPLY_RESULT_MERGED;
+ return Checker::PATCH_APPLY_RESULT_MERGED;
}
+
+ return Checker::PATCH_APPLY_RESULT_FAILED;
}
}
diff --git a/app/code/Patch/Check/Strategy/GitApplyStrategy.php b/app/code/Patch/Check/Strategy/GitApplyStrategy.php
index 7bcfeef..9eafb5b 100644
--- a/app/code/Patch/Check/Strategy/GitApplyStrategy.php
+++ b/app/code/Patch/Check/Strategy/GitApplyStrategy.php
@@ -1,4 +1,11 @@
originalPatchPath = $patchPath;
- $this->instanceManager = new Deploy_InstanceManager();
- $this->strategyManager = new StrategyManager();
- $this->patchConverter = new Patch_Converter();
- }
-
- private function getPatchForInstanceType($instanceType)
- {
- if (!isset($this->patchPerInstanceType[$instanceType])) {
- $patchPath = false;
- if ($instanceType == Deploy_Instance::INSTANCE_TYPE_GIT) {
- $patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.git.patch';
- $isConverted = $this->patchConverter->convertFromComposerToGitFormat($this->originalPatchPath, $patchPath);
- if (!$isConverted) {
- $patchPath = false;
- }
- } elseif ($instanceType == Deploy_Instance::INSTANCE_TYPE_COMPOSER) {
- $patchPath = BP . UPLOAD_PATH . pathinfo($this->originalPatchPath, PATHINFO_FILENAME) . '.composer.patch';
- $isConverted = $this->patchConverter->convertFromGitToComposerFormat($this->originalPatchPath, $patchPath);
- if (!$isConverted) {
- $patchPath = false;
- }
- }
-
- $this->patchPerInstanceType[$instanceType] = $patchPath;
- }
-
- return $this->patchPerInstanceType[$instanceType];
+ /**
+ * @param InstanceManager $instanceManager
+ * @param StrategyManager $strategyManager
+ * @param InstancePatchConverter $patchConverter
+ */
+ public function __construct(
+ InstanceManager $instanceManager,
+ StrategyManager $strategyManager,
+ InstancePatchConverter $patchConverter
+ ) {
+ parent::__construct($instanceManager);
+ $this->patchConverter = $patchConverter;
+ $this->strategyManager = $strategyManager;
}
- public function checkPatchForAllReleases()
+ /**
+ * @inheritDoc
+ */
+ public function getResult(Instance $instance, string $patch)
{
- $result = [];
- foreach ($this->instanceManager->getInstanceList() as $groupName => $groupInstanceList) {
- foreach ($groupInstanceList as $instance) {
- if (is_int($instance)) {
- for ($i = 0; $i < $instance; $i++) {
- $result[$groupName][] = ['instance_name' => 'n/a', 'check_strategy' => 'n/a'];
- }
- continue;
- }
- if ($instance->getInstanceType() == Deploy_Instance::INSTANCE_TYPE_INVALID) {
- $result[$groupName][] = ['instance_name' => $instance->getInstanceName(), 'check_strategy' => 'n/a'];
- continue;
- }
-
- $patchForInstancePath = $this->getPatchForInstanceType($instance->getInstanceType());
- $checkResult = [];
- foreach ($this->strategyManager->getStrategyList() as $strategy) {
- $patchPath = ($strategy->getIsPreserveOriginalFileFormat())
- ? $this->originalPatchPath
- : $patchForInstancePath;
-
- $strategyResult = $strategy->check($patchPath, $instance->getInstancePath());
-
- if ($strategyResult == self::PATCH_APPLY_RESULT_MERGED) {
- $checkResult = 'merged';
- break;
- }
-
- $checkResult[$strategy->getStrategyName()] = $strategyResult;
- }
-
- $result[$groupName][] = [
- 'instance_name' => $instance->getInstanceName(),
- 'check_strategy' => $checkResult
- ];
+ $patchForInstancePath = $this->patchConverter->convert($patch, $instance->getInstanceType());
+ $checkResult = [];
+ foreach ($this->strategyManager->getStrategyList() as $strategy) {
+ $patchPath = ($strategy->getIsPreserveOriginalFileFormat())
+ ? $patch
+ : $patchForInstancePath;
+ $strategyResult = $strategy->check($patchPath, $instance->getInstancePath());
+
+ if ($strategyResult === self::PATCH_APPLY_RESULT_MERGED) {
+ $checkResult = 'merged';
+ break;
}
+ $checkResult[$strategy->getStrategyName()] = $strategyResult;
}
- return $result;
+ return $checkResult;
}
}
diff --git a/app/code/Patch/Converter.php b/app/code/Patch/Converter.php
index 0bbd1f9..34455e6 100644
--- a/app/code/Patch/Converter.php
+++ b/app/code/Patch/Converter.php
@@ -1,8 +1,15 @@
patchConverter = $patchConverter;
+ }
+
+ /**
+ * Convert patch to the format compatible with given instance type
+ *
+ * @param string $originalPatchPath
+ * @param string $instanceType
+ * @return false|string
+ */
+ public function convert(string $originalPatchPath, string $instanceType)
+ {
+ if (!isset($this->cache[$originalPatchPath]) || !isset($this->cache[$originalPatchPath][$instanceType])) {
+ $patchPath = false;
+ if ($instanceType === Instance::INSTANCE_TYPE_GIT) {
+ $patchPath = BP . UPLOAD_PATH . pathinfo($originalPatchPath, PATHINFO_FILENAME) . '.git.patch';
+ $isConverted = $this->patchConverter->convertFromComposerToGitFormat($originalPatchPath, $patchPath);
+ if (!$isConverted) {
+ $patchPath = false;
+ }
+ } elseif ($instanceType === Instance::INSTANCE_TYPE_COMPOSER) {
+ $patchPath = BP . UPLOAD_PATH . pathinfo($originalPatchPath, PATHINFO_FILENAME) . '.composer.patch';
+ $isConverted = $this->patchConverter->convertFromGitToComposerFormat($originalPatchPath, $patchPath);
+ if (!$isConverted) {
+ $patchPath = false;
+ }
+ }
+
+ $this->cache[$originalPatchPath][$instanceType] = $patchPath;
+ }
+
+ return $this->cache[$originalPatchPath][$instanceType];
+ }
+}
diff --git a/app/code/Patch/MQP/Checker.php b/app/code/Patch/MQP/Checker.php
new file mode 100644
index 0000000..37e8759
--- /dev/null
+++ b/app/code/Patch/MQP/Checker.php
@@ -0,0 +1,63 @@
+versionsManager = $versionsManager;
+ $this->patchRepository = $patchRepository;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function getResult(Instance $instance, string $patch): int
+ {
+ $aggregatedPatch = $this->patchRepository->findOne($patch);
+ $status = self::PATCH_APPLY_RESULT_FAILED;
+ foreach ($aggregatedPatch->getPatches() as $patch) {
+ $packageVersion = $this->versionsManager->getPackageVersion(
+ $instance->getInstanceName(),
+ $patch->getPackageName()
+ );
+ if ($packageVersion && Semver::satisfies($packageVersion, $patch->getPackageConstraint())) {
+ $status = self::PATCH_APPLY_RESULT_SUCCESSFUL;
+ break;
+ }
+ }
+ return $status;
+ }
+}
diff --git a/app/code/Patch/MQP/Data/AggregatedPatch.php b/app/code/Patch/MQP/Data/AggregatedPatch.php
new file mode 100644
index 0000000..1bda868
--- /dev/null
+++ b/app/code/Patch/MQP/Data/AggregatedPatch.php
@@ -0,0 +1,52 @@
+config = $config;
+ }
+
+ /**
+ * Get patch items
+ *
+ * @return Patch[]
+ */
+ public function getPatches(): array
+ {
+ if ($this->patches === null) {
+ $this->patches = [];
+ foreach ($this->config as $packageName => $packageConfiguration) {
+ foreach ($packageConfiguration as $patchTitle => $patchInfo) {
+ foreach ($patchInfo as $packageConstraint => $patchData) {
+ $this->patches[] = new Patch($packageName, $packageConstraint, $patchData['file']);
+ }
+ }
+ }
+ }
+
+ return $this->patches;
+ }
+}
diff --git a/app/code/Patch/MQP/Data/Patch.php b/app/code/Patch/MQP/Data/Patch.php
new file mode 100644
index 0000000..db9a0a0
--- /dev/null
+++ b/app/code/Patch/MQP/Data/Patch.php
@@ -0,0 +1,72 @@
+packageName = $packageName;
+ $this->packageConstraint = $packageConstraint;
+ $this->filename = $filename;
+ }
+
+ /**
+ * Get package name
+ *
+ * @return string
+ */
+ public function getPackageName(): string
+ {
+ return $this->packageName;
+ }
+
+ /**
+ * Get package constraints
+ *
+ * @return string
+ */
+ public function getPackageConstraint(): string
+ {
+ return $this->packageConstraint;
+ }
+
+ /**
+ * Get patch filename
+ *
+ * @return string
+ */
+ public function getFilename(): string
+ {
+ return $this->filename;
+ }
+}
diff --git a/app/code/Patch/MQP/PatchRepository.php b/app/code/Patch/MQP/PatchRepository.php
new file mode 100644
index 0000000..873cb2f
--- /dev/null
+++ b/app/code/Patch/MQP/PatchRepository.php
@@ -0,0 +1,65 @@
+info = $info;
+ }
+
+
+ /**
+ * Find patch by ID
+ *
+ * @param string $id
+ * @return AggregatedPatch
+ * @throws \Exception
+ */
+ public function findOne(string $id): AggregatedPatch
+ {
+ $config = $this->getConfiguration();
+ if (isset($config[$id])) {
+ return new AggregatedPatch($config[$id]);
+ }
+ throw new \Exception("Patch '$id' cannot be found.");
+ }
+
+ /**
+ * Get patches configuration
+ *
+ * @return array
+ * @throws \Exception
+ */
+ private function getConfiguration(): array
+ {
+ $result = [];
+ $configPath = $this->info->getPatchesConfig();
+ if (file_exists($configPath)) {
+ $result = Util::getJsonFile($configPath);
+ }
+
+ return $result;
+ }
+}
diff --git a/app/code/Patch/MQP/Version.php b/app/code/Patch/MQP/Version.php
new file mode 100644
index 0000000..defee78
--- /dev/null
+++ b/app/code/Patch/MQP/Version.php
@@ -0,0 +1,32 @@
+getConfiguration()[$coreVersion][$packageName] ?? null;
+ }
+
+ /**
+ * Get versions configuration
+ *
+ * @return array
+ */
+ private function getConfiguration(): array
+ {
+ if ($this->configuration === null) {
+ $this->configuration = [];
+ $configPath = $this->getConfigurationPath();
+ if (file_exists($configPath)) {
+ $this->configuration = Util::getJsonFile($configPath);
+ }
+ }
+
+ return $this->configuration;
+ }
+
+ /**
+ * Get versions configuration path
+ *
+ * @return string
+ */
+ private function getConfigurationPath(): string
+ {
+ return Util::getAbsolutePath('app/config/magento_package_versions.json');
+ }
+}
diff --git a/app/code/Util.php b/app/code/Util.php
new file mode 100644
index 0000000..cf052aa
--- /dev/null
+++ b/app/code/Util.php
@@ -0,0 +1,47 @@
+'
+ + ''
+ + ''
+ + ''
+ + (result.check_method !== 'mqp'
+ ? ''
+ : ''
+ )
+ + '';
+
+ for (release in groupResults) {
+ release = groupResults[release];
+
+ output += '
' + (release.instance_name === 'n/a' ? ' ' : release.instance_name);
+ } else if (release.result === 'merged') {
+ output += '>' + release.instance_name + ' | '
+ + 'Merged';
+ } else if (release.result === 1) {
+ output += '>' + release.instance_name + ' | '
+ + 'Yes';
+ } else if (release.result === 0) {
+ output += '>' + release.instance_name + ' | '
+ + 'No';
+ } else {
+ falseResultClass = 'td_fail';
+ for (strategyResult in release.result) {
+ if (release.result[strategyResult] === 1) {
+ falseResultClass = 'td_adaptation_required';
+ break;
+ }
+ }
+
+ output += '>' + release.instance_name + ' | ';
+ if (release.result['patch'] === 1) {
+ output += 'Yes';
+ } else {
+ output += ' | No';
+ }
+ if (release.result['git_apply'] === 1) {
+ output += ' | Yes';
+ } else {
+ output += ' | No';
+ }
+ }
+ output += ' |
';
+ }
+ output += '';
- $('#legend_header_div').click(function () {
- $('#legend_body_div').toggle();
- $('#legend_fold_icon').toggleClass('rotate180');
- })
+ $('#results_div').append(output);
+ }
+ }
})
diff --git a/design/js/uploader.js b/design/js/uploader.js
index 2e82c7b..4785adb 100755
--- a/design/js/uploader.js
+++ b/design/js/uploader.js
@@ -28,63 +28,7 @@ $().ready(function() {
loaded : function(result) {
$('#PRO' + result.fileno).remove();
$('#FILE' + result.fileno).html('Uploaded: ' + result.filename + ' (' + result.size + ')');
-
- for (var groupName in result.check_results) {
- var groupResults = result.check_results[groupName];
-
- var output = ''
- + ''
- + ''
- + ''
- + '';
-
- for (var release in groupResults) {
- var release = groupResults[release];
-
- output += '' + columnContent;
- } else if (release.check_strategy == 'merged') {
- output += '>' + release.instance_name + ' | '
- + 'Merged';
- } else {
- var falseResultClass = 'td_fail';
- for (var strategyResult in release.check_strategy) {
- if (release.check_strategy[strategyResult] == 1) {
- falseResultClass = 'td_adaptation_required';
- break;
- }
- }
-
- output += '>' + release.instance_name + ' | ';
- if (release.check_strategy['patch'] == 1) {
- output += 'Ok';
- } else {
- output += ' | No';
- }
- if (release.check_strategy['git_apply'] == 1) {
- output += ' | Ok';
- } else {
- output += ' | No';
- }
- }
- output += ' |
';
- }
- output += '
';
-
- $('#results_div').append(output);
- }
+ $('#upload').trigger('uploaded', [result]);
},
progress : function(result) {
diff --git a/design/style/style.css b/design/style/style.css
index 6088c50..230276b 100755
--- a/design/style/style.css
+++ b/design/style/style.css
@@ -9,6 +9,39 @@ div {
float: left;
}
+div#mqp_form_container, div#separator {
+ clear: both;
+ margin-top: 10px;
+}
+
+div#mqp_form_container {
+ width: 760px;
+ border: 1px solid #ddd;
+ padding: 10px;
+}
+
+div#separator {
+ width: 760px;
+ text-align: center;
+}
+
+form#mqp_form{
+ margin-top: 10px;
+}
+
+span#mqp_error_patch_id {
+ display: block;
+ margin: 5px 0;
+ font-size: 12px;
+ color: red;
+}
+
+span#mqp_version {
+ display: block;
+ margin: 5px 0;
+ font-size: 10px;
+}
+
div#results_div {
clear: both;
padding: 32px;
@@ -45,6 +78,7 @@ table.result_table {
display: block;
float: left;
margin-right: 40px;
+ margin-top: 20px;
border-collapse: collapse;
}
td.td_fail {
diff --git a/design/templates/index.phtml b/design/templates/index.phtml
index 1c2969f..2440e76 100755
--- a/design/templates/index.phtml
+++ b/design/templates/index.phtml
@@ -21,42 +21,17 @@
-
-
- $group): ?>
-
-
-
- |
-
-
-
-
-
-
-
-
- |
-
-
-
- |
-
-
- |
-
-
-
- |
-
-
-
-
-
-
-
+
-OR-
+
+ Enter MQP Patch ID
+
-
+
@@ -69,7 +44,7 @@
- Ok |
+ Yes |
Patch is applicable. |
@@ -102,7 +77,7 @@
2.1.0 |
- Ok |
+ Yes |
No |
Validation was made for the specific release and the results are provided. |
diff --git a/index.php b/index.php
index e991d0e..6942bc6 100755
--- a/index.php
+++ b/index.php
@@ -6,16 +6,18 @@
try {
if ($action == 'upload' && !empty($_POST)) {
- require_once 'app/code/File/Uploader.php';
- $fileUploader = new File_Uploader(['upload_path' => BP . UPLOAD_PATH]);
+ $fileUploader = new \Magento\PatchChecker\File\Uploader(['upload_path' => BP . UPLOAD_PATH]);
$result = $fileUploader->upload();
- require_once 'app/code/Patch/Checker.php';
- $patchChecker = new Patch_Checker(BP . UPLOAD_PATH . $result['new_file_name'][0]);
- $checkResults = $patchChecker->checkPatchForAllReleases();
+ $patchChecker = new \Magento\PatchChecker\Patch\Checker(
+ new \Magento\PatchChecker\Deploy\InstanceManager(),
+ new \Magento\PatchChecker\Patch\Check\StrategyManager(),
+ new \Magento\PatchChecker\Patch\InstancePatchConverter(new \Magento\PatchChecker\Patch\Converter())
+ );
+ $checkResults = $patchChecker->check(BP . UPLOAD_PATH . $result['new_file_name'][0]);
$result = $result['result'];
$result['check_results'] = $checkResults;
-
+ $result['check_method'] = 'file';
// checked patches statistic collection
if (isset($result['filename'])) {
$statsPath = BP . STATS_PATH;
@@ -27,6 +29,27 @@
}
}
+ echo json_encode($result);
+ die;
+ } elseif (!empty($_POST['patch_id'])) {
+ $result = [
+ 'check_results' => [],
+ 'check_method' => 'mqp',
+ 'error' => '',
+ ];
+ try {
+ $patchChecker = new \Magento\PatchChecker\Patch\MQP\Checker(
+ new \Magento\PatchChecker\Deploy\InstanceManager(),
+ new \Magento\PatchChecker\Patch\MQP\PatchRepository(new \Magento\QualityPatches\Info()),
+ new \Magento\PatchChecker\Patch\MQP\VersionsManager
+ );
+ $result['check_results'] = $patchChecker->check($_POST['patch_id']);
+ $result['check_method'] = 'mqp';
+ } catch (\Exception $exception) {
+ $mqpVersion = new \Magento\PatchChecker\Patch\MQP\Version();
+ $result['error'] = "Patch ID '{$_POST['patch_id']}' is not found in MQP $mqpVersion";
+ }
+
echo json_encode($result);
die;
}
@@ -34,7 +57,7 @@
// @TODO Implement logging
}
-require_once 'app/code/Design.php';
-$design = new Design();
+$design = new \Magento\PatchChecker\Design();
+$mqpVersion = new \Magento\PatchChecker\Patch\MQP\Version();
require_once 'design/templates/index.phtml';