PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 3.8.0
WP STAGING – WordPress Backup, Restore, Migration & Clone v3.8.0
4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Filesystem / PathIdentifier.php
wp-staging / Framework / Filesystem Last commit date
Filters 2 years ago Scanning 5 years ago DebugLogReader.php 2 years ago DirectoryListing.php 2 years ago DiskWriteCheck.php 3 years ago FileObject.php 2 years ago Filesystem.php 2 years ago FilesystemExceptions.php 5 years ago FilterableDirectoryIterator.php 2 years ago LogCleanup.php 2 years ago LogFiles.php 2 years ago MissingFileException.php 3 years ago OPcache.php 2 years ago PathChecker.php 2 years ago PathIdentifier.php 2 years ago Permissions.php 5 years ago WpUploadsFolderSymlinker.php 4 years ago
PathIdentifier.php
205 lines
1 <?php
2
3 namespace WPStaging\Framework\Filesystem;
4
5 use WPStaging\Framework\Adapter\Directory;
6
7 /**
8 * This class is used to shorten the full file path
9 * to reduce the overall file size of the backup file.
10 *
11 * A file like wp-content/uploads/wp-staging-pro/wp-staging-pro.zip turn into
12 * wpstg_p_/wp-staging-pro/wp-staging.zip
13 *
14 * @todo rename this class to PathShortener
15 */
16
17 class PathIdentifier
18 {
19 /** @var string */
20 const IDENTIFIER_ABSPATH = 'wpstg_a_';
21
22 /** @var string */
23 const IDENTIFIER_WP_CONTENT = 'wpstg_c_';
24
25 /** @var string */
26 const IDENTIFIER_PLUGINS = 'wpstg_p_';
27
28 /** @var string */
29 const IDENTIFIER_THEMES = 'wpstg_t_';
30
31 /** @var string */
32 const IDENTIFIER_MUPLUGINS = 'wpstg_m_';
33
34 /** @var string */
35 const IDENTIFIER_UPLOADS = 'wpstg_u_';
36
37 /** @var string */
38 const IDENTIFIER_LANG = 'wpstg_l_';
39
40 /**
41 * @var string The identifier of the last match.
42 * We will try to match the path/identifier of the next item starting from this one. It's a form of cache,
43 * making it more efficient to transform long lists of similar paths.
44 */
45 protected $lastIdentifier;
46
47 /** @var Directory */
48 protected $directory;
49
50 public function __construct(Directory $directory)
51 {
52 $this->directory = $directory;
53 }
54
55 /** @var string */
56 public function getBackupDirectory()
57 {
58 return $this->directory->getBackupDirectory();
59 }
60
61 /**
62 * Convert an absolute file path of a file into an abbreviated path.
63 *
64 * E.g.:
65 *
66 * /var/www/single/wp-content/plugins/index.php => wpstg_p_index.php
67 * /var/www/single/wp-content/mu-plugins/index.php => wpstg_m_index.php
68 * /var/www/single/wp-content/uploads/2019/image.png => wpstg_c_uploads/2019/image.png
69 * /var/www/single/wp-content/themes/twentytwentyone/index.php => wpstg_t_twentytwentyone/index.php
70 *
71 * @param string $path /var/www/single/wp-content/plugins/index.php
72 *
73 * @return string wpstg_p_index.php
74 */
75 public function transformPathToIdentifiable($path)
76 {
77 // Start looking from the same placeholder as the last item, unless it was wp-content, which would cause false-positives.
78 if (isset($this->lastIdentifier) && $this->lastIdentifier !== self::IDENTIFIER_WP_CONTENT) {
79 $basePath = $this->getIdentifierPath($this->lastIdentifier);
80
81 // Early bail: This item has the same type as the previous one.
82 if (strpos($path, $basePath) === 0) {
83 return $this->lastIdentifier . substr($path, strlen($basePath));
84 }
85 }
86
87 // Uploads are usually the largest folders, so let's start with them.
88 if (strpos($path, $this->directory->getUploadsDirectory()) === 0) {
89 $this->lastIdentifier = self::IDENTIFIER_UPLOADS;
90
91 return $this->lastIdentifier . substr($path, strlen($this->directory->getUploadsDirectory()));
92 }
93
94 if ($this->directory->getPluginUploadsDirectory() !== $this->directory->getUploadsDirectory()) {
95 if (strpos($path, $this->directory->getPluginUploadsDirectory()) === 0) {
96 $this->lastIdentifier = self::IDENTIFIER_UPLOADS;
97
98 return $this->lastIdentifier . substr($path, strlen($this->directory->getPluginUploadsDirectory()));
99 }
100 }
101
102 if (strpos($path, $this->directory->getPluginsDirectory()) === 0) {
103 $this->lastIdentifier = self::IDENTIFIER_PLUGINS;
104
105 return $this->lastIdentifier . substr($path, strlen($this->directory->getPluginsDirectory()));
106 }
107
108 foreach ($this->directory->getAllThemesDirectories() as $themesDirectory) {
109 if (strpos($path, $themesDirectory) === 0) {
110 $this->lastIdentifier = self::IDENTIFIER_THEMES;
111
112 return $this->lastIdentifier . substr($path, strlen($themesDirectory));
113 }
114 }
115
116 if (strpos($path, $this->directory->getMuPluginsDirectory()) === 0) {
117 $this->lastIdentifier = self::IDENTIFIER_MUPLUGINS;
118
119 return $this->lastIdentifier . substr($path, strlen($this->directory->getMuPluginsDirectory()));
120 }
121
122 if (strpos($path, $this->directory->getLangsDirectory()) === 0) {
123 $this->lastIdentifier = self::IDENTIFIER_LANG;
124
125 return $this->lastIdentifier . substr($path, strlen($this->directory->getLangsDirectory()));
126 }
127
128 if (strpos($path, $this->directory->getWpContentDirectory()) === 0) {
129 $this->lastIdentifier = self::IDENTIFIER_WP_CONTENT;
130
131 return $this->lastIdentifier . substr($path, strlen($this->directory->getWpContentDirectory()));
132 }
133
134 if (strpos($path, $this->directory->getAbspath()) === 0) {
135 $this->lastIdentifier = self::IDENTIFIER_ABSPATH;
136
137 return $this->lastIdentifier . substr($path, strlen($this->directory->getAbspath()));
138 }
139
140 // This should never happen on Backups, as we only scan the folders above explicitly and don't follow links.
141 throw new \RuntimeException("Unknown entity type for path: $path");
142 }
143
144 /**
145 * @param string $path wpstg_p_index.php
146 *
147 * @return string /var/www/single/wp-content/plugins/index.php
148 */
149 public function transformIdentifiableToPath($path)
150 {
151 $identifier = $this->getIdentifierFromPath($path);
152 $pathWithoutIdentifier = $this->getPathWithoutIdentifier($path);
153
154 return $this->getIdentifierPath($identifier) . $pathWithoutIdentifier;
155 }
156
157 /**
158 * @param string $path wpstg_p_index.php
159 *
160 * @return string index.php
161 */
162 public function getPathWithoutIdentifier($path)
163 {
164 return substr($path, 8);
165 }
166
167 /**
168 * @param string $path wpstg_p_index.php
169 *
170 * @return string wpstg_p_
171 */
172 public function getIdentifierFromPath($path)
173 {
174 return substr($path, 0, 8);
175 }
176
177 /**
178 * @param string $identifier wpstg_p_
179 *
180 * @return string /var/www/single/wp-content/plugins/
181 */
182 protected function getIdentifierPath($identifier)
183 {
184 // It is crucial that generic paths are placed last in this list. Eg: wp-content directory must be last.
185 switch ($identifier) :
186 case self::IDENTIFIER_ABSPATH:
187 return $this->directory->getAbspath();
188 case self::IDENTIFIER_UPLOADS:
189 return $this->directory->getUploadsDirectory();
190 case self::IDENTIFIER_PLUGINS:
191 return $this->directory->getPluginsDirectory();
192 case self::IDENTIFIER_THEMES:
193 return $this->directory->getActiveThemeParentDirectory();
194 case self::IDENTIFIER_MUPLUGINS:
195 return $this->directory->getMuPluginsDirectory();
196 case self::IDENTIFIER_LANG:
197 return $this->directory->getLangsDirectory();
198 case self::IDENTIFIER_WP_CONTENT:
199 return $this->directory->getWpContentDirectory();
200 default:
201 throw new \UnexpectedValueException("Could not find a path for the placeholder: $identifier");
202 endswitch;
203 }
204 }
205