Skip to content

Commit 4c96a7b

Browse files
committed
internal: import WIP
1 parent cc11f8a commit 4c96a7b

10 files changed

Lines changed: 891 additions & 0 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
.phpunit.cache/
3+
composer.lock

behat.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
default:
2+
suites:
3+
default:
4+
contexts:
5+
- WP_CLI\Tests\Context\FeatureContext
6+
paths:
7+
- features

composer.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"name": "built-fast/wp-orphanage",
3+
"description": "Detect and report orphaned files in WordPress uploads directories.",
4+
"type": "wp-cli-package",
5+
"license": "MIT",
6+
"require": {
7+
"php": ">=8.1",
8+
"wp-cli/wp-cli": "^2.12"
9+
},
10+
"require-dev": {
11+
"wp-cli/wp-cli-tests": "^5",
12+
"phpunit/phpunit": "^11.0 || ^12.0"
13+
},
14+
"config": {
15+
"process-timeout": 7200,
16+
"sort-packages": true,
17+
"allow-plugins": {
18+
"dealerdirect/phpcodesniffer-composer-installer": true,
19+
"johnpbloch/wordpress-core-installer": true,
20+
"phpstan/extension-installer": true
21+
},
22+
"lock": false
23+
},
24+
"extra": {
25+
"commands": [
26+
"media find-orphans"
27+
]
28+
},
29+
"autoload": {
30+
"psr-4": {
31+
"WpOrphanage\\": "src/"
32+
},
33+
"files": [
34+
"wp-orphanage-command.php"
35+
]
36+
},
37+
"autoload-dev": {
38+
"psr-4": {
39+
"WpOrphanage\\Tests\\": "tests/"
40+
}
41+
},
42+
"minimum-stability": "dev",
43+
"prefer-stable": true,
44+
"scripts": {
45+
"behat": "run-behat-tests",
46+
"behat-rerun": "rerun-behat-tests",
47+
"lint": "run-linter-tests",
48+
"phpunit": "run-php-unit-tests",
49+
"prepare-tests": "install-package-tests",
50+
"test": [
51+
"@lint",
52+
"@phpunit",
53+
"@behat"
54+
]
55+
}
56+
}

features/find-orphans.feature

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
Feature: Find orphaned files in WordPress uploads
2+
3+
Background:
4+
Given a WP install
5+
6+
Scenario: Reports no orphans on a clean install
7+
When I run `wp media find-orphans --format=json`
8+
Then STDOUT should be JSON containing:
9+
"""
10+
{"status":"completed","orphan_count":0}
11+
"""
12+
And the return code should be 0
13+
14+
Scenario: Reports no orphans on a clean install with table format
15+
When I run `wp media find-orphans --format=table`
16+
Then STDOUT should contain:
17+
"""
18+
No orphaned files found.
19+
"""
20+
And the return code should be 0
21+
22+
Scenario: Detects orphaned files not tracked in the database
23+
Given a WP install
24+
25+
# Create a real attachment via WP-CLI so the DB has records.
26+
When I run `wp media import 'https://via.placeholder.com/300.png' --title="Known Image" --porcelain`
27+
Then save STDOUT as {ATTACHMENT_ID}
28+
29+
# Plant orphan files directly in uploads.
30+
Given a wp-content/uploads/2024/03/orphan-image.jpg file:
31+
"""
32+
fake image content
33+
"""
34+
And a wp-content/uploads/2024/03/orphan-thumb-150x150.jpg file:
35+
"""
36+
fake thumb content
37+
"""
38+
39+
When I run `wp media find-orphans --format=json`
40+
Then STDOUT should be JSON containing:
41+
"""
42+
{"status":"completed"}
43+
"""
44+
And STDOUT should contain:
45+
"""
46+
orphan-image.jpg
47+
"""
48+
And STDOUT should contain:
49+
"""
50+
orphan-thumb-150x150.jpg
51+
"""
52+
And the return code should be 0
53+
54+
Scenario: Excludes cache directory by default
55+
Given a wp-content/uploads/cache/object-cache.tmp file:
56+
"""
57+
cached data
58+
"""
59+
And a wp-content/uploads/2024/03/orphan.jpg file:
60+
"""
61+
fake image
62+
"""
63+
64+
When I run `wp media find-orphans --format=json`
65+
Then STDOUT should contain:
66+
"""
67+
"skipped_dirs":["cache"]
68+
"""
69+
And STDOUT should contain:
70+
"""
71+
orphan.jpg
72+
"""
73+
And STDOUT should not contain:
74+
"""
75+
object-cache.tmp
76+
"""
77+
78+
Scenario: Custom exclude directories
79+
Given a wp-content/uploads/woocommerce_uploads/product.zip file:
80+
"""
81+
product data
82+
"""
83+
And a wp-content/uploads/2024/03/orphan.jpg file:
84+
"""
85+
fake image
86+
"""
87+
88+
When I run `wp media find-orphans --exclude-dirs=cache,woocommerce_uploads --format=json`
89+
Then STDOUT should not contain:
90+
"""
91+
product.zip
92+
"""
93+
And STDOUT should contain:
94+
"""
95+
orphan.jpg
96+
"""
97+
98+
Scenario: Excludes index.php and .htaccess files
99+
Given a wp-content/uploads/index.php file:
100+
"""
101+
<?php // Silence is golden.
102+
"""
103+
And a wp-content/uploads/2024/03/index.php file:
104+
"""
105+
<?php // Silence is golden.
106+
"""
107+
And a wp-content/uploads/.htaccess file:
108+
"""
109+
deny from all
110+
"""
111+
And a wp-content/uploads/2024/03/orphan.jpg file:
112+
"""
113+
fake image
114+
"""
115+
116+
When I run `wp media find-orphans --format=json`
117+
Then STDOUT should contain:
118+
"""
119+
orphan.jpg
120+
"""
121+
And STDOUT should not contain:
122+
"""
123+
index.php
124+
"""
125+
126+
Scenario: Finds orphans from a file list (S3 mode)
127+
# Import an image so DB has a known attachment.
128+
When I run `wp media import 'https://via.placeholder.com/300.png' --title="Known" --porcelain`
129+
Then save STDOUT as {ATTACHMENT_ID}
130+
131+
# Get the attached file path so we can build the file list.
132+
When I run `wp post meta get {ATTACHMENT_ID} _wp_attached_file`
133+
Then save STDOUT as {ATTACHED_FILE}
134+
135+
# Create a file list with the known file + an orphan.
136+
Given a /tmp/test-file-list.txt file:
137+
"""
138+
{ATTACHED_FILE}
139+
2024/03/s3-orphan.jpg
140+
2024/03/s3-orphan-150x150.jpg
141+
"""
142+
143+
When I run `wp media find-orphans --file-list=/tmp/test-file-list.txt --format=json`
144+
Then STDOUT should be JSON containing:
145+
"""
146+
{"status":"completed","source":"s3"}
147+
"""
148+
And STDOUT should contain:
149+
"""
150+
s3-orphan.jpg
151+
"""
152+
And the return code should be 0
153+
154+
Scenario: Reports known file count correctly
155+
When I run `wp media import 'https://via.placeholder.com/300.png' --title="Image 1" --porcelain`
156+
And I run `wp media import 'https://via.placeholder.com/600.png' --title="Image 2" --porcelain`
157+
158+
When I run `wp media find-orphans --format=json`
159+
Then STDOUT should be JSON containing:
160+
"""
161+
{"status":"completed"}
162+
"""
163+
# known_files should be > 0 (exact count depends on WP thumbnail config).
164+
And STDOUT should not contain:
165+
"""
166+
"known_files":0
167+
"""
168+
And the return code should be 0

phpunit.xml.dist

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/12.0/phpunit.xsd"
5+
bootstrap="tests/bootstrap.php"
6+
colors="true"
7+
cacheDirectory=".phpunit.cache"
8+
>
9+
<testsuites>
10+
<testsuite name="unit">
11+
<directory suffix="Test.php">tests</directory>
12+
</testsuite>
13+
</testsuites>
14+
<source>
15+
<include>
16+
<directory suffix=".php">src</directory>
17+
</include>
18+
</source>
19+
</phpunit>

0 commit comments

Comments
 (0)