$result = $this->_doImport(array(), $definition);
$this->assertEquals(1, $result['updatecount'], 'should have updated 1 contact');
- $this->assertEquals(0, $result['totalcount']);
+ $this->assertEquals(0, $result['totalcount'], 'should have imported 0 records: ' . print_r($result['results']->toArray(), true));
$this->assertEquals(0, $result['failcount']);
$this->assertEquals('joerg@home.com', $result['results'][0]->email_home, 'duplicates resolving did not work: ' . print_r($result['results']->toArray(), true));
$this->assertEquals('Jörg', $result['results'][0]->n_given, 'wrong encoding: ' . print_r($result['results']->toArray(), true));
{
$this->_createCustomField('customfield1');
$this->_createCustomField('customfield2');
+ // empty values: should not trigger record updates
+ $this->_createCustomField('customfield3');
$result = $this->testImportDuplicateResolve(/* $withCustomfields */ true);
$this->assertEquals('Straßbough', $result['results'][1]['adr_one_locality'],
'should have changed the locality of contact #2: ' . print_r($result['results'][1]->toArray(), true));
$this->assertEquals('Gartencenter Röhr & Vater', $result['results'][3]['n_family']);
-
- // TODO this should be researched, imho the relation should not trigger an update of the record
-// $this->assertEquals(1, $result['results'][3]['seq'], 'Wolfer has been updated - relations changed');
-// $this->assertEquals('Weixdorf DD', $result['results'][0]['adr_one_locality'], 'locality should persist');
-// $this->assertEquals('Gartencenter Röhr & Vater', $result['results'][4]['n_fileas']);
-// $this->assertEquals('Straßback', $result['results'][5]['adr_one_locality']);
}
public function testSplitField()
<source>customfield2</source>
<destination>customfield2</destination>
</field>
+ <field>
+ <source>customfield3</source>
+ <destination>customfield3</destination>
+ </field>
</mapping>
</config>
\ No newline at end of file
-"org_name","salutation","title","n_given","n_family","role","adr_one_street","adr_one_postalcode","adr_one_locality","adr_one_countryname","tel_work","tel_fax","tel_cell","email","tel_fax_home","tel_home","email_home","customfield1","customfield2"\r
-"effect gmbh","Herr","Dr.","Jörg","Heinz","Geschäftsführer","Str. 25","21222","Köln","DE","022324321","","","joerg.heinz@honk.com","","","","cf1","cf2"\r
-"effect gmbh","Herr","","Hans","Fritz","Technical Lead","Str. 25","21222","Köln","DE","022324321","","","hans.fritz@honk.com","","","","cf1","cf2"\r
+"org_name","salutation","title","n_given","n_family","role","adr_one_street","adr_one_postalcode","adr_one_locality","adr_one_countryname","tel_work","tel_fax","tel_cell","email","tel_fax_home","tel_home","email_home","customfield1","customfield2","customfield3"
+"effect gmbh","Herr","Dr.","Jörg","Heinz","Geschäftsführer","Str. 25","21222","Köln","DE","022324321","","","joerg.heinz@honk.com","","","","cf1","cf2",""
+"effect gmbh","Herr","","Hans","Fritz","Technical Lead","Str. 25","21222","Köln","DE","022324321","","","hans.fritz@honk.com","","","","cf1","cf2",""
-"org_name","salutation","title","n_given","n_family","role","adr_one_street","adr_one_postalcode","adr_one_locality","adr_one_countryname","tel_work","tel_fax","tel_cell","email","tel_fax_home","tel_home","email_home","customfield1","customfield2"\r
-"effect gmbh","Herr","Dr.","Jörg","Heinz","Geschäftsführer","Str. 25","21222","Köln","DE","022324321","","","joerg.heinz@honk.com","022324322","022324323","joerg@home.com","","cf2-2"\r
-"effect gmbh","Herr","","Hans","Fritz","Technical Lead","Str. 25","21222","Köln","DE","022324321","","","hans.fritz@honk.com","","","","cf1","cf2"\r
+"org_name","salutation","title","n_given","n_family","role","adr_one_street","adr_one_postalcode","adr_one_locality","adr_one_countryname","tel_work","tel_fax","tel_cell","email","tel_fax_home","tel_home","email_home","customfield1","customfield2","customfield3"
+"effect gmbh","Herr","Dr.","Jörg","Heinz","Geschäftsführer","Str. 25","21222","Köln","DE","022324321","","","joerg.heinz@honk.com","022324322","022324323","joerg@home.com","","cf2-2",""
+"effect gmbh","Herr","","Hans","Fritz","Technical Lead","Str. 25","21222","Köln","DE","022324321","","","hans.fritz@honk.com","","","","cf1","cf2",""
$syncrotonEvent = new Syncroton_Model_Event($xml->Collections->Collection->Commands->Change[0]->ApplicationData);
$serverId = $controller->createEntry($syncrotonFolder->serverId, $syncrotonEvent);
-
+
$syncrotonEvent = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
$this->assertEquals(0, $syncrotonEvent->allDayEvent, 'alldayEvent');
$this->assertNotEmpty($syncrotonEvent->attendees, 'Events attendees not found in default calendar');
}
- public function testUpdateEntriesIPhone()
+ public function testUpdateEntriesIPhone($syncrotonFolder = null)
{
- // create event
- $syncrotonFolder = $this->testCreateFolder();
- $syncrotonFolder2 = $this->testCreateFolder();
-
- //make $syncrotonFolder2 the default
- Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $syncrotonFolder2->serverId);
-
+ // ensure folder is default
+ $syncrotonFolder = $syncrotonFolder ? $syncrotonFolder : $this->testCreateFolder();
+ Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $syncrotonFolder->serverId);
+
+ // create event with external attendee in default calendar
+ $xml = new SimpleXMLElement(file_get_contents(__DIR__ . '/files/event_with_attendee.xml'));
+ $syncrotonEvent = new Syncroton_Model_Event($xml->Collections->Collection->Commands->Change[0]->ApplicationData);
$controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), Tinebase_DateTime::now());
- list($serverId, $syncrotonEvent) = $this->testCreateEntry($syncrotonFolder);
+ $serverId = $controller->createEntry($syncrotonFolder->serverId, $syncrotonEvent);
- // update event
+ // assert external attendee is present
$syncrotonEventtoUpdate = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
+ $this->assertEquals(2, count($syncrotonEventtoUpdate->attendees), 'event: ' . var_export($syncrotonEventtoUpdate->attendees, TRUE));
+
+ // update event in non default folder
$syncrotonEventtoUpdate->exceptions[0]->subject = 'update';
$syncrotonEventtoUpdate->exceptions[0]->startTime->addHour(1);
$syncrotonEventtoUpdate->exceptions[0]->endTime->addHour(1);
-
$syncTimestamp = Calendar_Controller_Event::getInstance()->get($serverId)->last_modified_time;
$controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), $syncTimestamp);
$serverId = $controller->updateEntry($syncrotonFolder->serverId, $serverId, $syncrotonEventtoUpdate);
- // assert update
+ // assert update in default folder
$updatedSyncrotonEvent = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
$this->assertEquals('update', $updatedSyncrotonEvent->exceptions[0]->subject);
- $this->assertNotEquals($syncrotonEvent->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
- $this->assertEquals($syncrotonEventtoUpdate->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
+ $this->assertEquals('2012-11-25 15:00:00', $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
+ $this->assertEquals(2, count($updatedSyncrotonEvent->attendees), 'event: ' . var_export($updatedSyncrotonEvent->attendees, TRUE));
- // assert attendee are preserved
- $updatedEvent = Calendar_Controller_MSEventFacade::getInstance()->get($serverId);
- $this->assertNotEmpty($updatedEvent, 'attendee must be preserved during update');
+ return array($serverId, $updatedSyncrotonEvent);
}
/**
*/
public function testUpdateEntriesIPhoneNonDefaultFolder()
{
- // create event in folder1
+ // create event in default folder
$syncrotonFolder = $this->testCreateFolder();
- $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), Tinebase_DateTime::now());
- list($serverId, $syncrotonEvent) = $this->testCreateEntry($syncrotonFolder);
+ list($serverId, $syncrotonEvent) = $this->testUpdateEntriesIPhone($syncrotonFolder);
// create new default folder2
$syncrotonFolder2 = $this->testCreateFolder();
Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $syncrotonFolder2->serverId);
- // load event in non default folder2
+ // load event in non default folder
+ $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), Tinebase_DateTime::now());
$syncrotonEventtoUpdate = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
$this->assertEmpty($syncrotonEventtoUpdate->attendees, 'attendee in non default folders must be removed for ios');
// update event in non default folder
- $syncrotonEventtoUpdate->exceptions[0]->subject = 'update';
+ $syncrotonEventtoUpdate->exceptions[0]->subject = 'update2';
$syncrotonEventtoUpdate->exceptions[0]->startTime->addHour(1);
$syncrotonEventtoUpdate->exceptions[0]->endTime->addHour(1);
$controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), $syncTimestamp);
$serverId = $controller->updateEntry($syncrotonFolder->serverId, $serverId, $syncrotonEventtoUpdate);
- // assert update from non default folder
+ // assert update from default folder
$updatedSyncrotonEvent = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder2->serverId)), $serverId);
- $this->assertEquals('update', $updatedSyncrotonEvent->exceptions[0]->subject);
+ $this->assertEquals('update2', $updatedSyncrotonEvent->exceptions[0]->subject);
$this->assertNotEquals($syncrotonEvent->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
$this->assertEquals($syncrotonEventtoUpdate->exceptions[0]->startTime->toString(), $updatedSyncrotonEvent->exceptions[0]->startTime->toString());
+ $this->assertEquals(2, count($updatedSyncrotonEvent->attendees), 'event: ' . var_export($updatedSyncrotonEvent->attendees, TRUE));
+ }
+
+ public function testCreateUpdateGroupEvents()
+ {
+ $syncrotonFolder = $this->testCreateFolder();
+ Tinebase_Core::getPreference('Calendar')->setValue(Calendar_Preference::DEFAULTCALENDAR, $syncrotonFolder->serverId);
+
+ $defaultUserGroup = Tinebase_Group::getInstance()->getDefaultGroup();
+ $defaultUserGroupMembers = Tinebase_Group::getInstance()->getGroupMembers($defaultUserGroup->getId());
+
+ // create event with default user group (without explicit groupmembers)
+ $xml = new SimpleXMLElement(str_replace(array(
+ 'usersgroupid',
+ ), $defaultUserGroup->getId(), file_get_contents(__DIR__ . '/files/event_with_group_attendee.xml')));
+ $syncrotonEvent = new Syncroton_Model_Event($xml->Collections->Collection->Commands->Change[0]->ApplicationData);
+ $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), Tinebase_DateTime::now());
+ $serverId = $controller->createEntry($syncrotonFolder->serverId, $syncrotonEvent);
+
+ // assert created group & groupmembers
+ $syncrotonEventtoUpdate = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
+ $this->assertCount(count($defaultUserGroupMembers) + 1, $syncrotonEventtoUpdate->attendees, 'groupmembers not resolved');
+ $this->assertCount(count($defaultUserGroupMembers) + 1, $syncrotonEventtoUpdate->exceptions[0]->attendees, 'groupmembers not resolved');
+
+ // update event
+ $syncrotonEventtoUpdate->exceptions[0]->subject = 'update';
+ $syncTimestamp = Calendar_Controller_Event::getInstance()->get($serverId)->last_modified_time;
+ $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), $syncTimestamp);
+ $serverId = $controller->updateEntry($syncrotonFolder->serverId, $serverId, $syncrotonEventtoUpdate);
- // assert attendee are preserved
- $this->assertNotEmpty($updatedSyncrotonEvent->attendees, 'attendee must be preserved during update');
+ // assert updated group & groupmembers
+ $updatedSyncrotonEvent = $controller->getEntry(new Syncroton_Model_SyncCollection(array('collectionId' => $syncrotonFolder->serverId)), $serverId);
+ $this->assertCount(count($defaultUserGroupMembers) + 1, $updatedSyncrotonEvent->attendees, 'groupmembers not resolved');
+ $this->assertCount(count($defaultUserGroupMembers) + 1, $updatedSyncrotonEvent->exceptions[0]->attendees, 'groupmembers not resolved');
}
}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
+<Sync xmlns="uri:AirSync" xmlns:Calendar="uri:Calendar">
+ <Collections>
+ <Collection>
+ <Class>Calendar</Class>
+ <SyncKey>9</SyncKey>
+ <CollectionId>41</CollectionId>
+ <DeletesAsMoves/>
+ <GetChanges/>
+ <WindowSize>50</WindowSize>
+ <Options><FilterType>5</FilterType></Options>
+ <Commands>
+ <Change>
+ <ServerId>6de7cb687964dc6eea109cd81750177979362217</ServerId>
+ <ApplicationData>
+ <Calendar:Timezone>xP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAFAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAFAAIAAAAAAAAAxP///w==</Calendar:Timezone>
+ <Calendar:AllDayEvent>0</Calendar:AllDayEvent>
+ <Calendar:BusyStatus>2</Calendar:BusyStatus>
+ <Calendar:DtStamp>20121125T150537Z</Calendar:DtStamp>
+ <Calendar:EndTime>20121123T160000Z</Calendar:EndTime>
+ <Calendar:Sensitivity>2</Calendar:Sensitivity>
+ <Calendar:Subject>Repeat</Calendar:Subject>
+ <Calendar:StartTime>20121123T130000Z</Calendar:StartTime>
+ <Calendar:UID>6de7cb687964dc6eea109cd81750177979362217</Calendar:UID>
+ <Calendar:MeetingStatus>1</Calendar:MeetingStatus>
+ <Calendar:Attendees>
+ <Calendar:Attendee>
+ <Calendar:Name>Users</Calendar:Name>
+ <Calendar:Email>usersgroupid</Calendar:Email>
+ </Calendar:Attendee>
+ </Calendar:Attendees>
+ <Calendar:Recurrence>
+ <Calendar:Type>0</Calendar:Type><Calendar:Interval>1</Calendar:Interval><Calendar:Until>20121128T225959Z</Calendar:Until>
+ </Calendar:Recurrence>
+ <Calendar:Exceptions>
+ <Calendar:Exception>
+ <Calendar:Deleted>0</Calendar:Deleted>
+ <Calendar:ExceptionStartTime>20121125T130000Z</Calendar:ExceptionStartTime>
+ <Calendar:StartTime>20121125T140000Z</Calendar:StartTime>
+ <Calendar:EndTime>20121125T170000Z</Calendar:EndTime>
+ <Calendar:Subject>Repeat mal anders</Calendar:Subject>
+ <Calendar:BusyStatus>2</Calendar:BusyStatus>
+ <Calendar:AllDayEvent>0</Calendar:AllDayEvent>
+ <Calendar:Attendees>
+ <Calendar:Attendee>
+ <Calendar:Name>Users</Calendar:Name>
+ <Calendar:Email>usersgroupid</Calendar:Email>
+ </Calendar:Attendee>
+ </Calendar:Attendees>
+ </Calendar:Exception>
+ <Calendar:Exception>
+ <Calendar:Deleted>1</Calendar:Deleted><Calendar:ExceptionStartTime>20121124T130000Z</Calendar:ExceptionStartTime></Calendar:Exception>
+ </Calendar:Exceptions>
+ <Calendar:Reminder>15</Calendar:Reminder>
+ <Body xmlns="uri:AirSyncBase"><Type>1</Type><Data>Hello</Data></Body>
+ </ApplicationData>
+ </Change>
+ </Commands>
+ </Collection>
+ </Collections>
+</Sync>
\ No newline at end of file
}
/**
+ * @see 0012228: employee bday should be saved as datetime
+ */
+ public function testBirthday()
+ {
+ $e = $this->_getEmployee();
+ $datetime = new Tinebase_DateTime('2009-03-02 00:00:00');
+ $e->bday = $datetime;
+ $savedEmployee = $this->_json->saveEmployee($e->toArray());
+ $this->assertEquals($datetime->toString(), $savedEmployee['bday']);
+ }
+
+ /**
* Tests the duplicate check
*/
public function testDuplicateException()
/**
* Timetracker_AbstractTest Test class
*/
-abstract class Timetracker_AbstractTest extends PHPUnit_Framework_TestCase
+abstract class Timetracker_AbstractTest extends TestCase
{
/**
* @var Timetracker_Frontend_Json
$this->assertEquals(1, $results->count());
}
+
+ /**
+ * tests if the Timeaccount Filter is there
+ */
+ public function testTimeaccountfilterWithoutAdmin()
+ {
+ $this->_removeRoleRight('Timetracker', Tinebase_Acl_Rights::ADMIN);
+ $this->assertFalse(Tinebase_Core::getUser()->hasRight('Timetracker', Tinebase_Acl_Rights::ADMIN));
+ $config = Tinebase_ModelConfiguration::getFrontendConfigForModels(array('Timetracker_Model_Timesheet'));
+ $this->assertTrue(isset($config['Timesheet']['filterModel']['timeaccount_id']));
+ }
}
return $this->_webdavTree;
}
+
+ /**
+ * @see 0012216: Caldav Directory calendars not found
+ */
+ public function testCalendarRoot()
+ {
+ $calendarRoot = new Calendar_Frontend_WebDAV(\Sabre\CalDAV\Plugin::CALENDAR_ROOT, true);
+ $children = $calendarRoot->getChildren();
+ $this->assertTrue(count($children) > 0 && $children[0] instanceof Calendar_Frontend_WebDAV);
+ }
}
{
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " create entry");
-
+
+ $this->_assertContentControllerParams($folderId);
$entry = $this->toTineModel($entry);
// container_id gets set to personal folder in application specific controller if missing
Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " update CollectionId: $folderId Id: $serverId");
try {
+ $this->_assertContentControllerParams($folderId);
$oldEntry = $this->_contentController->get($serverId);
} catch (Tinebase_Exception_NotFound $tenf) {
if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
if ($entry &&
$this->_device->devicetype === Syncroton_Model_Device::TYPE_IPHONE &&
$this->_syncFolderId !== $this->_getDefaultContainerId()) {
- // keep attendees as the are / they were not sent to the device before
- continue;
+
+ if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(
+ __METHOD__ . '::' . __LINE__ . " keep attendees as the are / they were not sent to the device before ");
+
+ continue;
}
$newAttendees = array();
$lastName = $attendee->name;
}
- // @todo handle resources
$newAttendees[] = array(
'userType' => Calendar_Model_Attender::USERTYPE_USER,
'firstName' => $firstName,
}
}
+ // does a list with this id exist?
+ if (! $attendeeId) {
+ try {
+ $group = Tinebase_Group::getInstance()->getGroupById($newAttendee['email']);
+ if ($group) {
+ $newAttendee['userType'] = Calendar_Model_Attender::USERTYPE_GROUP;
+ $attendeeId = $group->getId();
+ }
+ } catch (Exception $e) {
+ // do nothing
+ }
+ }
+
if (! $attendeeId) {
// autocreate a contact if allowed
$contact = self::resolveEmailToContact($newAttendee, $_implicitAddMissingContacts);
cropper = node.getElementsByClassName('cal-daysviewpanel-cropper')[0],
body = node.getElementsByClassName('cal-daysviewpanel-body')[0],
dayStartPx = view.getTimeOffset(view.dayStart),
+ dayEndPx = view.getTimeOffset(view.dayEnd),
fullHeight = view.getTimeOffset(view.startDate.add(Date.DAY, 1).add(Date.MINUTE, -1)),
- cropHeight = view.dayEndPx - dayStartPx + 20,
+ cropHeight = dayEndPx - dayStartPx + 20,
scrollerHeight = view.cropDayTime ? cropHeight : fullHeight;
daysViewPanel.id = this.panelId = Ext.id();
// @TODO: if you have a lot of allDayEvents, your scroller gets smaller,
// this might be confusing in print
header.style.height = Math.max(header.firstChild.style.height, header.style.height);
+ scroller.style.height = scrollerHeight + 'px';
scroller.style.width = null;
return this.generateTitle(view) + node.innerHTML;
),
'bday' => array(
'label' => 'Birthday', //_('Birthday')
- 'type' => 'date',
+ 'type' => 'datetime',
'group' => 'private',
),
'bank_account_holder' => array(
));
}
- // check json key for all methods but some exceptoins
+ // check json key for all methods but some exceptions
if (! in_array($method, $anonymnousMethods) && Setup_Core::configFileExists()
&& ( empty($jsonKey) || $jsonKey != Setup_Core::get('jsonKey')
|| !Setup_Core::isRegistered(Setup_Core::USER)
Tine.Tinebase.tineInit.initRegistry = Tine.Tinebase.tineInit.initRegistry.createInterceptor(function () {
Tine.Tinebase.tineInit.clearRegistry();
Tine.Tinebase.tineInit.getAllRegistryDataMethod = 'Setup.getAllRegistryData';
+ Tine.Tinebase.tineInit.jsonKeyCookieId = 'TINE20SETUPJSONKEY';
Tine.Tinebase.tineInit.stateful = false;
return true;
Tine.Timetracker.TimesheetGridPanel.superclass.initActions.call(this);
},
+ /**
+ * check user exportGrant for timeaccounts
+ * NOTE: manage_timeaccounts ALWAYS allows to export
+ *
+ * @param action
+ * @param grants
+ * @param records
+ * @returns {boolean}
+ */
updateExportAction: function(action, grants, records) {
var exportGrant = true;
- Ext.each(records, function(record) {
- var c = record.get('timeaccount_id').container_id;
- if (c.hasOwnProperty('account_grants')) {
- if (! c.account_grants.exportGrant) {
- exportGrant = false;
- return false;
+ if (! Tine.Tinebase.common.hasRight('manage', 'Timetracker', 'timeaccounts')) {
+ Ext.each(records, function (record) {
+ var c = record.get('timeaccount_id').container_id;
+ if (c.hasOwnProperty('account_grants')) {
+ if (!c.account_grants.exportGrant) {
+ exportGrant = false;
+ return false;
+ }
}
- }
- });
+ });
+ }
var disable = ! exportGrant;
action.setDisabled(disable);
$ownField = $this->__get($fieldName);
$recordField = $_record->$fieldName;
-
+
+ if ($fieldName == 'customfields' && is_array($ownField) && is_array($recordField)) {
+ // special handling for customfields, remove empty customfields from array
+ foreach (array_keys($recordField, '', true) as $key) {
+ unset($recordField[$key]);
+ }
+ foreach (array_keys($ownField, '', true) as $key) {
+ unset($ownField[$key]);
+ }
+ }
+
if (in_array($fieldName, $this->_datetimeFields)) {
if ($ownField instanceof DateTime
&& $recordField instanceof DateTime) {
. ' Removing/unset current jpegphoto');
$contact->jpegphoto = false;
}
+ } else {
+ $syncPhoto = false;
}
$diff = $contact->diff($originalContact, $syncPhoto ? array('n_fn') : array('jpegphoto', 'n_fn'));
if (! $diff->isEmpty() || ($originalContact->jpegphoto === 0 && ! empty($contact->jpegphoto)) ) {
*
* @return \Sabre\DAV\INode[]
*/
- function getChildren()
+ public function getChildren()
{
$children = array();
if ($this->_hasPersonalFolders) {
$children[] = $this->getChild(
- $this->_useIdAsName ? Tinebase_Core::getUser()->contact_id : $this->_useLoginAsFolderName() ? Tinebase_Core::getUser()->accountLoginName : Tinebase_Core::getUser()->accountDisplayName
+ $this->_useIdAsName ?
+ Tinebase_Core::getUser()->contact_id :
+ ($this->_useLoginAsFolderName() ?
+ Tinebase_Core::getUser()->accountLoginName :
+ Tinebase_Core::getUser()->accountDisplayName)
);
$otherUsers = Tinebase_Container::getInstance()->getOtherUsers(Tinebase_Core::getUser(), $this->_getApplicationName(), array(
foreach ($otherUsers as $user) {
if ($user->contact_id && $user->visibility === Tinebase_Model_User::VISIBILITY_DISPLAYED) {
try {
- $folderId = $this->_useIdAsName ? $user->contact_id : $this->_useLoginAsFolderName() ? $user->accountLoginName : $user->accountDisplayName;
+ $folderId = $this->_useIdAsName ?
+ $user->contact_id :
+ ($this->_useLoginAsFolderName() ? $user->accountLoginName : $user->accountDisplayName);
$children[] = $this->getChild($folderId);
} catch (\Sabre\DAV\Exception\NotFound $sdavenf) {
$user = $this->_getUser(Tinebase_Helper::array_value(1, $this->_getPathParts()));
$contact = Addressbook_Controller_Contact::getInstance()->get($user->contact_id);
} catch (Tinebase_Exception_NotFound $tenf) {
- continue;
+ continue 2;
}
$response[$property] = $contact->n_fileas;
protected function _getUser($_id)
{
- $classCacheId = ($this->_useIdAsName ? 'contact_id' : $this->_useLoginAsFolderName() ? 'accountLoginName' : 'accountDisplayName') . $_id;
+ $classCacheId = ($this->_useIdAsName ? 'contact_id' : ($this->_useLoginAsFolderName() ? 'accountLoginName' : 'accountDisplayName')) . $_id;
if (isset(self::$_classCache[__FUNCTION__][$classCacheId])) {
return self::$_classCache[__FUNCTION__][$classCacheId];
stateful: true,
/**
+ * @cfg {String} jsonKeyCookieId
+ */
+ jsonKeyCookieId: 'TINE20JSONKEY',
+
+ /**
* @cfg {String} requestUrl
*/
requestUrl: 'index.php',
Ext.Ajax.on('beforerequest', function (connection, options) {
var jsonKey = Tine.Tinebase.registry && Tine.Tinebase.registry.get ? Tine.Tinebase.registry.get('jsonKey') : '';
- if (Tine.Tinebase.tineInit.jsonKeyCookieProvider.get('TINE20JSONKEY')) {
- var cookieJsonKey = Tine.Tinebase.tineInit.jsonKeyCookieProvider.get('TINE20JSONKEY');
- Tine.Tinebase.tineInit.jsonKeyCookieProvider.clear('TINE20JSONKEY');
+ if (Tine.Tinebase.tineInit.jsonKeyCookieProvider.get(this.jsonKeyCookieId)) {
+ var cookieJsonKey = Tine.Tinebase.tineInit.jsonKeyCookieProvider.get(this.jsonKeyCookieId);
+ Tine.Tinebase.tineInit.jsonKeyCookieProvider.clear(this.jsonKeyCookieId);
// NOTE cookie reset is not always working in IE, so we need to check jsonKey again
if (cookieJsonKey && cookieJsonKey != "null") {
jsonKey = cookieJsonKey;
json: options.jsonData
};
});
+
+
/**
* inspect completed responses => staus code == 200
doc.write(this.generateHTML(component));
doc.close();
+ // resize to full height as browser might print only the visible area
+ var totalHeight = Ext.fly(doc.body).getHeight();
+ Ext.fly(frame).setStyle('height', totalHeight+'px');
+
this.doPrintOnStylesheetLoad.defer(10, this, [frame.contentWindow, component]);
},
iconv_set_encoding('internal_encoding', "UTF-8");
}
}
-mb_internal_encoding("UTF-8");
+
+if (extension_loaded('mbstring')) {
+ mb_internal_encoding("UTF-8");
+}
// intialize composers autoloader
$autoloader = require __DIR__ . '/vendor/autoload.php';