TYPO3 CMS  TYPO3_8-7
FileNode.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
18 
22 class FileNode extends AbstractNode implements NodeInterface
23 {
27  protected $targetPermission = '0664';
28 
32  protected $targetContent = null;
33 
41  public function __construct(array $structure, NodeInterface $parent = null)
42  {
43  if (is_null($parent)) {
44  throw new Exception\InvalidArgumentException(
45  'File node must have parent',
46  1366927513
47  );
48  }
49  $this->parent = $parent;
50 
51  // Ensure name is a single segment, but not a path like foo/bar or an absolute path /foo
52  if (strstr($structure['name'], '/') !== false) {
53  throw new Exception\InvalidArgumentException(
54  'File name must not contain forward slash',
55  1366222207
56  );
57  }
58  $this->name = $structure['name'];
59 
60  if (isset($structure['targetPermission'])) {
61  $this->setTargetPermission($structure['targetPermission']);
62  }
63 
64  if (isset($structure['targetContent']) && isset($structure['targetContentFile'])) {
65  throw new Exception\InvalidArgumentException(
66  'Either targetContent or targetContentFile can be set, but not both',
67  1380364361
68  );
69  }
70 
71  if (isset($structure['targetContent'])) {
72  $this->targetContent = $structure['targetContent'];
73  }
74  if (isset($structure['targetContentFile'])) {
75  if (!is_readable($structure['targetContentFile'])) {
76  throw new Exception\InvalidArgumentException(
77  'targetContentFile ' . $structure['targetContentFile'] . ' does not exist or is not readable',
78  1380364362
79  );
80  }
81  $this->targetContent = file_get_contents($structure['targetContentFile']);
82  }
83  }
84 
92  public function getStatus()
93  {
94  $result = [];
95  if (!$this->exists()) {
96  $status = new Status\WarningStatus();
97  $status->setTitle('File ' . $this->getRelativePathBelowSiteRoot() . ' does not exist');
98  $status->setMessage('By using "Try to fix errors" we can try to create it');
99  $result[] = $status;
100  } else {
101  $result = $this->getSelfStatus();
102  }
103  return $result;
104  }
105 
113  public function fix()
114  {
115  $result = $this->fixSelf();
116  return $result;
117  }
118 
124  protected function fixSelf()
125  {
126  $result = [];
127  if (!$this->exists()) {
128  $resultCreateFile = $this->createFile();
129  $result[] = $resultCreateFile;
130  if ($resultCreateFile instanceof Status\OkStatus
131  && !is_null($this->targetContent)
132  ) {
133  $result[] = $this->setContent();
134  if (!$this->isPermissionCorrect()) {
135  $result[] = $this->fixPermission();
136  }
137  }
138  } elseif (!$this->isFile()) {
139  $status = new Status\ErrorStatus();
140  $status->setTitle('Path ' . $this->getRelativePathBelowSiteRoot() . ' is not a file');
141  $fileType = @filetype($this->getAbsolutePath());
142  if ($fileType) {
143  $status->setMessage(
144  'The target ' . $this->getRelativePathBelowSiteRoot() . ' should be a file,' .
145  ' but is of type ' . $fileType . '. This cannot be fixed automatically. Please investigate.'
146  );
147  } else {
148  $status->setMessage(
149  'The target ' . $this->getRelativePathBelowSiteRoot() . ' should be a file,' .
150  ' but is of unknown type, probably because an upper level directory does not exist. Please investigate.'
151  );
152  }
153  $result[] = $status;
154  } elseif (!$this->isPermissionCorrect()) {
155  $result[] = $this->fixPermission();
156  }
157  return $result;
158  }
159 
166  protected function createFile()
167  {
168  if ($this->exists()) {
169  throw new Exception(
170  'File ' . $this->getRelativePathBelowSiteRoot() . ' already exists',
171  1367048077
172  );
173  }
174  $result = @touch($this->getAbsolutePath());
175  if ($result === true) {
176  $status = new Status\OkStatus();
177  $status->setTitle('File ' . $this->getRelativePathBelowSiteRoot() . ' successfully created.');
178  } else {
179  $status = new Status\ErrorStatus();
180  $status->setTitle('File ' . $this->getRelativePathBelowSiteRoot() . ' not created!');
181  $status->setMessage(
182  'The target file could not be created. There is probably a' .
183  ' group or owner permission problem on the parent directory.'
184  );
185  }
186  return $status;
187  }
188 
194  protected function getSelfStatus()
195  {
196  $result = [];
197  if (!$this->isFile()) {
198  $status = new Status\ErrorStatus();
199  $status->setTitle($this->getRelativePathBelowSiteRoot() . ' is not a file');
200  $status->setMessage(
201  'Path ' . $this->getAbsolutePath() . ' should be a file,' .
202  ' but is of type ' . filetype($this->getAbsolutePath())
203  );
204  $result[] = $status;
205  } elseif (!$this->isWritable()) {
206  $status = new Status\NoticeStatus();
207  $status->setTitle('File ' . $this->getRelativePathBelowSiteRoot() . ' is not writable');
208  $status->setMessage(
209  'File ' . $this->getRelativePathBelowSiteRoot() . ' exists, but is not writable.'
210  );
211  $result[] = $status;
212  } elseif (!$this->isPermissionCorrect()) {
213  $status = new Status\NoticeStatus();
214  $status->setTitle('File ' . $this->getRelativePathBelowSiteRoot() . ' permissions mismatch');
215  $status->setMessage(
216  'Default configured permissions are ' . $this->getTargetPermission() .
217  ' but file permissions are ' . $this->getCurrentPermission()
218  );
219  $result[] = $status;
220  }
221  if ($this->isFile() && !$this->isContentCorrect()) {
222  $status = new Status\NoticeStatus();
223  $status->setTitle('File ' . $this->getRelativePathBelowSiteRoot() . ' content differs');
224  $status->setMessage(
225  'File content is not identical to default content. This file may have been changed manually.' .
226  ' The Install Tool will not overwrite the current version!'
227  );
228  $result[] = $status;
229  } else {
230  $status = new Status\OkStatus();
231  $status->setTitle('File ' . $this->getRelativePathBelowSiteRoot());
232  $status->setMessage(
233  'Is a file with the default content and configured permissions of ' . $this->getTargetPermission()
234  );
235  $result[] = $status;
236  }
237  return $result;
238  }
239 
246  protected function isContentCorrect()
247  {
248  $absolutePath = $this->getAbsolutePath();
249  if (is_link($absolutePath) || !is_file($absolutePath)) {
250  throw new Exception(
251  'File ' . $absolutePath . ' must exist',
252  1367056363
253  );
254  }
255  $result = false;
256  if (is_null($this->targetContent)) {
257  $result = true;
258  } else {
259  $targetContentHash = md5($this->targetContent);
260  $currentContentHash = md5(file_get_contents($absolutePath));
261  if ($targetContentHash === $currentContentHash) {
262  $result = true;
263  }
264  }
265  return $result;
266  }
267 
274  protected function setContent()
275  {
276  $absolutePath = $this->getAbsolutePath();
277  if (is_link($absolutePath) || !is_file($absolutePath)) {
278  throw new Exception(
279  'File ' . $absolutePath . ' must exist',
280  1367060201
281  );
282  }
283  if (is_null($this->targetContent)) {
284  throw new Exception(
285  'Target content not defined for ' . $absolutePath,
286  1367060202
287  );
288  }
289  $result = @file_put_contents($absolutePath, $this->targetContent);
290  if ($result !== false) {
291  $status = new Status\OkStatus();
292  $status->setTitle('Set content to ' . $this->getRelativePathBelowSiteRoot());
293  } else {
294  $status = new Status\ErrorStatus();
295  $status->setTitle('Setting content to ' . $this->getRelativePathBelowSiteRoot() . ' failed');
296  $status->setMessage('Setting content of the file failed for unknown reasons.');
297  }
298  return $status;
299  }
300 
306  protected function isFile()
307  {
308  $path = $this->getAbsolutePath();
309  return !is_link($path) && is_file($path);
310  }
311 }
__construct(array $structure, NodeInterface $parent=null)
Definition: FileNode.php:41