1
0
mirror of https://github.com/owncloudarchive/contacts.git synced 2025-01-19 08:52:22 +01:00

More photo handling cleanups

This commit is contained in:
Thomas Tanghus 2014-03-20 21:53:13 +01:00
parent d9a1089c7d
commit 43e65fc817
5 changed files with 93 additions and 79 deletions

View File

@ -793,9 +793,9 @@ OC.Contacts = OC.Contacts || {};
$.when(this.storage.addContact(this.metadata.backend, this.metadata.parent)) $.when(this.storage.addContact(this.metadata.backend, this.metadata.parent))
.then(function(response) { .then(function(response) {
if(!response.error) { if(!response.error) {
self.id = String(response.data.metadata.id); self.id = String(response.metadata.id);
self.metadata = response.data.metadata; self.metadata = response.metadata;
self.data = response.data.data; self.data = response.data;
console.log('Contact.add, groupprops', self.groupprops); console.log('Contact.add, groupprops', self.groupprops);
if(self.groupprops && self.groupprops.groups.length > 0) { if(self.groupprops && self.groupprops.groups.length > 0) {
self._buildGroupSelect(self.groupprops.groups); self._buildGroupSelect(self.groupprops.groups);

View File

@ -32,6 +32,10 @@ OC.Contacts = OC.Contacts || {};
} }
} else { } else {
this.data = response.data || response; this.data = response.data || response;
// Kind of a hack
if (response.metadata) {
this.metadata = response.metadata;
}
} }
} }
}; };

View File

@ -400,6 +400,45 @@ class Contact extends VObject\VCard implements IPIMObject {
} }
} }
/**
* Set the contact photo.
*
* @param \OCP\Image $photo
*/
public function setPhoto(\OCP\Image $photo) {
// For vCard 3.0 the type must be e.g. JPEG or PNG
// For version 4.0 the full mimetype should be used.
// https://tools.ietf.org/html/rfc2426#section-3.1.4
if(strval($this->VERSION) === '4.0') {
$type = $photo->mimeType();
} else {
$type = explode('/', $photo->mimeType());
$type = strtoupper(array_pop($type));
}
if(isset($this->PHOTO)) {
$property = $this->PHOTO;
if(!$property) {
return false;
}
$property->setValue(strval($photo));
$property->parameters = array();
$property->parameters[]
= new \Sabre\VObject\Parameter('ENCODING', 'b');
$property->parameters[]
= new \Sabre\VObject\Parameter('TYPE', $photo->mimeType());
$this->PHOTO = $property;
} else {
$this->add('PHOTO',
strval($photo), array('ENCODING' => 'b',
'TYPE' => $type));
// TODO: Fix this hack
$this->setSaved(false);
}
return true;
}
/** /**
* Get a property index in the contact by the checksum of its serialized value * Get a property index in the contact by the checksum of its serialized value
* *

View File

@ -33,23 +33,14 @@ class ContactPhotoController extends Controller {
$addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']); $addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']);
$contact = $addressBook->getChild($params['contactId']); $contact = $addressBook->getChild($params['contactId']);
if(!$contact) { $tempPhoto = TemporaryPhoto::create(
$response = new JSONResponse(); $this->server,
$response->bailOut(App::$l10n->t('Couldn\'t find contact.')); TemporaryPhoto::PHOTO_CURRENT,
return $response; $contact
} );
$image = $tempPhoto->getPhoto();
$image = new \OCP\Image();
if (isset($contact->PHOTO) && $image->loadFromBase64((string)$contact->PHOTO)) {
// OK
$etag = md5($contact->PHOTO);
}
else
// Logo :-/
if(isset($contact->LOGO) && $image->loadFromBase64((string)$contact->LOGO)) {
// OK
$etag = md5($contact->LOGO);
}
if($image->valid()) { if($image->valid()) {
$response = new ImageResponse($image); $response = new ImageResponse($image);
$lastModified = $contact->lastModified(); $lastModified = $contact->lastModified();
@ -65,9 +56,7 @@ class ContactPhotoController extends Controller {
} }
return $response; return $response;
} else { } else {
$response = new JSONResponse(); throw new \Exception(App::$l10n->t('Error getting user photo'));
$response->bailOut(App::$l10n->t('Error getting user photo'));
return $response;
} }
} }
@ -81,7 +70,7 @@ class ContactPhotoController extends Controller {
$params = $this->request->urlParams; $params = $this->request->urlParams;
$response = new JSONResponse(); $response = new JSONResponse();
$tempPhoto = TemporaryPhoto::get( $tempPhoto = TemporaryPhoto::create(
$this->server, $this->server,
TemporaryPhoto::PHOTO_UPLOADED, TemporaryPhoto::PHOTO_UPLOADED,
$this->request $this->request
@ -111,7 +100,7 @@ class ContactPhotoController extends Controller {
$addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']); $addressBook = $this->app->getAddressBook($params['backend'], $params['addressBookId']);
$contact = $addressBook->getChild($params['contactId']); $contact = $addressBook->getChild($params['contactId']);
$tempPhoto = TemporaryPhoto::get( $tempPhoto = TemporaryPhoto::create(
$this->server, $this->server,
TemporaryPhoto::PHOTO_CURRENT, TemporaryPhoto::PHOTO_CURRENT,
$contact $contact
@ -142,7 +131,7 @@ class ContactPhotoController extends Controller {
$response->bailOut(App::$l10n->t('No photo path was submitted.')); $response->bailOut(App::$l10n->t('No photo path was submitted.'));
} }
$tempPhoto = TemporaryPhoto::get( $tempPhoto = TemporaryPhoto::create(
$this->server, $this->server,
TemporaryPhoto::PHOTO_FILESYSTEM, TemporaryPhoto::PHOTO_FILESYSTEM,
$this->request->get['path'] $this->request->get['path']
@ -167,8 +156,9 @@ class ContactPhotoController extends Controller {
$params = $this->request->urlParams; $params = $this->request->urlParams;
$tmpkey = $params['key']; $tmpkey = $params['key'];
$image = new \OCP\Image(); $tmpPhoto = new TemporaryPhoto($this->server, $tmpkey);
$image->loadFromData($this->server->getCache()->get($tmpkey)); $image = $tmpPhoto->getPhoto();
if($image->valid()) { if($image->valid()) {
$response = new ImageResponse($image); $response = new ImageResponse($image);
return $response; return $response;
@ -197,19 +187,10 @@ class ContactPhotoController extends Controller {
$response = new JSONResponse(); $response = new JSONResponse();
if(!$contact) { $tmpPhoto = new TemporaryPhoto($this->server, $tmpkey);
return $response->bailOut(App::$l10n->t('Couldn\'t find contact.')); $image = $tmpPhoto->getPhoto();
} if(!$image || !$image->valid()) {
return $response->bailOut(App::$l10n->t('Error loading image from cache'));
$data = $this->server->getCache()->get($tmpkey);
if(!$data) {
return $response->bailOut(App::$l10n->t('Image has been removed from cache'));
}
$image = new \OCP\Image();
if(!$image->loadFromData($data)) {
return $response->bailOut(App::$l10n->t('Error creating temporary image'));
} }
$w = ($w !== -1 ? $w : $image->width()); $w = ($w !== -1 ? $w : $image->width());
@ -219,36 +200,11 @@ class ContactPhotoController extends Controller {
return $response->bailOut(App::$l10n->t('Error cropping image')); return $response->bailOut(App::$l10n->t('Error cropping image'));
} }
// For vCard 3.0 the type must be e.g. JPEG or PNG if (!$contact->setPhoto($image)) {
// For version 4.0 the full mimetype should be used. $tmpPhoto->remove($tmpkey);
// https://tools.ietf.org/html/rfc2426#section-3.1.4 return $response->bailOut(App::$l10n->t('Error getting PHOTO property.'));
if(strval($contact->VERSION) === '4.0') {
$type = $image->mimeType();
} else {
$type = explode('/', $image->mimeType());
$type = strtoupper(array_pop($type));
}
if(isset($contact->PHOTO)) {
$property = $contact->PHOTO;
if(!$property) {
$this->server->getCache()->remove($tmpkey);
return $response->bailOut(App::$l10n
->t('Error getting PHOTO property.'));
}
$property->setValue(strval($image));
$property->parameters = array();
$property->parameters[]
= new \Sabre\VObject\Parameter('ENCODING', 'b');
$property->parameters[]
= new \Sabre\VObject\Parameter('TYPE', $image->mimeType());
$contact->PHOTO = $property;
} else {
$contact->add('PHOTO',
strval($image), array('ENCODING' => 'b',
'TYPE' => $type));
// TODO: Fix this hack
$contact->setSaved(false);
} }
if(!$contact->save()) { if(!$contact->save()) {
return $response->bailOut(App::$l10n->t('Error saving contact.')); return $response->bailOut(App::$l10n->t('Error saving contact.'));
} }
@ -268,7 +224,7 @@ class ContactPhotoController extends Controller {
) )
)); ));
$this->server->getCache()->remove($tmpkey); $tmpPhoto->remove($tmpkey);
return $response; return $response;
} }

View File

@ -25,9 +25,9 @@ namespace OCA\Contacts\Utils;
use OCP\Image; use OCP\Image;
/** /**
* This class is used for getting a contact photo for cropping. * This class is used for getting a temporary contact photo for cropping.
*/ */
abstract class TemporaryPhoto { class TemporaryPhoto {
const MAX_SIZE = 400; const MAX_SIZE = 400;
@ -82,33 +82,48 @@ abstract class TemporaryPhoto {
* Always call parents ctor: * Always call parents ctor:
* parent::__construct($server); * parent::__construct($server);
*/ */
public function __construct(\OCP\IServerContainer $server) { public function __construct(\OCP\IServerContainer $server, $key = null) {
$this->server = $server; $this->server = $server;
$this->key = $key;
if (!is_null($key)) {
$this->processImage();
}
} }
/** /**
* Returns an instance of a subclass of this class * Returns an instance of a subclass of this class
* *
* @param \OCP\IServerContainer $server * @param \OCP\IServerContainer $server
* @param int $type One of the pre-defined types. * @param int|null $type One of the pre-defined types.
* @param mixed $data Whatever data is needed to load the photo. * @param mixed|null $data Whatever data is needed to load the photo.
*/ */
public static function get(\OCP\IServerContainer $server, $type, $data) { public static function create(\OCP\IServerContainer $server, $type = null, $data = null) {
if (isset(self::$classMap[$type])) { if (isset(self::$classMap[$type])) {
return new self::$classMap[$type]($server, $data); return new self::$classMap[$type]($server, $data);
} else { } else {
// TODO: Return a "null object" return new self($data, $data);
return new self($data);
} }
} }
/**
* Remove a cached image by key.
*
* @param string $key
*/
public function remove($key) {
return $this->server->getCache()->remove($key);
}
/** /**
* Do what's needed to get the image from storage * Do what's needed to get the image from storage
* depending on the type. * depending on the type.
* After this method is called $this->image must hold an * After this method is called $this->image must hold an
* instance of \OCP\Image. * instance of \OCP\Image.
*/ */
protected abstract function processImage(); protected function processImage() {
$this->image = new \OCP\Image();
$this->image->loadFromData($this->server->getCache()->get($this->key));
}
/** /**
* Whether this image is valied * Whether this image is valied