Files

146 lines
5.3 KiB
PHP

<?php
/**
* Nextcloud Bridge — File operations on same-server Nextcloud instance.
*/
namespace HermesAiBridge;
defined('ABSPATH') or die();
class NextcloudBridge {
protected $base_url;
protected $username;
protected $password;
protected $webdav_url;
public function __construct() {
$this->base_url = get_option('hermes_nextcloud_url', '');
$this->username = get_option('hermes_nextcloud_user', '');
$this->password = get_option('hermes_nextcloud_pass', '');
$this->webdav_url = rtrim($this->base_url, '/') . '/remote.php/dav/files/' . $this->username . '/';
}
/**
* List files in Nextcloud directory.
*/
public function list_files($path = '/') {
if (!$this->is_configured()) return new \WP_Error('not_configured', 'Nextcloud not configured');
$url = $this->webdav_url . ltrim($path, '/');
$response = $this->propfind($url);
if (is_wp_error($response)) return $response;
$files = [];
$dom = new \DOMDocument();
$dom->loadXML($response);
foreach ($dom->getElementsByTagNameNS('DAV:', 'response') as $node) {
$href = $node->getElementsByTagNameNS('DAV:', 'href')->item(0)->nodeValue ?? '';
if ($href === $this->webdav_url) continue; // skip root
$files[] = [
'path' => $href,
'name' => basename($href),
'size' => $node->getElementsByTagNameNS('DAV:', 'getcontentlength')->item(0)->nodeValue ?? 0,
'modified' => $node->getElementsByTagNameNS('DAV:', 'getlastmodified')->item(0)->nodeValue ?? '',
'type' => $node->getElementsByTagNameNS('DAV:', 'getcontenttype')->item(0)->nodeValue ?? 'directory',
];
}
return $files;
}
/**
* Upload a file to Nextcloud from WordPress Media Library.
*/
public function upload_from_media($attachment_id, $destination_path = '/') {
if (!$this->is_configured()) return new \WP_Error('not_configured', 'Nextcloud not configured');
$file_path = get_attached_file($attachment_id);
if (!$file_path || !file_exists($file_path)) {
return new \WP_Error('file_not_found', 'Attachment file not found on disk');
}
$filename = basename($file_path);
$dest_url = $this->webdav_url . ltrim($destination_path, '/') . '/' . $filename;
$response = wp_remote_request($dest_url, [
'method' => 'PUT',
'headers' => [
'Authorization' => 'Basic ' . base64_encode($this->username . ':' . $this->password),
'Content-Type' => get_post_mime_type($attachment_id) ?: 'application/octet-stream',
],
'body' => file_get_contents($file_path),
'timeout' => 60,
]);
if (is_wp_error($response)) return $response;
$status = wp_remote_retrieve_response_code($response);
if ($status < 200 || $status >= 300) {
return new \WP_Error('upload_failed', "WebDAV upload returned $status");
}
RestController::log('info', 'File uploaded to Nextcloud', ['file' => $filename, 'dest' => $dest_url]);
return ['success' => true, 'path' => $dest_url];
}
/**
* Download a file from Nextcloud into WordPress Media Library.
*/
public function import_to_media($nextcloud_path) {
if (!$this->is_configured()) return new \WP_Error('not_configured', 'Nextcloud not configured');
$url = $this->webdav_url . ltrim($nextcloud_path, '/');
$response = wp_remote_get($url, [
'headers' => [
'Authorization' => 'Basic ' . base64_encode($this->username . ':' . $this->password),
],
'timeout' => 60,
]);
if (is_wp_error($response)) return $response;
$body = wp_remote_retrieve_body($response);
$filename = basename($nextcloud_path);
$upload = wp_upload_bits($filename, null, $body);
if ($upload['error']) {
return new \WP_Error('upload_failed', $upload['error']);
}
$attachment = [
'post_mime_type' => wp_check_filetype($filename)['type'] ?: 'application/octet-stream',
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit',
'guid' => $upload['url'],
];
$attach_id = wp_insert_attachment($attachment, $upload['file']);
require_once ABSPATH . 'wp-admin/includes/image.php';
wp_generate_attachment_metadata($attach_id, $upload['file']);
RestController::log('info', 'File imported from Nextcloud', ['file' => $filename, 'attachment_id' => $attach_id]);
return ['success' => true, 'attachment_id' => $attach_id, 'url' => $upload['url']];
}
protected function propfind($url) {
$response = wp_remote_request($url, [
'method' => 'PROPFIND',
'headers' => [
'Authorization' => 'Basic ' . base64_encode($this->username . ':' . $this->password),
'Depth' => '1',
],
'timeout' => 30,
]);
if (is_wp_error($response)) return $response;
return wp_remote_retrieve_body($response);
}
protected function is_configured() {
return !empty($this->base_url) && !empty($this->username) && !empty($this->password);
}
}