1 | <?php |
||
2 | |||
3 | namespace Sunnysideup\MoveLargeFilesToAssets; |
||
4 | |||
5 | use SilverStripe\Assets\File; |
||
6 | use SilverStripe\Assets\Folder; |
||
7 | use SilverStripe\Assets\Image; |
||
8 | use SilverStripe\Control\Controller; |
||
9 | use SilverStripe\Control\Director; |
||
10 | use SilverStripe\Dev\Tasks\MigrateFileTask; |
||
11 | use SilverStripe\ORM\DB; |
||
12 | |||
13 | class MoveFiles extends MigrateFileTask |
||
14 | { |
||
15 | /** |
||
16 | * {@inheritDoc} |
||
17 | */ |
||
18 | protected $title = 'Copy (large / large number of) files to assets'; |
||
19 | |||
20 | /** |
||
21 | * {@inheritDoc} |
||
22 | */ |
||
23 | protected $description = 'Move predefined folder to assets/predefined folder and register in Database.'; |
||
24 | |||
25 | /** |
||
26 | * {@inheritDoc} |
||
27 | */ |
||
28 | protected $enabled = true; |
||
29 | |||
30 | private static $segment = 'MoveFiles'; |
||
31 | |||
32 | private static $include_reset = true; |
||
33 | |||
34 | private static $use_exec_for_copy = true; |
||
35 | |||
36 | private static $folder_name = 'new-files'; |
||
37 | |||
38 | /** |
||
39 | * {@inheritDoc} |
||
40 | */ |
||
41 | public function run($request) |
||
42 | { |
||
43 | $folderNameFromConfig = self::config()->get('folder_name'); |
||
44 | $oldPathFromConfig = Controller::join_links(Director::baseFolder(), $folderNameFromConfig); |
||
45 | $base = Director::baseFolder(); |
||
46 | $baseWithFolderNameFromConfig = Controller::join_links($base, $folderNameFromConfig); |
||
0 ignored issues
–
show
Unused Code
introduced
by
![]() |
|||
47 | |||
48 | if (is_dir($oldPathFromConfig)) { |
||
49 | $newPath = Controller::join_links(ASSETS_PATH, $folderNameFromConfig); |
||
50 | $this->reset($newPath); |
||
51 | $this->reset($newPath); |
||
52 | DB::alteration_message('copying --' . $oldPathFromConfig . '-- to --' . $newPath); |
||
53 | $this->rcopy($oldPathFromConfig, $newPath); |
||
54 | $this->registerFiles($newPath); |
||
55 | $this->defaultSubtasks = [ |
||
56 | 'move-files', |
||
57 | 'migrate-folders', |
||
58 | 'generate-cms-thumbnails', |
||
59 | 'fix-folder-permissions', |
||
60 | 'fix-secureassets', |
||
61 | 'normalise-access', |
||
62 | ]; |
||
63 | parent::run($request); |
||
64 | } |
||
65 | } |
||
66 | |||
67 | public function reset($newPath) |
||
68 | { |
||
69 | if ($this->Config()->get('include_reset')) { |
||
70 | $folderPath = str_replace(ASSETS_PATH . '/', '', $newPath); |
||
71 | $folder = Folder::find_or_make($folderPath); |
||
72 | if ($folder) { |
||
0 ignored issues
–
show
|
|||
73 | $folder->delete(); |
||
74 | DB::alteration_message('Deleting folder ' . $folderPath . ', based on ' . $newPath, 'deleted'); |
||
75 | } |
||
76 | if (file_exists($newPath)) { |
||
77 | $this->rrmdir($newPath); |
||
78 | DB::alteration_message('Deleting folder ' . $folderPath . ', based on ' . $newPath . ', from file system', 'deleted'); |
||
79 | } |
||
80 | if (file_exists($newPath)) { |
||
81 | user_error('ERROR: Could not reset files', E_USER_ERROR); |
||
82 | } |
||
83 | } else { |
||
84 | DB::alteration_message('OK: not including reset'); |
||
85 | } |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * {@inheritDoc} |
||
90 | */ |
||
91 | protected function registerFiles($newPath) |
||
92 | { |
||
93 | $files = $this->getDirContents($newPath); |
||
94 | foreach ($files as $newPath) { |
||
0 ignored issues
–
show
|
|||
95 | $this->addToDb($newPath); |
||
96 | } |
||
97 | } |
||
98 | |||
99 | protected function addToDb(string $newPath) |
||
100 | { |
||
101 | DB::alteration_message('considering ' . $newPath); |
||
102 | if (! is_dir($newPath)) { |
||
103 | $fileName = basename($newPath); |
||
104 | $folderPath = str_replace(ASSETS_PATH . '/', '', dirname($newPath)); |
||
105 | $folder = Folder::find_or_make($folderPath); |
||
106 | $filter = ['Name' => $fileName, 'ParentID' => $folder->ID]; |
||
107 | $file = File::get()->filter($filter)->exists(); |
||
108 | if (! $file) { |
||
109 | if ($this->isImage($newPath)) { |
||
110 | DB::alteration_message('New IMAGE!: ' . $newPath); |
||
111 | $file = Image::create(); |
||
112 | } else { |
||
113 | DB::alteration_message('New FILE!: ' . $newPath); |
||
114 | $file = File::create(); |
||
115 | } |
||
116 | $file->setFromLocalFile($newPath); |
||
117 | $file->ParentID = $folder->ID; |
||
118 | $file->write(); |
||
119 | $file->doPublish(); |
||
120 | } else { |
||
121 | DB::alteration_message('existing file: ' . $newPath); |
||
122 | } |
||
123 | } |
||
124 | } |
||
125 | |||
126 | protected function getDirContents(string $dir, ?array &$results = []) |
||
127 | { |
||
128 | $files = scandir($dir); |
||
129 | |||
130 | foreach ($files as $key => $value) { |
||
131 | $path = realpath($dir . DIRECTORY_SEPARATOR . $value); |
||
132 | if (! is_dir($path)) { |
||
133 | $results[] = $path; |
||
134 | } elseif ('.' !== $value && '..' !== $value) { |
||
135 | $this->getDirContents($path, $results); |
||
136 | $results[] = $path; |
||
137 | } |
||
138 | } |
||
139 | |||
140 | return $results; |
||
141 | } |
||
142 | |||
143 | protected function isImage(string $newPath): bool |
||
144 | { |
||
145 | $ext = pathinfo( |
||
146 | parse_url($newPath, PHP_URL_PATH), |
||
147 | PATHINFO_EXTENSION |
||
148 | ); |
||
149 | |||
150 | return in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true); |
||
151 | } |
||
152 | |||
153 | protected function normalizePath($path) |
||
154 | { |
||
155 | return $path . (is_dir($path) && ! preg_match('#/$#', $path) ? '/' : ''); |
||
156 | } |
||
157 | |||
158 | protected function rscandir($dir, $sort = SCANDIR_SORT_ASCENDING) |
||
159 | { |
||
160 | $results = []; |
||
161 | |||
162 | if (! is_dir($dir)) { |
||
163 | return $results; |
||
164 | } |
||
165 | |||
166 | $dir = $this->normalizePath($dir); |
||
167 | |||
168 | $objects = scandir($dir, $sort); |
||
169 | |||
170 | foreach ($objects as $object) { |
||
171 | if ('.' !== $object && '..' !== $object) { |
||
172 | if (is_dir($dir . $object)) { |
||
173 | $results = array_merge($results, $this->rscandir($dir . $object, $sort)); |
||
174 | } else { |
||
175 | $results[] = $dir . $object; |
||
176 | } |
||
177 | } |
||
178 | } |
||
179 | |||
180 | $results[] = $dir; |
||
181 | |||
182 | return $results; |
||
183 | } |
||
184 | |||
185 | protected function rcopy($source, $dest, $destmode = null) |
||
186 | { |
||
187 | if ($this->Config()->get('use_exec_for_copy')) { |
||
188 | exec('cp ' . $source . ' ' . ASSETS_PATH . ' -r'); |
||
189 | |||
190 | return; |
||
191 | } |
||
192 | $files = $this->rscandir($source); |
||
193 | |||
194 | if (empty($files)) { |
||
195 | return; |
||
196 | } |
||
197 | |||
198 | if (! file_exists($dest)) { |
||
199 | DB::alteration_message('MKDIR --' . $dest); |
||
200 | mkdir($dest, is_int($destmode) ? $destmode : fileperms($source), true); |
||
201 | } |
||
202 | |||
203 | $source = $this->normalizePath(realpath($source)); |
||
204 | $dest = $this->normalizePath(realpath($dest)); |
||
205 | |||
206 | foreach ($files as $file) { |
||
207 | $file_dest = str_replace($source, $dest, $file); |
||
208 | $file = str_replace(' ', ' ', $file); |
||
209 | $file_dest = str_replace(' ', ' ', $file_dest); |
||
210 | if (is_dir($file)) { |
||
211 | if (! file_exists($file_dest)) { |
||
212 | DB::alteration_message('MKDIR --' . $file_dest); |
||
213 | mkdir($file_dest, is_int($destmode) ? $destmode : fileperms($file), true); |
||
214 | } |
||
215 | } else { |
||
216 | DB::alteration_message('COPY --' . $file . '-- to --' . $file_dest . '--'); |
||
217 | if (file_exists($file)) { |
||
218 | if (! file_exists($file_dest)) { |
||
219 | copy($file, $file_dest); |
||
220 | if (! file_exists($file_dest)) { |
||
221 | DB::alteration_message('ERROR could not find after copy: --' . $file_dest); |
||
222 | die(); |
||
0 ignored issues
–
show
|
|||
223 | } |
||
224 | } else { |
||
225 | DB::alteration_message('ERROR file already exists: --' . $file_dest); |
||
226 | } |
||
227 | } else { |
||
228 | DB::alteration_message('ERROR could not find: --' . $file); |
||
229 | die(''); |
||
0 ignored issues
–
show
|
|||
230 | } |
||
231 | } |
||
232 | } |
||
233 | } |
||
234 | |||
235 | protected function rrmdir($dir) |
||
236 | { |
||
237 | if (is_dir($dir)) { |
||
238 | $objects = scandir($dir); |
||
239 | foreach ($objects as $object) { |
||
240 | if ('.' !== $object && '..' !== $object) { |
||
241 | if (is_dir($dir . DIRECTORY_SEPARATOR . $object) && ! is_link($dir . '/' . $object)) { |
||
242 | $this->rrmdir($dir . DIRECTORY_SEPARATOR . $object); |
||
243 | } else { |
||
244 | unlink($dir . DIRECTORY_SEPARATOR . $object); |
||
245 | } |
||
246 | } |
||
247 | } |
||
248 | rmdir($dir); |
||
249 | } |
||
250 | } |
||
251 | } |
||
252 |