Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
DeploystrategyAbstract.php
Go to the documentation of this file.
1 <?php
7 
11 abstract class DeploystrategyAbstract
12 {
18  protected $mappings = array();
19 
25  protected $currentMapping = array();
26 
32  protected $ignoredMappings = array();
33 
34 
40  protected $destDir;
41 
47  protected $sourceDir;
48 
54  protected $isForced = false;
55 
62  public function __construct($sourceDir, $destDir)
63  {
64  $this->destDir = $destDir;
65  $this->sourceDir = $sourceDir;
66  }
67 
73  public function deploy()
74  {
75  foreach ($this->getMappings() as $data) {
76  list ($source, $dest) = $data;
77  $this->setCurrentMapping($data);
78  $this->create($source, $dest);
79  }
80  return $this;
81  }
82 
88  public function clean()
89  {
90  foreach ($this->getMappings() as $data) {
91  list ($source, $dest) = $data;
92  $this->remove($source, $dest);
93  $this->rmEmptyDirsRecursive(dirname($dest), $this->getDestDir());
94  }
95  return $this;
96  }
97 
103  protected function getDestDir()
104  {
105  return $this->destDir;
106  }
107 
113  protected function getSourceDir()
114  {
115  return $this->sourceDir;
116  }
117 
123  public function isForced()
124  {
125  return $this->isForced;
126  }
127 
133  public function setIsForced($forced = true)
134  {
135  $this->isForced = (bool) $forced;
136  }
137 
143  public function getMappings()
144  {
145  return $this->mappings;
146  }
147 
153  public function setMappings(array $mappings)
154  {
155  $this->mappings = $mappings;
156  }
157 
163  public function getCurrentMapping()
164  {
165  return $this->currentMapping;
166  }
167 
173  public function setCurrentMapping($mapping)
174  {
175  $this->currentMapping = $mapping;
176  }
177 
178 
185  {
186  $this->ignoredMappings = $ignoredMappings;
187  }
188 
194  public function getIgnoredMappings()
195  {
196  return $this->ignoredMappings;
197  }
198 
199 
205  protected function isDestinationIgnored($destination)
206  {
207  $destination = '/'.$destination;
208  $destination = str_replace('/./','/', $destination);
209  $destination = str_replace('//','/', $destination);
210  foreach($this->ignoredMappings as $ignored){
211  if( 0 === strpos($ignored,$destination) ){
212  return true;
213  }
214  }
215  return false;
216  }
217 
221  public function addMapping($key, $value)
222  {
223  $this->mappings[] = array($key, $value);
224  }
225 
226  protected function removeTrailingSlash($path)
227  {
228  return rtrim($path, ' \\/');
229  }
230 
241  public function create($source, $dest)
242  {
243  if($this->isDestinationIgnored($dest)){
244  return;
245  }
246 
247  $sourcePath = $this->getSourceDir() . '/' . $this->removeTrailingSlash($source);
248  $destPath = $this->getDestDir() . '/' . $dest;
249 
250  /* List of possible cases, keep around for now, might come in handy again
251 
252  Assume app/etc exists, app/etc/a does not exist unless specified differently
253 
254  dir app/etc/a/ --> link app/etc/a to dir
255  dir app/etc/a --> link app/etc/a to dir
256  dir app/etc/ --> link app/etc/dir to dir
257  dir app/etc --> link app/etc/dir to dir
258 
259  dir/* app/etc --> for each dir/$file create a target link in app/etc
260  dir/* app/etc/ --> for each dir/$file create a target link in app/etc
261  dir/* app/etc/a --> for each dir/$file create a target link in app/etc/a
262  dir/* app/etc/a/ --> for each dir/$file create a target link in app/etc/a
263 
264  file app/etc --> link app/etc/file to file
265  file app/etc/ --> link app/etc/file to file
266  file app/etc/a --> link app/etc/a to file
267  file app/etc/a --> if app/etc/a is a file throw exception unless force is set, in that case rm and see above
268  file app/etc/a/ --> link app/etc/a/file to file regardless if app/etc/a exists or not
269 
270  */
271 
272  // Create target directory if it ends with a directory separator
273  if (! file_exists($destPath) && in_array(substr($destPath, -1), array('/', '\\')) && ! is_dir($sourcePath)) {
274  mkdir($destPath, 0777, true);
275  $destPath = $this->removeTrailingSlash($destPath);
276  }
277 
278  // If source doesn't exist, check if it's a glob expression, otherwise we have nothing we can do
279  if (!file_exists($sourcePath)) {
280  // Handle globing
281  $matches = glob($sourcePath);
282  if ($matches) {
283  foreach ($matches as $match) {
284  $newDest = substr($destPath . '/' . basename($match), strlen($this->getDestDir()));
285  $newDest = ltrim($newDest, ' \\/');
286  $this->create(substr($match, strlen($this->getSourceDir())+1), $newDest);
287  }
288  return true;
289  }
290 
291  // Source file isn't a valid file or glob
292  throw new \ErrorException("Source $sourcePath does not exist");
293  }
294  return $this->createDelegate($source, $dest);
295  }
296 
304  public function remove($source, $dest)
305  {
306  $sourcePath = $this->getSourceDir() . '/' . $this->removeTrailingSlash($source);
307  $destPath = $this->getDestDir() . '/' . $dest;
308 
309  // If source doesn't exist, check if it's a glob expression, otherwise we have nothing we can do
310  if (!file_exists($sourcePath)) {
311  $this->removeContentOfCategory($sourcePath, $destPath);
312  return;
313  } elseif (file_exists($sourcePath) && is_dir($sourcePath)) {
314  $this->removeContentOfCategory($sourcePath . '/*', $destPath);
315  @rmdir($destPath);
316  return;
317  }
318 
319  // MP Avoid removing whole folders in case the modman file is not 100% well-written
320  // e.g. app/etc/modules/Testmodule.xml app/etc/modules/ installs correctly, but would otherwise delete the whole app/etc/modules folder!
321  if (basename($sourcePath) !== basename($destPath)) {
322  $destPath .= '/' . basename($source);
323  }
324  self::rmdirRecursive($destPath);
325  }
326 
334  protected function removeContentOfCategory($sourcePath, $destPath)
335  {
336  $sourcePath = preg_replace('#/\*$#', '/{,.}*', $sourcePath);
337  $matches = glob($sourcePath, GLOB_BRACE);
338  if ($matches) {
339  foreach ($matches as $match) {
340  if (preg_match("#/\.{1,2}$#", $match)) {
341  continue;
342  }
343  $newDest = substr($destPath . '/' . basename($match), strlen($this->getDestDir()));
344  $newDest = ltrim($newDest, ' \\/');
345  $this->remove(substr($match, strlen($this->getSourceDir())+1), $newDest);
346  }
347  return;
348  }
349 
350  // Source file isn't a valid file or glob
351  throw new \ErrorException("Source $sourcePath does not exist");
352  }
353 
360  public function rmEmptyDirsRecursive($dir, $stopDir = null)
361  {
362  $absoluteDir = $this->getDestDir() . '/' . $dir;
363  if (is_dir($absoluteDir)) {
364  $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($absoluteDir),
365  \RecursiveIteratorIterator::CHILD_FIRST);
366 
367  foreach ($iterator as $item) {
368  $path = (string) $item;
369  if (!strcmp($path, '.') || !strcmp($path, '..')) {
370  continue;
371  }
372  // The directory contains something, do not remove
373  return;
374  }
375  // RecursiveIteratorIterator have opened handle on $absoluteDir
376  // that cause Windows to block the directory and not remove it until
377  // the iterator will be destroyed.
378  unset($iterator);
379 
380  // The specified directory is empty
381  if (@rmdir($absoluteDir)) {
382  // If the parent directory doesn't match the $stopDir and it's empty, remove it, too
383  $parentDir = dirname($dir);
384  $absoluteParentDir = $this->getDestDir() . '/' . $parentDir;
385  if (! isset($stopDir) || (realpath($stopDir) !== realpath($absoluteParentDir))) {
386  // Remove the parent directory if it is empty
387  $this->rmEmptyDirsRecursive($parentDir);
388  }
389  }
390  }
391  }
392 
398  public static function rmdirRecursive($dir)
399  {
400  $fs = new \Composer\Util\Filesystem();
401  if(is_dir($dir)){
402  $result = $fs->removeDirectory($dir);
403  }else{
404  @unlink($dir);
405  }
406 
407  return;
408  }
409 
410 
420  abstract protected function createDelegate($source, $dest);
421 
422 }
elseif(isset( $params[ 'redirect_parent']))
Definition: iframe.phtml:17
$source
Definition: source.php:23
$value
Definition: gender.phtml:16
mkdir($pathname, $mode=0777, $recursive=false, $context=null)
Definition: ioMock.php:25