PageRenderTime 33ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/magento/magento2-base/setup/src/Magento/Setup/Model/MarketplaceManager.php

https://gitlab.com/yousafsyed/easternglamor
PHP | 455 lines | 279 code | 38 blank | 138 comment | 25 complexity | 920a5610e109a6b491c55e28de075e36 MD5 | raw file
  1. <?php
  2. /**
  3. * Copyright © 2016 Magento. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Setup\Model;
  7. use Zend\ServiceManager\ServiceLocatorInterface;
  8. use Magento\Framework\App\Filesystem\DirectoryList;
  9. use Magento\Framework\Filesystem;
  10. use Zend\View\Model\JsonModel;
  11. class MarketplaceManager
  12. {
  13. /**
  14. * @var \Zend\ServiceManager\ServiceLocatorInterface
  15. */
  16. protected $serviceLocator;
  17. /**
  18. * @var \Magento\Framework\Composer\ComposerInformation
  19. */
  20. protected $composerInformation;
  21. /**
  22. * @var \Magento\Framework\HTTP\Client\Curl
  23. */
  24. protected $curlClient;
  25. /**
  26. * @var string
  27. */
  28. protected $urlPrefix = 'https://';
  29. /**
  30. * @var \Magento\Framework\Filesystem
  31. */
  32. private $filesystem;
  33. /**
  34. * @var string
  35. */
  36. private $pathToAuthFile = 'auth.json';
  37. /**#@+
  38. * Composer auth.json keys
  39. */
  40. const KEY_HTTPBASIC = 'http-basic';
  41. const KEY_USERNAME = 'username';
  42. const KEY_PASSWORD = 'password';
  43. /**
  44. * @var \Magento\Framework\Filesystem\Directory\Write
  45. */
  46. protected $directory;
  47. /**
  48. * @var string
  49. */
  50. protected $pathToInstallPackagesCacheFile = 'install_composer_packages.json';
  51. /**
  52. * @var array
  53. */
  54. protected $errorCodes = [401, 403, 404];
  55. /**
  56. * @param \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator
  57. * @param \Magento\Framework\Composer\ComposerInformation $composerInformation
  58. * @param \Magento\Framework\HTTP\Client\Curl $curl
  59. * @param \Magento\Framework\Filesystem $filesystem
  60. */
  61. public function __construct(
  62. \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator,
  63. \Magento\Framework\Composer\ComposerInformation $composerInformation,
  64. \Magento\Framework\HTTP\Client\Curl $curl,
  65. \Magento\Framework\Filesystem $filesystem
  66. ) {
  67. $this->serviceLocator = $serviceLocator;
  68. $this->composerInformation = $composerInformation;
  69. $this->curlClient = $curl;
  70. $this->filesystem = $filesystem;
  71. $this->directory = $filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
  72. }
  73. /**
  74. * @return string
  75. */
  76. public function getCheckCredentialUrl()
  77. {
  78. return $this->urlPrefix . $this->getCredentialBaseUrl() . '/check_credentials';
  79. }
  80. /**
  81. * @return string
  82. */
  83. public function getCredentialBaseUrl()
  84. {
  85. $config = $this->getServiceLocator()->get('config');
  86. return $config['marketplace']['check_credentials_url'];
  87. }
  88. /**
  89. * @return string
  90. */
  91. public function getPackagesJsonUrl()
  92. {
  93. return $this->urlPrefix . $this->getCredentialBaseUrl() . '/packages.json';
  94. }
  95. /**
  96. * @param string $token
  97. * @param string $secretKey
  98. * @return string
  99. */
  100. public function checkCredentialsAction($token, $secretKey)
  101. {
  102. $serviceUrl = $this->getPackagesJsonUrl();
  103. $this->getCurlClient()->setCredentials($token, $secretKey);
  104. try {
  105. $this->getCurlClient()->post($serviceUrl, []);
  106. if ($this->getCurlClient()->getStatus() == 200) {
  107. return \Zend_Json::encode(['success' => true]);
  108. } else {
  109. return \Zend_Json::encode(['success' => false, 'message' => 'Bad credentials']);
  110. }
  111. } catch (\Exception $e) {
  112. return \Zend_Json::encode(['success' => false, 'message' => $e->getMessage()]);
  113. }
  114. }
  115. /**
  116. * Gets packages.json
  117. *
  118. * @return bool|string
  119. */
  120. public function getPackagesJson()
  121. {
  122. $serviceUrl = $this->getPackagesJsonUrl();
  123. $authJsonData = $this->getAuthJsonData();
  124. if (!empty($authJsonData)) {
  125. $this->getCurlClient()->setCredentials($authJsonData['username'], $authJsonData['password']);
  126. try {
  127. $this->getCurlClient()->post($serviceUrl, []);
  128. return $this->getCurlClient()->getBody();
  129. } catch (\Exception $e) {
  130. }
  131. }
  132. return false;
  133. }
  134. /**
  135. * Sync packages for install
  136. *
  137. * @return bool
  138. */
  139. public function syncPackagesForInstall()
  140. {
  141. try {
  142. $packagesJson = $this->getPackagesJson();
  143. if ($packagesJson) {
  144. $packagesJsonData = json_decode($packagesJson, true);
  145. } else {
  146. $packagesJsonData['packages'] = [];
  147. }
  148. $packageNames = array_column($this->getComposerInformation()->getInstalledMagentoPackages(), 'name');
  149. $installPackages = [];
  150. foreach ($packagesJsonData['packages'] as $package) {
  151. $package = $this->unsetDevVersions($package);
  152. if (!empty($package)) {
  153. ksort($package);
  154. $package = array_pop($package);
  155. if ($this->isNewUserPackage($package, $packageNames)) {
  156. $package['vendor'] = explode('/', $package['name'])[0];
  157. $installPackages[$package['name']] = $package;
  158. }
  159. }
  160. }
  161. return $this->savePackagesForInstallToCache($installPackages) ? true : false;
  162. } catch (\Exception $e) {
  163. }
  164. return false;
  165. }
  166. /**
  167. * Check if this new user package
  168. *
  169. * @param array $package
  170. * @param array $packageNames
  171. * @return bool
  172. */
  173. protected function isNewUserPackage($package, $packageNames)
  174. {
  175. if (!in_array($package['name'], $packageNames) &&
  176. in_array($package['type'], $this->getComposerInformation()->getPackagesTypes()) &&
  177. strpos($package['name'], 'magento/product-') === false &&
  178. strpos($package['name'], 'magento/project-') === false
  179. ) {
  180. return true;
  181. }
  182. return false;
  183. }
  184. /**
  185. * Unset dev versions
  186. *
  187. * @param array $package
  188. * @return array
  189. */
  190. protected function unsetDevVersions($package)
  191. {
  192. foreach ($package as $key => $version) {
  193. if (strpos($key, 'dev') !== false) {
  194. unset($package[$key]);
  195. }
  196. }
  197. unset($version);
  198. return $package;
  199. }
  200. /**
  201. * Gets auth.json file
  202. *
  203. * @return array|false
  204. */
  205. public function getAuthJsonData()
  206. {
  207. try {
  208. $authJson = $this->getAuthJson();
  209. $serviceUrl = $this->getCredentialBaseUrl();
  210. $authJsonData = isset($authJson['http-basic'][$serviceUrl]) ? $authJson['http-basic'][$serviceUrl] : false;
  211. } catch (\Exception $e) {
  212. $authJsonData = false;
  213. }
  214. return $authJsonData;
  215. }
  216. /**
  217. * Gets auth.json
  218. *
  219. * @return bool|mixed
  220. * @throws \Exception
  221. */
  222. public function getAuthJson()
  223. {
  224. $directory = $this->getFilesystem()->getDirectoryRead(DirectoryList::COMPOSER_HOME);
  225. if ($directory->isExist($this->pathToAuthFile) && $directory->isReadable($this->pathToAuthFile)) {
  226. try {
  227. $data = $directory->readFile($this->pathToAuthFile);
  228. return json_decode($data, true);
  229. } catch (\Magento\Framework\Exception\FileSystemException $e) {
  230. }
  231. }
  232. return false;
  233. }
  234. /**
  235. * Removes credentials from auth.json
  236. *
  237. * @return bool
  238. * @throws \Exception
  239. */
  240. public function removeCredentials()
  241. {
  242. $serviceUrl = $this->getCredentialBaseUrl();
  243. $directory = $this->getFilesystem()->getDirectoryRead(DirectoryList::COMPOSER_HOME);
  244. if ($directory->isExist($this->pathToAuthFile) && $directory->isReadable($this->pathToAuthFile)) {
  245. try {
  246. $authJsonData = $this->getAuthJson();
  247. if (!empty($authJsonData) && isset($authJsonData['http-basic'][$serviceUrl])) {
  248. unset($authJsonData['http-basic'][$serviceUrl]);
  249. if (empty($authJsonData['http-basic'])) {
  250. return unlink(getenv('COMPOSER_HOME') . DIRECTORY_SEPARATOR . $this->pathToAuthFile);
  251. } else {
  252. $data = json_encode($authJsonData, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
  253. $this->getDirectory()->writeFile(
  254. DirectoryList::COMPOSER_HOME . DIRECTORY_SEPARATOR . $this->pathToAuthFile,
  255. $data
  256. );
  257. return true;
  258. }
  259. }
  260. } catch (\Exception $e) {
  261. }
  262. }
  263. return false;
  264. }
  265. /**
  266. * Saves auth.json file
  267. *
  268. * @param string $username
  269. * @param string $password
  270. * @return bool
  271. * @throws \Exception
  272. */
  273. public function saveAuthJson($username, $password)
  274. {
  275. $authContent = [
  276. self::KEY_HTTPBASIC => [
  277. $this->getCredentialBaseUrl() => [
  278. self::KEY_USERNAME => "$username",
  279. self::KEY_PASSWORD => "$password"
  280. ]
  281. ]
  282. ];
  283. $json = new JsonModel($authContent);
  284. $json->setOption('prettyPrint', true);
  285. $jsonContent = $json->serialize();
  286. return $this->getDirectory()->writeFile(
  287. DirectoryList::COMPOSER_HOME . DIRECTORY_SEPARATOR . $this->pathToAuthFile,
  288. $jsonContent
  289. );
  290. }
  291. /**
  292. * Saves composer packages available for install to cache
  293. *
  294. * @param array $availablePackages
  295. * @return bool|string
  296. */
  297. public function savePackagesForInstallToCache($availablePackages)
  298. {
  299. $syncInfo = [];
  300. $syncInfo['packages'] = $availablePackages;
  301. $data = json_encode($syncInfo, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
  302. try {
  303. $this->getDirectory()->writeFile($this->pathToInstallPackagesCacheFile, $data);
  304. } catch (\Magento\Framework\Exception\FileSystemException $e) {
  305. return false;
  306. }
  307. return $data;
  308. }
  309. /**
  310. * Sync and cache list of available for install versions for packages
  311. *
  312. * @return bool|string
  313. */
  314. public function getPackagesForInstall()
  315. {
  316. $actualInstallackages = [];
  317. $installPackagesInfo = $this->loadPackagesForInstallFromCache();
  318. if (!$installPackagesInfo) {
  319. return false;
  320. }
  321. try {
  322. $installPackages = $installPackagesInfo['packages'];
  323. $availablePackageNames = array_column(
  324. $this->getComposerInformation()->getInstalledMagentoPackages(),
  325. 'name'
  326. );
  327. $metaPackageByPackage = $this->getMetaPackageForPackage($installPackages);
  328. foreach ($installPackages as $package) {
  329. if (!in_array($package['name'], $availablePackageNames) &&
  330. in_array($package['type'], $this->getComposerInformation()->getPackagesTypes()) &&
  331. strpos($package['name'], 'magento/product-') === false &&
  332. strpos($package['name'], 'magento/project-') === false
  333. ) {
  334. $package['metapackage'] =
  335. isset($metaPackageByPackage[$package['name']]) ? $metaPackageByPackage[$package['name']] : '';
  336. $actualInstallackages[$package['name']] = $package;
  337. }
  338. }
  339. $installPackagesInfo['packages'] = $actualInstallackages;
  340. return $installPackagesInfo;
  341. } catch (\Exception $e) {
  342. }
  343. return false;
  344. }
  345. /**
  346. *
  347. * @param array $packages
  348. * @return array
  349. */
  350. protected function getMetaPackageForPackage($packages)
  351. {
  352. $result = [];
  353. foreach ($packages as $package) {
  354. if ($package['type'] == \Magento\Framework\Composer\ComposerInformation::METAPACKAGE_PACKAGE_TYPE) {
  355. if (isset($package['require'])) {
  356. foreach ($package['require'] as $key => $requirePackage) {
  357. $result[$key] = $package['name'];
  358. }
  359. }
  360. }
  361. }
  362. unset($requirePackage);
  363. return $result;
  364. }
  365. /**
  366. * Load composer packages available for install from cache
  367. *
  368. * @return bool|string
  369. */
  370. public function loadPackagesForInstallFromCache()
  371. {
  372. if ($this->getDirectory()->isExist($this->pathToInstallPackagesCacheFile)
  373. && $this->getDirectory()->isReadable($this->pathToInstallPackagesCacheFile)) {
  374. try {
  375. $data = $this->getDirectory()->readFile($this->pathToInstallPackagesCacheFile);
  376. return json_decode($data, true);
  377. } catch (\Magento\Framework\Exception\FileSystemException $e) {
  378. }
  379. }
  380. return false;
  381. }
  382. /**
  383. * @return ServiceLocatorInterface
  384. */
  385. public function getServiceLocator()
  386. {
  387. return $this->serviceLocator;
  388. }
  389. /**
  390. * @return \Zend\ServiceManager\ServiceLocatorInterface
  391. */
  392. public function getComposerInformation()
  393. {
  394. return $this->composerInformation;
  395. }
  396. /**
  397. * @return \Magento\Framework\HTTP\Client\Curl
  398. */
  399. public function getCurlClient()
  400. {
  401. return $this->curlClient;
  402. }
  403. /**
  404. * @return \Magento\Framework\Filesystem
  405. */
  406. public function getFilesystem()
  407. {
  408. return $this->filesystem;
  409. }
  410. /**
  411. * @return Filesystem\Directory\Write|Filesystem\Directory\WriteInterface
  412. */
  413. public function getDirectory()
  414. {
  415. return $this->directory;
  416. }
  417. }