diff --git a/setup/cli/modules/class.module.php b/setup/cli/modules/class.module.php index a1647ce3cac8d2be9a57e29ab0fe60fe1eb82ce5..b91b020eaeda7512bcd1fa439d6f91cea5047922 100644 --- a/setup/cli/modules/class.module.php +++ b/setup/cli/modules/class.module.php @@ -92,11 +92,10 @@ class Option { class OutputStream { var $stream; - function OutputStream() { - call_user_func_array(array($this, '__construct'), func_get_args()); - } function __construct($stream) { - $this->stream = fopen($stream, 'w'); + if (!($this->stream = fopen($stream, 'w'))) + throw new Exception(sprintf('%s: Cannot open for writing', + $stream)); } function write($what) { diff --git a/setup/cli/modules/file.php b/setup/cli/modules/file.php index 840b84053d9723ff1225b321e8fed37d0e0c6e63..2761ac46883b62cb9bb309c45870a2835dcb600b 100644 --- a/setup/cli/modules/file.php +++ b/setup/cli/modules/file.php @@ -12,6 +12,7 @@ class FileManager extends Module { 'list' => 'List files matching criteria', 'export' => 'Export files from the system', 'import' => 'Load files exported via `export`', + 'zip' => 'Create a zip file of the matching files', 'dump' => 'Dump file content to stdout', 'load' => 'Load file contents from stdin', 'migrate' => 'Migrate a file to another backend', @@ -210,6 +211,9 @@ class FileManager extends Module { foreach ($files as $m) { $f = AttachmentFile::lookup($m->id); + if ($options['verbose']) + $this->stderr->write($m->name."\n"); + // TODO: Log %attachment and %ticket_attachment entries $info = array('file' => $f->getInfo()); foreach ($m->tickets as $t) @@ -242,8 +246,8 @@ class FileManager extends Module { if (!$options['file'] || $options['file'] == '-') $options['file'] = 'php://stdin'; - if (!($stream = fopen($options['file'], 'wb'))) - $this->fail($options['file'].': Unable to open file for export stream'); + if (!($stream = fopen($options['file'], 'rb'))) + $this->fail($options['file'].': Unable to open import stream'); while (true) { // Read the file header @@ -381,13 +385,45 @@ class FileManager extends Module { } break; + case 'zip': + // Create a temporary ZIP file + $files = FileModel::objects(); + $this->_applyCriteria($options, $files); + if (!$options['file']) + $this->fail('Please specify zip file with `-f`'); + + $zip = new ZipArchive(); + if (true !== ($reason = $zip->open($options['file'], + ZipArchive::CREATE))) + $this->fail($reason.': Unable to create zip file'); + + foreach ($files as $m) { + $f = AttachmentFile::lookup($m->id); + if ($options['verbose']) + $this->stderr->write($m->name."\n"); + $name = Format::encode(sprintf( + '%d-%s', $f->getId(), $f->getName() + ), 'utf-8', 'cp437'); + $zip->addFromString($name, $f->getData()); + } + $zip->close(); + break; + case 'expunge': $files = FileModel::objects(); $this->_applyCriteria($options, $files); - foreach ($files as $f) { - $f->tickets->expunge(); - $f->unlink() && $f->delete(); + foreach ($files as $m) { + // Drop associated attachment links + $m->tickets->expunge(); + $f = AttachmentFile::lookup($m->id); + + // Drop file contents + if ($bk = $f->open()) + $bk->unlink(); + + // Drop file record + $f->delete(); } } }