4 * This file is part of the TYPO3 CMS project.
6 * It is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License, either version 2
8 * of the License, or any later version.
10 * For the full copyright and license information, please read the
11 * LICENSE.txt file that was distributed with this source code.
13 * The TYPO3 project - inspiring people to share!
16 namespace TYPO3\CMS\Install\FolderStructure
;
18 use TYPO3\CMS\Core\Core\Environment
;
19 use TYPO3\CMS\Core\Messaging\FlashMessage
;
20 use TYPO3\CMS\Install\FolderStructure\Exception\InvalidArgumentException
;
23 * Abstract node implements common methods
24 * @internal This class is only meant to be used within EXT:install and is not part of the TYPO3 Core API.
26 abstract class AbstractNode
34 * @var string|null Target permissions for unix, eg. '2775' or '0664' (4 characters string)
36 protected $targetPermission;
39 * @var NodeInterface|null Parent object of this structure node
44 * @var array Directories and root may have children, files and link always empty array
46 protected $children = [];
53 public function getName()
59 * Get target permission
61 * Make sure to call octdec on the value when passing this to chmod
63 * @return string Permissions as a 4 character octal string, i.e. 2775 or 0644
65 protected function getTargetPermission()
67 return $this->targetPermission
;
71 * Set target permission
73 * @param string $permission Permissions as a 4 character octal string, i.e. 2775 or 0644
75 protected function setTargetPermission($permission)
77 // Normalize the permission string to "4 characters", padding with leading "0" if necessary:
78 $permission = substr($permission, 0, 4);
79 $permission = str_pad($permission, 4, '0', STR_PAD_LEFT
);
80 $this->targetPermission
= $permission;
88 protected function getChildren()
90 return $this->children
;
96 * @return NodeInterface|null
98 protected function getParent()
100 return $this->parent
;
104 * Get absolute path of node
108 public function getAbsolutePath()
110 return $this->getParent()->getAbsolutePath() . '/' . $this->name
;
114 * Current node is writable if parent is writable
116 * @return bool TRUE if parent is writable
118 public function isWritable()
120 return $this->getParent()->isWritable();
124 * Checks if node exists.
125 * Returns TRUE if it is there, even if it is only a link.
126 * Does not check the type!
130 protected function exists()
132 if (@is_link
($this->getAbsolutePath())) {
135 return @file_exists
($this->getAbsolutePath());
139 * Fix permission if they are not equal to target permission
142 * @return FlashMessage
144 protected function fixPermission(): FlashMessage
146 if ($this->isPermissionCorrect()) {
148 'Permission on ' . $this->getAbsolutePath() . ' are already ok',
152 $result = @chmod
($this->getAbsolutePath(), octdec($this->getTargetPermission()));
153 if ($result === true) {
154 return new FlashMessage(
156 'Fixed permission on ' . $this->getRelativePathBelowSiteRoot() . '.'
159 return new FlashMessage(
160 'Permissions could not be changed to ' . $this->getTargetPermission()
161 . '. This only is a problem if files and folders within this node cannot be written.',
162 'Permission change on ' . $this->getRelativePathBelowSiteRoot() . ' not successful',
168 * Checks if current permission are identical to target permission
172 protected function isPermissionCorrect()
174 if ($this->isWindowsOs()) {
177 if ($this->getCurrentPermission() === $this->getTargetPermission()) {
184 * Get current permission of node
186 * @return string eg. 2775 for dirs, 0664 for files
188 protected function getCurrentPermission()
190 $permissions = decoct((int)fileperms($this->getAbsolutePath()));
191 return substr($permissions, -4);
195 * Returns TRUE if OS is windows
197 * @return bool TRUE on windows
199 protected function isWindowsOs()
201 return Environment
::isWindows();
205 * Cut off project path from given path
207 * @param string $path Given path
208 * @return string Relative path, but beginning with /
209 * @throws Exception\InvalidArgumentException
211 protected function getRelativePathBelowSiteRoot($path = null)
213 if ($path === null) {
214 $path = $this->getAbsolutePath();
216 $projectPath = Environment
::getProjectPath();
217 if (strpos($path, $projectPath, 0) !== 0) {
218 throw new InvalidArgumentException(
219 'Public path is not first part of given path',
223 $relativePath = substr($path, strlen($projectPath), strlen($path));
224 // Add a forward slash again, so we don't end up with an empty string
225 if ($relativePath === '') {
228 return $relativePath;