Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
PatchApplier.php
Go to the documentation of this file.
1 <?php
8 
15 
21 {
25  const SCHEMA_PATCH = 'schema';
26 
30  const DATA_PATCH = 'data';
31 
35  private $patchRegistryFactory;
36 
40  private $dataPatchReader;
41 
45  private $schemaPatchReader;
46 
50  private $resourceConnection;
51 
55  private $patchHistory;
56 
60  private $patchFactory;
61 
65  private $schemaSetup;
66 
70  private $moduleDataSetup;
71 
75  private $objectManager;
76 
80  private $patchBackwardCompatability;
81 
85  private $moduleList;
86 
103  public function __construct(
104  PatchReader $dataPatchReader,
105  PatchReader $schemaPatchReader,
106  PatchRegistryFactory $patchRegistryFactory,
107  ResourceConnection $resourceConnection,
108  PatchBackwardCompatability $patchBackwardCompatability,
109  PatchHistory $patchHistory,
110  PatchFactory $patchFactory,
111  ObjectManagerInterface $objectManager,
112  \Magento\Framework\Setup\SchemaSetupInterface $schemaSetup,
113  \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup,
114  ModuleList $moduleList
115  ) {
116  $this->patchRegistryFactory = $patchRegistryFactory;
117  $this->dataPatchReader = $dataPatchReader;
118  $this->schemaPatchReader = $schemaPatchReader;
119  $this->resourceConnection = $resourceConnection;
120  $this->patchHistory = $patchHistory;
121  $this->patchFactory = $patchFactory;
122  $this->schemaSetup = $schemaSetup;
123  $this->moduleDataSetup = $moduleDataSetup;
124  $this->objectManager = $objectManager;
125  $this->patchBackwardCompatability = $patchBackwardCompatability;
126  $this->moduleList = $moduleList;
127  }
128 
135  public function applyDataPatch($moduleName = null)
136  {
137  $registry = $this->prepareRegistry($moduleName, self::DATA_PATCH);
138  foreach ($registry as $dataPatch) {
142  if ($this->patchBackwardCompatability->isSkipableByDataSetupVersion($dataPatch, $moduleName)) {
143  $this->patchHistory->fixPatch($dataPatch);
144  continue;
145  }
146 
147  $dataPatch = $this->objectManager->create(
148  '\\' . $dataPatch,
149  ['moduleDataSetup' => $this->moduleDataSetup]
150  );
151  if (!$dataPatch instanceof DataPatchInterface) {
152  throw new Exception(
153  new Phrase("Patch %1 should implement DataPatchInterface", [get_class($dataPatch)])
154  );
155  }
156  if ($dataPatch instanceof NonTransactionableInterface) {
157  $dataPatch->apply();
158  $this->patchHistory->fixPatch(get_class($dataPatch));
159  } else {
160  try {
161  $this->moduleDataSetup->getConnection()->beginTransaction();
162  $dataPatch->apply();
163  $this->patchHistory->fixPatch(get_class($dataPatch));
164  $this->moduleDataSetup->getConnection()->commit();
165  } catch (\Exception $e) {
166  $this->moduleDataSetup->getConnection()->rollBack();
167  throw new Exception(new Phrase($e->getMessage()));
168  } finally {
169  unset($dataPatch);
170  }
171  }
172  }
173  }
174 
183  private function prepareRegistry($moduleName, $patchType)
184  {
185  $reader = $patchType === self::DATA_PATCH ? $this->dataPatchReader : $this->schemaPatchReader;
186  $registry = $this->patchRegistryFactory->create();
187 
188  //Prepare modules to read
189  if ($moduleName === null) {
190  $patchNames = [];
191  foreach ($this->moduleList->getNames() as $moduleName) {
192  $patchNames += $reader->read($moduleName);
193  }
194  } else {
195  $patchNames = $reader->read($moduleName);
196  }
197 
198  foreach ($patchNames as $patchName) {
199  $registry->registerPatch($patchName);
200  }
201 
202  return $registry;
203  }
204 
213  public function applySchemaPatch($moduleName = null)
214  {
215  $registry = $this->prepareRegistry($moduleName, self::SCHEMA_PATCH);
216  foreach ($registry as $schemaPatch) {
217  try {
221  if ($this->patchBackwardCompatability->isSkipableBySchemaSetupVersion($schemaPatch, $moduleName)) {
222  $this->patchHistory->fixPatch($schemaPatch);
223  continue;
224  }
228  $schemaPatch = $this->patchFactory->create($schemaPatch, ['schemaSetup' => $this->schemaSetup]);
229  $schemaPatch->apply();
230  $this->patchHistory->fixPatch(get_class($schemaPatch));
231  } catch (\Exception $e) {
232  throw new Exception(
233  new Phrase(
234  'Unable to apply patch %1 for module %2. Original exception message: %3',
235  [
236  get_class($schemaPatch),
237  $moduleName,
238  $e->getMessage()
239  ]
240  )
241  );
242  } finally {
243  unset($schemaPatch);
244  }
245  }
246  }
247 
254  public function revertDataPatches($moduleName = null)
255  {
256  $registry = $this->prepareRegistry($moduleName, self::DATA_PATCH);
257  $adapter = $this->moduleDataSetup->getConnection();
258 
259  foreach ($registry->getReverseIterator() as $dataPatch) {
260  $dataPatch = $this->objectManager->create(
261  '\\' . $dataPatch,
262  ['moduleDataSetup' => $this->moduleDataSetup]
263  );
264  if ($dataPatch instanceof PatchRevertableInterface) {
265  try {
266  $adapter->beginTransaction();
268  $dataPatch->revert();
269  $this->patchHistory->revertPatchFromHistory(get_class($dataPatch));
270  $adapter->commit();
271  } catch (\Exception $e) {
272  $adapter->rollBack();
273  throw new Exception(new Phrase($e->getMessage()));
274  } finally {
275  unset($dataPatch);
276  }
277  }
278  }
279  }
280 }
$objectManager
Definition: bootstrap.php:17
$adapter
Definition: webapi_user.php:16
__construct(PatchReader $dataPatchReader, PatchReader $schemaPatchReader, PatchRegistryFactory $patchRegistryFactory, ResourceConnection $resourceConnection, PatchBackwardCompatability $patchBackwardCompatability, PatchHistory $patchHistory, PatchFactory $patchFactory, ObjectManagerInterface $objectManager, \Magento\Framework\Setup\SchemaSetupInterface $schemaSetup, \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, ModuleList $moduleList)