-
Identify the HTTP verb and response shape for the new operation:
- GET (read body): use
CURLOPT_HTTPGET => true
- GET (headers only): add
CURLOPT_HEADER => true, CURLOPT_NOBODY => true
- PUT (create/update): use
CURLOPT_CUSTOMREQUEST => 'PUT'
- DELETE: use
CURLOPT_CUSTOMREQUEST => 'DELETE'
- Response types seen in the codebase: raw string, header-parsed array, or
json_decode()
Verify: confirm which verb and response shape match the OpenStack Swift API docs for this operation.
-
Build the $options array using this exact structure — always include all three required keys:
$options = [
CURLOPT_HTTPHEADER => ['X-Auth-Token:'.$this->storage_token],
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_SSL_VERIFYPEER => false,
];
Add verb-specific keys after the three required ones:
- For GET body: prepend
CURLOPT_HTTPGET => true
- For GET headers: prepend
CURLOPT_HEADER => true, CURLOPT_NOBODY => true
- For PUT/DELETE: append
CURLOPT_CUSTOMREQUEST => 'PUT' or 'DELETE'
- For extra headers (e.g. ACL, ETag): append to the
CURLOPT_HTTPHEADER array: $options[CURLOPT_HTTPHEADER][] = 'Header-Name: '.$value;
Verify: every $options array in the method has CURLOPT_HTTPHEADER, CURLOPT_SSL_VERIFYHOST, and CURLOPT_SSL_VERIFYPEER.
-
Build the URL by concatenating $this->storage_url and the path components:
$url = $this->storage_url.'/'.$container;
$url = $this->storage_url.'/'.$container.'/'.$object;
$url = $this->storage_url.'/'.$container.'?marker='.$marker;
Verify: no trailing / is added unless the Swift API requires it.
-
Call getcurlpage() and handle the response based on step 1's response shape:
Raw string (e.g. download, ls, upload, delete):
$response = getcurlpage($url, '', $options);
return $response;
Header-parsed array (e.g. usage, acl) — filter out noise headers:
$response = getcurlpage($url, '', $options);
preg_match_all('/^(.*): (.*)$/m', $response, $matches);
$response = [];
foreach ($matches[1] as $idx => $key) {
if (!in_array($key, ['Accept-Ranges', 'X-Trans-Id', 'Date'])) {
$response[$key] = trim($matches[2][$idx]);
}
}
return $response;
JSON (e.g. list_accounts, list_account, list_user) — uses $this->auth_url not $this->storage_url:
$response = getcurlpage($this->auth_url.$path, $this->args, $this->options);
return json_decode($response, true);
Paginated listing (e.g. ls) — loop while response has 10 000 entries:
$response = trim(getcurlpage($url, '', $options));
$return = $response;
$lines = explode("\n", $response);
while (count($lines) == 10000) {
$response = trim(getcurlpage($url.'?marker='.$lines[9999], '', $options));
$return .= "\n".$response;
$lines = explode("\n", $response);
}
return $return;
-
Add a PHPDoc block above the method using the style from existing methods:
Verify: @param types match PHP primitives only (string, bool, int); @return matches actual return type.
-
Add a method-signature test in tests/SwiftTest.php following the reflection pattern used for existing methods:
public function testMyNewMethodSignature(): void
{
$ref = new ReflectionClass(Swift::class);
$method = $ref->getMethod('my_new_method');
$params = $method->getParameters();
$this->assertTrue($method->isPublic());
$this->assertFalse($method->isStatic());
$this->assertCount(2, $params);
$this->assertSame('container', $params[0]->getName());
$this->assertFalse($params[0]->isDefaultValueAvailable());
}
Also add the new method name to the $expected array in testExpectedPublicMethodsExist().
Verify: run vendor/bin/phpunit tests/SwiftTest.php — all tests pass.
-
getcurlpage() is undefined at runtime: You are running the method outside the MyAdmin environment. The function is defined in include/functions.inc.php. In tests, it is stubbed in tests/bootstrap.php — ensure vendor/bin/phpunit is run with the phpunit.xml.dist config (it sets the bootstrap automatically).
-
SSL errors / empty response from getcurlpage(): Missing CURLOPT_SSL_VERIFYHOST => false or CURLOPT_SSL_VERIFYPEER => false in $options. Check every key in the array — both must be present.
-
X-Auth-Token rejected (401): authenticate() was not called before the method, so $this->storage_token is null. Call $sw->authenticate() first and verify it returns a non-false value.
-
Header-parsed response returns empty array: The preg_match_all pattern /^(.*): (.*)$/m requires the response to include headers (CURLOPT_HEADER => true). If you omitted that flag and only get a body, add it to the $options array.
-
testExpectedPublicMethodsExist fails after adding your method: You added the method to src/Swift.php but forgot to add its name to the $expected array in tests/SwiftTest.php:452. Add the method name string there.
-
testPrivatePropertyCount fails: You added a new property to the class. Update the assertion in tests/SwiftTest.php:517 from assertCount(8, ...) to the new count.