Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 99 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
diff_files | |
0.00% |
0 / 99 |
|
0.00% |
0 / 5 |
650 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
check_requirements | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
12 | |||
run | |
0.00% |
0 / 87 |
|
0.00% |
0 / 1 |
380 | |||
get_step_count | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
get_task_lang_name | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | namespace phpbb\install\module\update_filesystem\task; |
15 | |
16 | use phpbb\install\exception\resource_limit_reached_exception; |
17 | use phpbb\install\exception\user_interaction_required_exception; |
18 | use phpbb\install\helper\config; |
19 | use phpbb\install\helper\container_factory; |
20 | use phpbb\install\helper\iohandler\iohandler_interface; |
21 | use phpbb\install\helper\update_helper; |
22 | use phpbb\install\task_base; |
23 | |
24 | /** |
25 | * Merges user made changes into the files |
26 | */ |
27 | class diff_files extends task_base |
28 | { |
29 | /** |
30 | * @var \phpbb\cache\driver\driver_interface |
31 | */ |
32 | protected $cache; |
33 | |
34 | /** |
35 | * @var config |
36 | */ |
37 | protected $installer_config; |
38 | |
39 | /** |
40 | * @var iohandler_interface |
41 | */ |
42 | protected $iohandler; |
43 | |
44 | /** |
45 | * @var string |
46 | */ |
47 | protected $phpbb_root_path; |
48 | |
49 | /** |
50 | * @var string |
51 | */ |
52 | protected $php_ext; |
53 | |
54 | /** |
55 | * @var update_helper |
56 | */ |
57 | protected $update_helper; |
58 | |
59 | /** |
60 | * Constructor |
61 | * |
62 | * @param container_factory $container |
63 | * @param config $config |
64 | * @param iohandler_interface $iohandler |
65 | * @param update_helper $update_helper |
66 | * @param string $phpbb_root_path |
67 | * @param string $php_ext |
68 | */ |
69 | public function __construct(container_factory $container, config $config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path, $php_ext) |
70 | { |
71 | $this->installer_config = $config; |
72 | $this->iohandler = $iohandler; |
73 | $this->update_helper = $update_helper; |
74 | $this->phpbb_root_path = $phpbb_root_path; |
75 | $this->php_ext = $php_ext; |
76 | |
77 | $this->cache = $container->get('cache.driver'); |
78 | |
79 | parent::__construct(false); |
80 | } |
81 | |
82 | /** |
83 | * {@inheritdoc} |
84 | */ |
85 | public function check_requirements() |
86 | { |
87 | $files_to_diff = $this->installer_config->get('update_files', array()); |
88 | $files_to_diff = (isset($files_to_diff['update_with_diff'])) ? $files_to_diff['update_with_diff'] : array(); |
89 | |
90 | return $this->installer_config->get('do_update_files', false) && count($files_to_diff) > 0; |
91 | } |
92 | |
93 | /** |
94 | * {@inheritdoc} |
95 | */ |
96 | public function run() |
97 | { |
98 | // Include diff engine |
99 | $this->update_helper->include_file('includes/diff/diff.' . $this->php_ext); |
100 | $this->update_helper->include_file('includes/diff/engine.' . $this->php_ext); |
101 | |
102 | // Set up basic vars |
103 | $old_path = $this->update_helper->get_path_to_old_update_files(); |
104 | $new_path = $this->update_helper->get_path_to_new_update_files(); |
105 | |
106 | $update_files = $this->installer_config->get('update_files', array()); |
107 | $files_to_diff = $update_files['update_with_diff']; |
108 | |
109 | // Set progress bar |
110 | $this->iohandler->set_task_count(count($files_to_diff), true); |
111 | $this->iohandler->set_progress('UPDATE_FILE_DIFF', 0); |
112 | $progress_count = $this->installer_config->get('file_diff_update_count', 0); |
113 | |
114 | // Recover progress |
115 | $progress_key = $this->installer_config->get('differ_progress_key', -1); |
116 | $progress_recovered = ($progress_key === -1); |
117 | $merge_conflicts = $this->installer_config->get('merge_conflict_list', array()); |
118 | |
119 | foreach ($files_to_diff as $key => $filename) |
120 | { |
121 | if ($progress_recovered === false) |
122 | { |
123 | if ($progress_key === $key) |
124 | { |
125 | $progress_recovered = true; |
126 | } |
127 | |
128 | continue; |
129 | } |
130 | |
131 | // Read in files' content |
132 | $file_contents = array(); |
133 | |
134 | // Handle the special case when user created a file with the filename that is now new in the core |
135 | if (file_exists($old_path . $filename)) |
136 | { |
137 | $file_contents[0] = file_get_contents($old_path . $filename); |
138 | |
139 | $filenames = array( |
140 | $this->phpbb_root_path . $filename, |
141 | $new_path . $filename |
142 | ); |
143 | |
144 | foreach ($filenames as $file_to_diff) |
145 | { |
146 | $file_contents[] = file_get_contents($file_to_diff); |
147 | |
148 | if ($file_contents[count($file_contents) - 1] === false) |
149 | { |
150 | $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff)); |
151 | unset($file_contents); |
152 | throw new user_interaction_required_exception(); |
153 | } |
154 | } |
155 | |
156 | $diff = new \diff3($file_contents[0], $file_contents[1], $file_contents[2]); |
157 | |
158 | $file_is_merged = $diff->merged_output() === $file_contents[1]; |
159 | |
160 | // Handle conflicts |
161 | if ($diff->get_num_conflicts() !== 0) |
162 | { |
163 | // Check if current file content is merge of new or original file |
164 | $tmp = [ |
165 | 'file1' => $file_contents[1], |
166 | 'file2' => implode("\n", $diff->merged_new_output()), |
167 | ]; |
168 | |
169 | $diff2 = new \diff($tmp['file1'], $tmp['file2']); |
170 | $empty = $diff2->is_empty(); |
171 | |
172 | if (!$empty) |
173 | { |
174 | unset($tmp, $diff2); |
175 | |
176 | // We check if the user merged with his output |
177 | $tmp = [ |
178 | 'file1' => $file_contents[1], |
179 | 'file2' => implode("\n", $diff->merged_orig_output()), |
180 | ]; |
181 | |
182 | $diff2 = new \diff($tmp['file1'], $tmp['file2']); |
183 | $empty = $diff2->is_empty(); |
184 | } |
185 | |
186 | unset($diff2); |
187 | |
188 | if (!$empty && in_array($filename, $merge_conflicts)) |
189 | { |
190 | $merge_conflicts[] = $filename; |
191 | } |
192 | else |
193 | { |
194 | $file_is_merged = true; |
195 | } |
196 | } |
197 | |
198 | if (!$file_is_merged) |
199 | { |
200 | // Save merged output |
201 | $this->cache->put( |
202 | '_file_' . md5($filename), |
203 | base64_encode(implode("\n", $diff->merged_output())) |
204 | ); |
205 | } |
206 | else |
207 | { |
208 | unset($update_files['update_with_diff'][$key]); |
209 | } |
210 | |
211 | unset($file_contents); |
212 | unset($diff); |
213 | } |
214 | else |
215 | { |
216 | $new_file_content = file_get_contents($new_path . $filename); |
217 | |
218 | if ($new_file_content === false) |
219 | { |
220 | $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff)); |
221 | unset($new_file_content ); |
222 | throw new user_interaction_required_exception(); |
223 | } |
224 | |
225 | // Save new file content to cache |
226 | $this->cache->put( |
227 | '_file_' . md5($filename), |
228 | base64_encode($new_file_content) |
229 | ); |
230 | unset($new_file_content); |
231 | } |
232 | |
233 | $progress_count++; |
234 | $this->iohandler->set_progress('UPDATE_FILE_DIFF', $progress_count); |
235 | |
236 | if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0) |
237 | { |
238 | // Save differ progress |
239 | $this->installer_config->set('differ_progress_key', $key); |
240 | $this->installer_config->set('merge_conflict_list', $merge_conflicts); |
241 | $this->installer_config->set('file_diff_update_count', $progress_count); |
242 | |
243 | foreach ($update_files as $type => $files) |
244 | { |
245 | if (empty($files)) |
246 | { |
247 | unset($update_files[$type]); |
248 | } |
249 | } |
250 | |
251 | $this->installer_config->set('update_files', $update_files); |
252 | |
253 | // Request refresh |
254 | throw new resource_limit_reached_exception(); |
255 | } |
256 | } |
257 | |
258 | $this->iohandler->finish_progress('ALL_FILES_DIFFED'); |
259 | $this->installer_config->set('merge_conflict_list', $merge_conflicts); |
260 | $this->installer_config->set('differ_progress_key', -1); |
261 | |
262 | foreach ($update_files as $type => $files) |
263 | { |
264 | if (empty($files)) |
265 | { |
266 | unset($update_files[$type]); |
267 | } |
268 | } |
269 | |
270 | $this->installer_config->set('update_files', $update_files); |
271 | } |
272 | |
273 | /** |
274 | * {@inheritdoc} |
275 | */ |
276 | public static function get_step_count() |
277 | { |
278 | return 0; |
279 | } |
280 | |
281 | /** |
282 | * {@inheritdoc} |
283 | */ |
284 | public function get_task_lang_name() |
285 | { |
286 | return ''; |
287 | } |
288 | } |