c5f075e90132b504a8ce4ae9e8deb3ad67583bee
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / Classes / FolderStructure / LinkNode.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\Install\Status;
18
19 /**
20 * A link
21 */
22 class LinkNode extends AbstractNode implements NodeInterface {
23
24 /**
25 * @var string Optional link target
26 */
27 protected $target = '';
28
29 /**
30 * Implement constructor
31 *
32 * @param array $structure Structure array
33 * @param NodeInterface $parent Parent object
34 * @throws Exception\InvalidArgumentException
35 */
36 public function __construct(array $structure, NodeInterface $parent = NULL) {
37 if (is_null($parent)) {
38 throw new \TYPO3\CMS\Install\FolderStructure\Exception\InvalidArgumentException(
39 'Link node must have parent',
40 1380485700
41 );
42 }
43 $this->parent = $parent;
44
45 // Ensure name is a single segment, but not a path like foo/bar or an absolute path /foo
46 if (strstr($structure['name'], '/') !== FALSE) {
47 throw new \TYPO3\CMS\Install\FolderStructure\Exception\InvalidArgumentException(
48 'File name must not contain forward slash',
49 1380546061
50 );
51 }
52 $this->name = $structure['name'];
53
54 if (isset($structure['target']) && strlen($structure['target']) > 0) {
55 $this->target = $structure['target'];
56 }
57 }
58
59 /**
60 * Get own status
61 * Returns information status if running on Windows
62 * Returns OK status if is link and possible target is correct
63 * Else returns error (not fixable)
64 *
65 * @return array<\TYPO3\CMS\Install\Status\StatusInterface>
66 */
67 public function getStatus() {
68 if ($this->isWindowsOs()) {
69 $status = new Status\InfoStatus();
70 $status->setTitle($this->getRelativePathBelowSiteRoot() . ' should be a link, but this support is incomplete for Windows.');
71 $status->setMessage(
72 'This node is not handled for Windows OS and should be checked manually.'
73 );
74 return array($status);
75 }
76
77 if (!$this->exists()) {
78 $status = new Status\ErrorStatus();
79 $status->setTitle($this->getRelativePathBelowSiteRoot() . ' should be a link, but it does not exist');
80 $status->setMessage('Links cannot be fixed by this system');
81 return array($status);
82 }
83
84 if (!$this->isLink()) {
85 $status = new Status\WarningStatus();
86 $status->setTitle('Path ' . $this->getRelativePathBelowSiteRoot() . ' is not a link');
87 $type = @filetype($this->getAbsolutePath());
88 if ($type) {
89 $status->setMessage(
90 'The target ' . $this->getRelativePathBelowSiteRoot() . ' should be a link,' .
91 ' but is of type ' . $type . '. This cannot be fixed automatically. Please investigate.'
92 );
93 } else {
94 $status->setMessage(
95 'The target ' . $this->getRelativePathBelowSiteRoot() . ' should be a file,' .
96 ' but is of unknown type, probably because an upper level directory does not exist. Please investigate.'
97 );
98 }
99 return array($status);
100 }
101
102 if (!$this->isTargetCorrect()) {
103 $status = new Status\ErrorStatus();
104 $status->setTitle($this->getRelativePathBelowSiteRoot() . ' is a link, but link target is not as specified');
105 $status->setMessage(
106 'Link target should be ' . $this->getTarget() . ' but is ' . $this->getCurrentTarget()
107 );
108 return array($status);
109 }
110
111 $status = new Status\OkStatus();
112 $message = 'Is a link';
113 if ($this->getTarget() !== '') {
114 $message .= ' and correctly points to target ' . $this->getTarget();
115 }
116 $status->setTitle($this->getRelativePathBelowSiteRoot());
117 $status->setMessage($message);
118 return array($status);
119 }
120
121 /**
122 * Fix structure
123 *
124 * If there is nothing to fix, returns an empty array
125 *
126 * @return array<\TYPO3\CMS\Install\Status\StatusInterface>
127 */
128 public function fix() {
129 return array();
130 }
131
132 /**
133 * Get link target
134 *
135 * @return string Link target
136 */
137 protected function getTarget() {
138 return $this->target;
139 }
140
141 /**
142 * Find out if node is a link
143 *
144 * @throws Exception\InvalidArgumentException
145 * @return bool TRUE if node is a link
146 */
147 protected function isLink() {
148 if (!$this->exists()) {
149 throw new \TYPO3\CMS\Install\FolderStructure\Exception\InvalidArgumentException(
150 'Link does not exist',
151 1380556246
152 );
153 }
154 return @is_link($this->getAbsolutePath());
155 }
156
157 /**
158 * Checks if the real link target is identical to given target
159 *
160 * @throws Exception\InvalidArgumentException
161 * @return bool TRUE if target is correct
162 */
163 protected function isTargetCorrect() {
164 if (!$this->exists()) {
165 throw new \TYPO3\CMS\Install\FolderStructure\Exception\InvalidArgumentException(
166 'Link does not exist',
167 1380556245
168 );
169 }
170 if (!$this->isLink()) {
171 throw new \TYPO3\CMS\Install\FolderStructure\Exception\InvalidArgumentException(
172 'Node is not a link',
173 1380556247
174 );
175 }
176
177 $result = FALSE;
178 $expectedTarget = $this->getTarget();
179 if (empty($expectedTarget)) {
180 $result = TRUE;
181 } else {
182 $actualTarget = $this->getCurrentTarget();
183 if ($actualTarget === rtrim($expectedTarget, '/')) {
184 $result = TRUE;
185 }
186 }
187 return $result;
188 }
189
190 /**
191 * Return current target of link
192 *
193 * @return string target
194 */
195 protected function getCurrentTarget() {
196 return readlink($this->getAbsolutePath());
197 }
198
199 }