[FEATURE] Integrate preliminary PackageManager API
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Cache / Backend / ClassLoaderBackend.php
1 <?php
2 namespace TYPO3\CMS\Core\Cache\Backend;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2013 Thomas Maroschik <tmaroschik@dfau.de>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Core\Utility\GeneralUtility;
31 use TYPO3\CMS\Core\Utility\PathUtility;
32
33 /**
34 * A caching backend customized explicitly for the class loader.
35 * This backend is NOT public API!
36 *
37 * @internal
38 */
39 class ClassLoaderBackend extends SimpleFileBackend {
40
41 /**
42 * Set a class loader cache content
43 *
44 * @TODO: Rename method
45 * @param string $entryIdentifier
46 * @param string $filePath
47 * @throws \InvalidArgumentException
48 * @internal This is not an API method
49 */
50 public function setLinkToPhpFile($entryIdentifier, $filePath) {
51 if ($entryIdentifier === '') {
52 throw new \InvalidArgumentException('The specified entry identifier must not be empty.', 1364205170);
53 }
54 if (!@file_exists($filePath)) {
55 throw new \InvalidArgumentException('The specified file path (' . $filePath . ') must exist.', 1364205235);
56 }
57 if (strtolower(substr($filePath, -3)) !== 'php') {
58 throw new \InvalidArgumentException('The specified file (' . $filePath . ') must be a php file.', 1364205377);
59 }
60 if ($entryIdentifier !== basename($entryIdentifier)) {
61 throw new \InvalidArgumentException('The specified entry identifier (' . $entryIdentifier . ') must not contain a path segment.', 1364205166);
62 }
63 if ($filePath[0] === '/' && \TYPO3\CMS\Core\Utility\GeneralUtility::isAllowedAbsPath($filePath)) {
64 // Make relative if absolute to prevent wrong entries if the whole installation is moved or copied
65 $filePath = \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath($this->cacheDirectory, dirname($filePath)) . basename($filePath);
66 }
67 if ($filePath[0] === '/') {
68 $this->set($entryIdentifier, '<?php require \'' . $filePath . '\';');
69 } else {
70 $this->set($entryIdentifier, '<?php require __DIR__ . \'/' . $filePath . '\';');
71 }
72 }
73
74 /**
75 * Used to set alias for class
76 *
77 * @TODO: Rename method
78 * @param string $entryIdentifier
79 * @param string $otherEntryIdentifier
80 * @internal
81 */
82 public function setLinkToOtherCacheEntry($entryIdentifier, $otherEntryIdentifier) {
83 $otherCacheEntryPathAndFilename = $this->cacheDirectory . $otherEntryIdentifier . $this->cacheEntryFileExtension;
84 $this->setLinkToPhpFile($entryIdentifier, $otherCacheEntryPathAndFilename);
85 }
86
87 /**
88 * Loads data from a cache file.
89 *
90 * @param string $entryIdentifier An identifier which describes the cache entry to load
91 * @return mixed The cache entry's content as a string or FALSE if the cache entry could not be loaded
92 * @throws \InvalidArgumentException If identifier is invalid
93 * @internal
94 */
95 public function get($entryIdentifier) {
96 if ($entryIdentifier !== basename($entryIdentifier)) {
97 throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756877);
98 }
99 $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
100 if (!@file_exists($pathAndFilename)) {
101 return FALSE;
102 }
103 return file_get_contents($pathAndFilename);
104 }
105
106 /**
107 * Retrieves the target of the a linked cache entry
108 *
109 * @TODO: Rename method
110 * @param string $entryIdentifier
111 * @return bool|string
112 * @internal
113 */
114 public function getTargetOfLinkedCacheEntry($entryIdentifier) {
115 $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
116 if (@file_exists($pathAndFilename)) {
117 // If not a link
118 $fileContent = file_get_contents($pathAndFilename);
119 $pattern = "!^\<\?php require ((__DIR__) \. )?'([\/\.\_a-z0-9]+)';!i";
120 $matches = array();
121 if (preg_match($pattern, $fileContent, $matches) !== FALSE) {
122 if (!empty($matches[3])) {
123 $targetPath = $matches[3];
124 if (!empty($matches[2]) && $matches[2] == '__DIR__') {
125 $targetPath = dirname($pathAndFilename) . $targetPath;
126 }
127 return \TYPO3\CMS\Core\Utility\PathUtility::getRelativePath($this->cacheDirectory, dirname($targetPath)) . basename($targetPath);
128 }
129 }
130 }
131 return FALSE;
132 }
133
134 /**
135 * Checks if a cache entry with the specified identifier exists.
136 *
137 * @param string $entryIdentifier
138 * @return boolean TRUE if such an entry exists, FALSE if not
139 * @throws \InvalidArgumentException
140 * @internal
141 */
142 public function has($entryIdentifier) {
143 if ($entryIdentifier !== basename($entryIdentifier)) {
144 throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1334756878);
145 }
146 $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
147 return @file_exists($pathAndFilename);
148 }
149
150 /**
151 * Checks if the given cache entry files are still valid or if their
152 * lifetime has exceeded.
153 *
154 * @param string $cacheEntryPathAndFilename
155 * @return boolean
156 * @internal
157 */
158 protected function isCacheFileExpired($cacheEntryPathAndFilename) {
159 return @file_exists($cacheEntryPathAndFilename) === FALSE;
160 }
161
162 /**
163 * Tries to find the cache entry for the specified identifier.
164 *
165 * @TODO: This methods is implemented in simple, file and this backend, but never called?
166 * @param string $entryIdentifier The cache entry identifier
167 * @return mixed The file names (including path) as an array if one or more entries could be found, otherwise FALSE
168 */
169 protected function findCacheFilesByIdentifier($entryIdentifier) {
170 $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
171 return @file_exists($pathAndFilename) ? array($pathAndFilename) : FALSE;
172 }
173
174 /**
175 * Loads PHP code from the cache and require_onces it right away.
176 *
177 * @param string $entryIdentifier An identifier which describes the cache entry to load
178 * @return mixed Potential return value from the include operation
179 * @throws \InvalidArgumentException
180 * @internal
181 */
182 public function requireOnce($entryIdentifier) {
183 $pathAndFilename = $this->cacheDirectory . $entryIdentifier . $this->cacheEntryFileExtension;
184 if ($entryIdentifier !== basename($entryIdentifier)) {
185 throw new \InvalidArgumentException('The specified entry identifier must not contain a path segment.', 1282073036);
186 }
187 return @file_exists($pathAndFilename) ? require_once $pathAndFilename : FALSE;
188 }
189
190 }