PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backups, Restore, Migration & Clone / 4.9.4
WP STAGING – WordPress Backups, Restore, Migration & Clone v4.9.4
4.9.4 4.9.3 4.9.2 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 / Staging / Ajax / DirectoryChildren.php
wp-staging / Staging / Ajax Last commit date
Create 3 weeks ago Delete 1 month ago Reset 1 month ago Update 1 month ago AbstractAjaxPrepare.php 3 weeks ago Create.php 1 month ago Delete.php 1 year ago DirectoryChildren.php 2 weeks ago Listing.php 9 months ago Repair.php 7 months ago Reset.php 1 month ago Setup.php 1 month ago SizeCalculator.php 2 weeks ago StagingSiteDataChecker.php 4 months ago Update.php 1 month ago
DirectoryChildren.php
127 lines
1 <?php
2
3 namespace WPStaging\Staging\Ajax;
4
5 use InvalidArgumentException;
6 use Throwable;
7 use WPStaging\Framework\Adapter\Directory;
8 use WPStaging\Framework\Component\AbstractTemplateComponent;
9 use WPStaging\Framework\Facades\Sanitize;
10 use WPStaging\Framework\Filesystem\PathIdentifier;
11 use WPStaging\Framework\TemplateEngine\TemplateEngine;
12 use WPStaging\Staging\Service\AbstractStagingSetup;
13 use WPStaging\Staging\Service\DirectoryScanner;
14 use WPStaging\Staging\Sites;
15
16 /**
17 * Renders lazily requested directory children for staging operations.
18 */
19 class DirectoryChildren extends AbstractTemplateComponent
20 {
21 /** @var AbstractStagingSetup */
22 private $stagingSetup;
23
24 /** @var DirectoryScanner */
25 private $directoryScanner;
26
27 /** @var Directory */
28 private $directory;
29
30 /** @var Sites */
31 private $stagingSites;
32
33 public function __construct(
34 TemplateEngine $templateEngine,
35 AbstractStagingSetup $stagingSetup,
36 DirectoryScanner $directoryScanner,
37 Directory $directory,
38 Sites $stagingSites
39 ) {
40 parent::__construct($templateEngine);
41 $this->stagingSetup = $stagingSetup;
42 $this->directoryScanner = $directoryScanner;
43 $this->directory = $directory;
44 $this->stagingSites = $stagingSites;
45 }
46
47 /**
48 * @return void
49 */
50 public function ajaxRender()
51 {
52 if (!$this->canRenderAjax()) {
53 return;
54 }
55
56 try {
57 $jobType = isset($_POST['jobType']) ? Sanitize::sanitizeString($_POST['jobType']) : AbstractStagingSetup::JOB_NEW_STAGING_SITE;
58 $cloneId = isset($_POST['cloneId']) ? Sanitize::sanitizeString($_POST['cloneId']) : '';
59 $dirPath = isset($_POST['dirPath']) ? Sanitize::sanitizePath($_POST['dirPath']) : '';
60 $prefix = isset($_POST['prefix']) ? Sanitize::sanitizeString($_POST['prefix']) : '';
61 $parentChecked = isset($_POST['isChecked']) && Sanitize::sanitizeBool($_POST['isChecked']);
62 $forceDefault = isset($_POST['forceDefault']) && Sanitize::sanitizeBool($_POST['forceDefault']);
63
64 $this->setupScanner($jobType, $cloneId);
65 $basePath = $this->getBasePath($prefix);
66 $path = $this->resolvePathWithinBase($dirPath, $basePath);
67
68 $directories = $this->directoryScanner->scanDirectory($path, $basePath, $prefix);
69 $listing = $this->directoryScanner->directoryListing($directories, $parentChecked, $forceDefault);
70
71 wp_send_json_success(['directoryListing' => $listing]);
72 } catch (Throwable $e) {
73 wp_send_json_error(['message' => $e->getMessage()]);
74 }
75 }
76
77 private function setupScanner(string $jobType, string $cloneId)
78 {
79 if ($jobType === AbstractStagingSetup::JOB_UPDATE || $jobType === AbstractStagingSetup::JOB_RESET) {
80 if ($cloneId === '') {
81 throw new InvalidArgumentException('Invalid clone ID provided.');
82 }
83
84 $stagingSiteDto = $this->stagingSites->getStagingSiteDtoByCloneId($cloneId);
85 if ($jobType === AbstractStagingSetup::JOB_RESET) {
86 $this->stagingSetup->initResetJob($stagingSiteDto);
87 } else {
88 $this->stagingSetup->initUpdateJob($stagingSiteDto);
89 }
90 } else {
91 $this->stagingSetup->initNewStagingSite();
92 }
93
94 $this->directoryScanner->setStagingSetup($this->stagingSetup);
95 }
96
97 private function getBasePath(string $prefix): string
98 {
99 if ($prefix === PathIdentifier::IDENTIFIER_ABSPATH) {
100 return trailingslashit(wp_normalize_path($this->directory->getAbsPath()));
101 }
102
103 if ($prefix === PathIdentifier::IDENTIFIER_WP_CONTENT) {
104 return trailingslashit(wp_normalize_path($this->directory->getWpContentDirectory()));
105 }
106
107 throw new InvalidArgumentException('Invalid directory path identifier.');
108 }
109
110 private function resolvePathWithinBase(string $dirPath, string $basePath): string
111 {
112 $resolvedBase = realpath($basePath);
113 $resolvedPath = realpath($basePath . ltrim($dirPath, '/\\'));
114 if ($resolvedBase === false || $resolvedPath === false) {
115 throw new InvalidArgumentException('Invalid directory path.');
116 }
117
118 $resolvedBase = wp_normalize_path($resolvedBase);
119 $resolvedPath = wp_normalize_path($resolvedPath);
120 if ($resolvedPath !== $resolvedBase && strpos(trailingslashit($resolvedPath), trailingslashit($resolvedBase)) !== 0) {
121 throw new InvalidArgumentException('Directory path is outside the allowed base path.');
122 }
123
124 return $resolvedPath;
125 }
126 }
127