copyfiles.class.php 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. <?php
  2. /**
  3. * Processor file for UpgradeMODX extra
  4. *
  5. * Copyright 2015-2018 by Bob Ray <https://bobsguides.com>
  6. * Created on 07-16-2018
  7. *
  8. * UpgradeMODX is free software; you can redistribute it and/or modify it under the
  9. * terms of the GNU General Public License as published by the Free Software
  10. * Foundation; either version 2 of the License, or (at your option) any later
  11. * version.
  12. *
  13. * UpgradeMODX is distributed in the hope that it will be useful, but WITHOUT ANY
  14. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  15. * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along with
  18. * UpgradeMODX; if not, write to the Free Software Foundation, Inc., 59 Temple
  19. * Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. * @package upgrademodx
  22. * @subpackage processors
  23. */
  24. /* @var $modx modX */
  25. include_once 'ugmprocessor.class.php';
  26. class UpgradeMODXCopyfilesProcessor extends UgmProcessor {
  27. var $fileCount = 0;
  28. function initialize() {
  29. /* Initialization here */
  30. parent::initialize();
  31. $this->name = 'Copy Files Processor';
  32. $this->log($this->modx->lexicon('ugm_copying_files'));
  33. return true;
  34. }
  35. public function normalize($paths) {
  36. if (is_array($paths)) {
  37. foreach ($paths as $k => $v) {
  38. $v = str_replace('\\', '/', rtrim($v, '/\\'));
  39. $paths[$k] = $v;
  40. }
  41. } else {
  42. $paths = str_replace('\\', '/', rtrim($paths, '/\\'));
  43. }
  44. return $paths;
  45. }
  46. /** Return true if processors are under core;
  47. * false if not;
  48. *
  49. * @var $corePath string
  50. * @var $pPath string
  51. * @return boolean
  52. */
  53. public function processorsUnderCore($corePath, $pPath) {
  54. /* If processors are under the core, no need to do processors path */
  55. $corePath = $this->normalize($corePath);
  56. $pPath = $this->normalize($pPath);
  57. return stripos($pPath, $corePath) !== false;
  58. }
  59. /**
  60. * Get Array of directories to process
  61. *
  62. * @param array $directories
  63. * @return array
  64. */
  65. public function getDirectories($directories = array()) {
  66. $managerPath = $this->modx->getOption('manager_path', null, MODX_MANAGER_PATH);
  67. $connectorsPath = $this->modx->getOption('connectors_path', null, MODX_CONNECTORS_PATH);
  68. $processorsPath = $this->modx->getOption('processors_path', null, MODX_PROCESSORS_PATH);
  69. if (empty($directories)) {
  70. $directories = array(
  71. 'setup' => $this->basePath . 'setup/',
  72. 'core' => $this->modxCorePath,
  73. 'manager' => $managerPath,
  74. 'connectors' => $connectorsPath,
  75. );
  76. }
  77. if ($this->devMode) {
  78. $directories = array(
  79. 'setup' => $this->testDir . 'setup/',
  80. 'core' => $this->testDir . 'core/',
  81. 'manager' => $this->testDir . 'manager/',
  82. 'connectors' => $this->testDir . 'connectors/',
  83. );
  84. }
  85. /* See if we need to do processors path */
  86. $path = $this->processorsUnderCore($this->modxCorePath, $processorsPath);
  87. if (! $path) { // processors not under core
  88. $directories['core/model/modx/processors'] = $processorsPath;
  89. }
  90. /* Normalize directory paths */
  91. $directories = $this->normalize($directories);
  92. return $directories;
  93. }
  94. /** @throws Exception */
  95. public function copyFiles($sourceDir, $directories) {
  96. /* Normalize directory paths */
  97. $this->normalize($directories);
  98. $this->normalize($sourceDir);
  99. /* Copy directories */
  100. /*
  101. * @var $source string
  102. * @var $target string
  103. */
  104. foreach ($directories as $source => $target) {
  105. if (empty($target)) {
  106. throw new Exception('EMPTY1: ' . $source. ' => ' . $target);
  107. }
  108. $this->mmkDir($target);
  109. set_time_limit(0);
  110. $this->recurse_copy($sourceDir . '/' . $source, $target);
  111. $this->log(' ' . $this->modx->lexicon($this->modx->lexicon('ugm_copied') .
  112. ' ' . $source . ' ' .
  113. $this->modx->lexicon('ugm_to') . ' ' . $target));
  114. }
  115. }
  116. /**
  117. * @param $source string
  118. * @param $dest string
  119. * @return bool
  120. * @throws Exception
  121. */
  122. public function recurse_copy($source, $dest) {
  123. if (empty($source)) {
  124. throw new Exception('[Copy Files Processor] Source path is empty -- Source = ' . $source);
  125. }
  126. if (empty($dest)) {
  127. throw new Exception('[Copy Files Processor] Destination path is empty -- Path = ' . $dest);
  128. }
  129. /* Skip these (setup/includes/config.core.php copied elsewhere) */
  130. $configCore = 'config.core.php';
  131. // Check for symlinks
  132. if (is_link($source)) {
  133. $this->fileCount++;
  134. return symlink(readlink($source), $dest);
  135. }
  136. // Simple copy for a file
  137. if (is_file($source)) {
  138. $this->fileCount++;
  139. return copy($source, $dest);
  140. }
  141. if (is_dir($source)) {
  142. $this->fileCount++;
  143. }
  144. // Make destination directory
  145. if (!is_dir($dest)) {
  146. mkdir($dest);
  147. }
  148. // Loop through the folder
  149. $dir = dir($source);
  150. while (false !== ($entry = $dir->read())) {
  151. // Skip pointers and config files
  152. if ($entry == '.' || $entry == '..' || $entry == $configCore) {
  153. continue;
  154. }
  155. // Deep copy directories
  156. $this->recurse_copy("{$source}/{$entry}", "{$dest}/{$entry}");
  157. }
  158. // Clean up
  159. $dir->close();
  160. return true;
  161. }
  162. public function process() {
  163. $version = str_replace('.zip', '' , $this->zipFileName);
  164. /* Get directories for file copy */
  165. try {
  166. $directories = $this->getDirectories();
  167. $directories = $this->normalize($directories);
  168. } catch (Exception $e) {
  169. $this->addError($e->getMessage());
  170. }
  171. if (! $this->hasErrors()) {
  172. /* set start time */
  173. $mtime = microtime();
  174. $mtime = explode(" ", $mtime);
  175. $mtime = $mtime[1] + $mtime[0];
  176. $tstart = $mtime;
  177. set_time_limit(0);
  178. $source = $this->unzippedDir . '/' . $version;
  179. $dest = $this->devMode ? $this->testDir : $this->basePath;
  180. try {
  181. copy($source . '/ht.access', $dest . 'ht.access');
  182. copy($source . '/index.php', $dest . 'index.php');
  183. $this->copyFiles($source, $directories);
  184. /* We do need this one */
  185. copy($source . '/setup/includes/config.core.php', $dest . '/setup/includes/config.core.php');
  186. } catch (Exception $e) {
  187. $this->addError($e->getMessage());
  188. }
  189. /* report how long it took */
  190. $output = '';
  191. $mtime = microtime();
  192. $mtime = explode(" ", $mtime);
  193. $mtime = $mtime[1] + $mtime[0];
  194. $tend = $mtime;
  195. $totalTime = ($tend - $tstart);
  196. $totalTime = sprintf("%2.4f s", $totalTime);
  197. $output .= "\n " . 'Copy Time' .
  198. ': ' . $totalTime;
  199. $output .= ' -- ' . $this->modx->lexicon('ugm_files_copied') . ' ' . $this->fileCount;
  200. $this->log($output);
  201. } else {
  202. $output = 'Exception occurred in copyFiles processor ' . isset($this->errors[0])? $this->errors[0] : '';
  203. $this->log($output);
  204. }
  205. return $this->prepareResponse($this->modx->lexicon('ugm_preparing_setup'));
  206. }
  207. }
  208. return 'UpgradeMODXCopyfilesProcessor';