[TASK] Replace TYPO3_OS constant with Environment check
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / FolderStructure / AbstractNode.php
1 <?php
2 namespace TYPO3\CMS\Install\FolderStructure;
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
17 use TYPO3\CMS\Core\Core\Environment;
18 use TYPO3\CMS\Core\Messaging\FlashMessage;
19
20 /**
21 * Abstract node implements common methods
22 */
23 abstract class AbstractNode
24 {
25 /**
26 * @var string Name
27 */
28 protected $name = '';
29
30 /**
31 * @var string|null Target permissions for unix, eg. '2775' or '0664' (4 characters string)
32 */
33 protected $targetPermission = null;
34
35 /**
36 * @var NodeInterface|null Parent object of this structure node
37 */
38 protected $parent = null;
39
40 /**
41 * @var array Directories and root may have children, files and link always empty array
42 */
43 protected $children = [];
44
45 /**
46 * Get name
47 *
48 * @return string Name
49 */
50 public function getName()
51 {
52 return $this->name;
53 }
54
55 /**
56 * Get target permission
57 *
58 * Make sure to call octdec on the value when passing this to chmod
59 *
60 * @return string Permissions as a 4 character octal string, i.e. 2775 or 0644
61 */
62 protected function getTargetPermission()
63 {
64 return $this->targetPermission;
65 }
66
67 /**
68 * Set target permission
69 *
70 * @param string $permission Permissions as a 4 character octal string, i.e. 2775 or 0644
71 */
72 protected function setTargetPermission($permission)
73 {
74 // Normalize the permission string to "4 characters", padding with leading "0" if necessary:
75 $permission = substr($permission, 0, 4);
76 $permission = str_pad($permission, 4, '0', STR_PAD_LEFT);
77 $this->targetPermission = $permission;
78 }
79
80 /**
81 * Get children
82 *
83 * @return array
84 */
85 protected function getChildren()
86 {
87 return $this->children;
88 }
89
90 /**
91 * Get parent
92 *
93 * @return NodeInterface|null
94 */
95 protected function getParent()
96 {
97 return $this->parent;
98 }
99
100 /**
101 * Get absolute path of node
102 *
103 * @return string
104 */
105 public function getAbsolutePath()
106 {
107 return $this->getParent()->getAbsolutePath() . '/' . $this->name;
108 }
109
110 /**
111 * Current node is writable if parent is writable
112 *
113 * @return bool TRUE if parent is writable
114 */
115 public function isWritable()
116 {
117 return $this->getParent()->isWritable();
118 }
119
120 /**
121 * Checks if node exists.
122 * Returns TRUE if it is there, even if it is only a link.
123 * Does not check the type!
124 *
125 * @return bool
126 */
127 protected function exists()
128 {
129 if (@is_link($this->getAbsolutePath())) {
130 return true;
131 }
132 return @file_exists($this->getAbsolutePath());
133 }
134
135 /**
136 * Fix permission if they are not equal to target permission
137 *
138 * @throws Exception
139 * @return FlashMessage
140 */
141 protected function fixPermission(): FlashMessage
142 {
143 if ($this->isPermissionCorrect()) {
144 throw new Exception(
145 'Permission on ' . $this->getAbsolutePath() . ' are already ok',
146 1366744035
147 );
148 }
149 $result = @chmod($this->getAbsolutePath(), octdec($this->getTargetPermission()));
150 if ($result === true) {
151 return new FlashMessage(
152 '',
153 'Fixed permission on ' . $this->getRelativePathBelowSiteRoot() . '.'
154 );
155 }
156 return new FlashMessage(
157 'Permissions could not be changed to ' . $this->getTargetPermission()
158 . '. This only is a problem if files and folders within this node cannot be written.',
159 'Permission change on ' . $this->getRelativePathBelowSiteRoot() . ' not successful',
160 FlashMessage::NOTICE
161 );
162 }
163
164 /**
165 * Checks if current permission are identical to target permission
166 *
167 * @return bool
168 */
169 protected function isPermissionCorrect()
170 {
171 if ($this->isWindowsOs()) {
172 return true;
173 }
174 if ($this->getCurrentPermission() === $this->getTargetPermission()) {
175 return true;
176 }
177 return false;
178 }
179
180 /**
181 * Get current permission of node
182 *
183 * @return string, eg. 2775 for dirs, 0664 for files
184 */
185 protected function getCurrentPermission()
186 {
187 $permissions = decoct(fileperms($this->getAbsolutePath()));
188 return substr($permissions, -4);
189 }
190
191 /**
192 * Returns TRUE if OS is windows
193 *
194 * @return bool TRUE on windows
195 */
196 protected function isWindowsOs()
197 {
198 return Environment::isWindows();
199 }
200
201 /**
202 * Cut off PATH_site from given path
203 *
204 * @param string $path Given path
205 * @return string Relative path, but beginning with /
206 * @throws Exception\InvalidArgumentException
207 */
208 protected function getRelativePathBelowSiteRoot($path = null)
209 {
210 if ($path === null) {
211 $path = $this->getAbsolutePath();
212 }
213 $pathSiteWithoutTrailingSlash = substr(PATH_site, 0, -1);
214 if (strpos($path, $pathSiteWithoutTrailingSlash, 0) !== 0) {
215 throw new Exception\InvalidArgumentException(
216 'PATH_site is not first part of given path',
217 1366398198
218 );
219 }
220 $relativePath = substr($path, strlen($pathSiteWithoutTrailingSlash), strlen($path));
221 // Add a forward slash again, so we don't end up with an empty string
222 if ($relativePath === '') {
223 $relativePath = '/';
224 }
225 return $relativePath;
226 }
227 }