1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
24: class IMP_Compose_Attachment_Storage_VfsLinked
25: extends IMP_Compose_Attachment_Storage
26: implements IMP_Compose_Attachment_Linked
27: {
28:
29: const METADATA_NAME = 'metadata';
30:
31:
32: const VFS_LINK_ATTACH_PATH = '.horde/imp/attachments';
33:
34: 35: 36: 37: 38:
39: protected $_md;
40:
41: 42: 43: 44: 45:
46: protected $_vfs;
47:
48: 49: 50: 51: 52:
53: protected $_vfspath;
54:
55: 56:
57: public function __construct($user, $id = null)
58: {
59: global $injector;
60:
61: parent::__construct($user, $id);
62:
63: $this->_vfs = $injector->getInstance('Horde_Core_Factory_Vfs')->create();
64: $this->_vfspath = self::VFS_LINK_ATTACH_PATH . '/'. $this->_user;
65: }
66:
67: 68:
69: protected function _read()
70: {
71: try {
72: if (method_exists($this->_vfs, 'readStream')) {
73: $stream = new Horde_Stream_Existing(array(
74: 'stream' => $this->_vfs->readStream($this->_vfspath, $this->_id)
75: ));
76: $stream->rewind();
77: } else {
78: $stream = new Horde_Stream_Temp();
79: $stream->add($this->_vfs->read($this->_vfspath, $this->_id), true);
80: }
81: return $stream;
82: } catch (Horde_Vfs_Exception $e) {
83: throw new IMP_Compose_Exception($e);
84: }
85: }
86:
87: 88:
89: protected function _write($filename, Horde_Mime_Part $part)
90: {
91: global $browser;
92:
93: try {
94: $this->_vfs->write(
95: $this->_vfspath,
96: $this->_id,
97: $filename,
98: true
99: );
100: } catch (Horde_Vfs_Exception $e) {
101: throw new IMP_Compose_Exception($e);
102: }
103:
104:
105: $type = $part->getType();
106: if ($browser->isBrowser('mozilla') &&
107: in_array(Horde_String::lower($type), array('application/java-archive', 'application/x-jar'))) {
108: $type = 'application/octet-stream';
109: }
110:
111: $md = $this->getMetadata();
112: $md->filename = $part->getName(true);
113: $md->time = time();
114: $md->type = $type;
115:
116: $this->saveMetadata($md);
117: }
118:
119: 120:
121: public function delete()
122: {
123: $this->_vfs->deleteFile($this->_vfspath, $this->_id);
124: }
125:
126: 127:
128: public function exists()
129: {
130: return $this->_vfs->exists($this->_vfspath, $this->_id);
131: }
132:
133: 134:
135: public function gc()
136: {
137: if (!($keep = IMP_Compose_LinkedAttachment::keepDate(true))) {
138: return;
139: }
140:
141: $changed = false;
142: $this->_getMetadata();
143:
144: foreach ($this->_md as $key => $val) {
145: $md = new IMP_Compose_Attachment_Linked_Metadata();
146: $md->data = $val;
147:
148: if ($md->time < $keep) {
149: try {
150: $this->_vfs->deleteFile($this->_vfspath, $key);
151: } catch (Exception $e) {}
152: unset($this->_md[$key]);
153: $changed = true;
154: }
155: }
156:
157: if ($changed) {
158: $this->_saveMetadata();
159: }
160: }
161:
162: 163:
164: public function getMetadata()
165: {
166: $this->_getMetadata();
167:
168: $md = new IMP_Compose_Attachment_Linked_Metadata();
169: if (isset($this->_id) && isset($this->_md[$this->_id])) {
170: $md->data = $this->_md[$this->_id];
171: }
172:
173: return $md;
174: }
175:
176: 177: 178:
179: protected function _getMetadata()
180: {
181: if (!isset($this->_md)) {
182: try {
183: $this->_md = json_decode($this->_vfs->read($this->_vfspath, self::METADATA_NAME), true);
184: } catch (Horde_Vfs_Exception $e) {}
185:
186: if (!is_array($this->_md)) {
187: $this->_md = array();
188: }
189: }
190: }
191:
192: 193:
194: public function saveMetadata($md = null)
195: {
196: if (!isset($this->_id)) {
197: return;
198: }
199:
200: $this->_getMetadata();
201:
202: if (is_null($md)) {
203: unset($this->_md[$this->_id]);
204: } else {
205: $this->_md[$this->_id] = $md->data;
206: }
207:
208: $this->_saveMetadata();
209: }
210:
211: 212: 213:
214: protected function _saveMetadata()
215: {
216: if (empty($this->_md)) {
217: $this->_vfs->deleteFile($this->_vfspath, self::METADATA_NAME);
218: } else {
219: $this->_vfs->writeData($this->_vfspath, self::METADATA_NAME, json_encode($this->_md), true);
220: }
221: }
222:
223: }
224: