Merge branch 'pu/2013.03/modelconfig-hr'
authorPhilipp Schüle <p.schuele@metaways.de>
Thu, 25 Apr 2013 20:17:02 +0000 (22:17 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 25 Apr 2013 20:17:02 +0000 (22:17 +0200)
Conflicts:
tine20/Inventory/Model/InventoryItem.php

760 files changed:
scripts/packaging/build-tine20-packages.sh
scripts/packaging/debian/changelog
tests/setup/Setup/ControllerTest.php
tests/tine20/Calendar/Backend/SqlTest.php
tests/tine20/Calendar/Controller/EventTests.php
tests/tine20/Calendar/Controller/RecurTest.php
tests/tine20/Calendar/Frontend/WebDAV/EventTest.php
tests/tine20/Calendar/Import/files/lightning_repeating_weekly.ics [new file with mode: 0644]
tests/tine20/Calendar/Import/files/lightning_repeating_weekly_exception.ics [new file with mode: 0644]
tests/tine20/Calendar/JsonTests.php
tests/tine20/Calendar/TestCase.php
tests/tine20/Courses/JsonTest.php
tests/tine20/Felamimail/Controller/MessageTest.php
tests/tine20/Felamimail/JsonTest.php
tests/tine20/Felamimail/Model/MessageTest.php
tests/tine20/Felamimail/files/facebook_notification.eml [new file with mode: 0644]
tests/tine20/Filemanager/AllTests.php
tests/tine20/Filemanager/Frontend/AllTests.php
tests/tine20/Filemanager/Frontend/JsonTests.php
tests/tine20/Inventory/Import/CsvTest.php
tests/tine20/Inventory/Import/files/inv_tine_import_csv.xml
tests/tine20/Inventory/Import/files/inv_tine_import_csv_nohook.xml
tests/tine20/Inventory/Import/files/inv_tine_import_datetimes.csv [new file with mode: 0644]
tests/tine20/Inventory/JsonTest.php
tests/tine20/Tasks/ControllerTest.php
tests/tine20/Tinebase/AllTests.php
tests/tine20/Tinebase/DateTimeTest.php
tests/tine20/Tinebase/FileSystem/StreamWrapperTest.php
tests/tine20/Tinebase/FileSystemTest.php
tests/tine20/Tinebase/Frontend/JsonTest.php
tests/tine20/Tinebase/PreferenceTest.php
tests/tine20/Tinebase/TempFileTest.php [new file with mode: 0644]
tests/tine20/Tinebase/User/EmailUser/Smtp/PostfixTest.php
tests/tine20/Tinebase/UserTest.php
tests/tine20/Tinebase/files/brokenname.txt [new file with mode: 0644]
tine20/ActiveSync/Setup/Update/Release5.php
tine20/ActiveSync/translations/da.po
tine20/ActiveSync/translations/de.po
tine20/ActiveSync/translations/fi.po
tine20/ActiveSync/translations/fr.po
tine20/ActiveSync/translations/hr_HR.po
tine20/ActiveSync/translations/hu.po
tine20/ActiveSync/translations/it.po
tine20/ActiveSync/translations/ko_KR.po
tine20/ActiveSync/translations/nl_NL.po
tine20/ActiveSync/translations/pl.po
tine20/ActiveSync/translations/ru.po
tine20/ActiveSync/translations/sv_SE.po
tine20/ActiveSync/translations/tr_TR.po
tine20/ActiveSync/translations/vi.po
tine20/ActiveSync/translations/zh_CN.po
tine20/ActiveSync/translations/zh_TW.po
tine20/Addressbook/Addressbook.jsb2
tine20/Addressbook/Backend/List.php
tine20/Addressbook/Controller.php
tine20/Addressbook/Frontend/Json.php
tine20/Addressbook/Model/List.php
tine20/Addressbook/Model/ListHiddenFilter.php
tine20/Addressbook/Setup/DemoData.php
tine20/Addressbook/Setup/Update/Release7.php
tine20/Addressbook/Setup/setup.xml
tine20/Addressbook/js/Addressbook.js
tine20/Addressbook/js/ContactEditDialog.js
tine20/Addressbook/js/ContactGrid.js
tine20/Addressbook/js/ContactModel.js [moved from tine20/Addressbook/js/Model.js with 91% similarity]
tine20/Addressbook/js/EmailModel.js [new file with mode: 0644]
tine20/Addressbook/js/ListEditDialog.js [new file with mode: 0644]
tine20/Addressbook/js/ListGrid.js [new file with mode: 0644]
tine20/Addressbook/js/ListGridDetailsPanel.js [new file with mode: 0644]
tine20/Addressbook/js/ListMemberGridPanel.js [new file with mode: 0644]
tine20/Addressbook/js/ListModel.js [new file with mode: 0644]
tine20/Addressbook/js/SearchCombo.js
tine20/Addressbook/translations/bg.po
tine20/Addressbook/translations/ca.po
tine20/Addressbook/translations/cs.po
tine20/Addressbook/translations/da.po
tine20/Addressbook/translations/de.po
tine20/Addressbook/translations/es.po
tine20/Addressbook/translations/es_MX.po
tine20/Addressbook/translations/et.po
tine20/Addressbook/translations/fa_IR.po
tine20/Addressbook/translations/fi.po
tine20/Addressbook/translations/fr.po
tine20/Addressbook/translations/hr_HR.po
tine20/Addressbook/translations/hu.po
tine20/Addressbook/translations/it.po
tine20/Addressbook/translations/ja.po
tine20/Addressbook/translations/ko_KR.po
tine20/Addressbook/translations/lt.po
tine20/Addressbook/translations/nb.po
tine20/Addressbook/translations/nl_NL.po
tine20/Addressbook/translations/pl.po
tine20/Addressbook/translations/pt_BR.po
tine20/Addressbook/translations/ru.po
tine20/Addressbook/translations/sk.po
tine20/Addressbook/translations/sv_SE.po
tine20/Addressbook/translations/template.pot
tine20/Addressbook/translations/tr_TR.po
tine20/Addressbook/translations/vi.po
tine20/Addressbook/translations/zh_CN.po
tine20/Addressbook/translations/zh_TW.po
tine20/Admin/Acl/Rights.php
tine20/Admin/Event/DeleteAccount.php [new file with mode: 0644]
tine20/Admin/Setup/DemoData.php
tine20/Admin/js/Admin.js
tine20/Admin/js/Applications.js
tine20/Admin/js/Groups.js
tine20/Admin/js/Roles.js
tine20/Admin/js/user/EditDialog.js
tine20/Admin/translations/de.po
tine20/Admin/translations/es_MX.po
tine20/Admin/translations/et.po
tine20/Admin/translations/fi.po
tine20/Admin/translations/fr.po
tine20/Admin/translations/hr_HR.po
tine20/Admin/translations/hu.po
tine20/Admin/translations/it.po
tine20/Admin/translations/lt.po
tine20/Admin/translations/pl.po
tine20/Admin/translations/pt_BR.po
tine20/Admin/translations/ru.po
tine20/Admin/translations/sv_SE.po
tine20/Admin/translations/vi.po
tine20/Admin/translations/zh_TW.po
tine20/Calendar/Backend/Sql.php
tine20/Calendar/Controller/Event.php
tine20/Calendar/Controller/EventNotifications.php
tine20/Calendar/Controller/MSEventFacade.php
tine20/Calendar/Convert/Event/VCalendar/Abstract.php
tine20/Calendar/Frontend/Cli.php
tine20/Calendar/Frontend/Json.php
tine20/Calendar/Frontend/WebDAV/Event.php
tine20/Calendar/Model/Event.php
tine20/Calendar/Setup/Update/Release6.php
tine20/Calendar/Setup/Update/Release7.php
tine20/Calendar/Setup/setup.xml
tine20/Calendar/js/AddressbookGridPanelHook.js
tine20/Calendar/js/AttendeeFilterGrid.js
tine20/Calendar/js/AttendeeGridPanel.js
tine20/Calendar/js/ColorManager.js
tine20/Calendar/js/MainScreenCenterPanel.js
tine20/Calendar/js/Model.js
tine20/Calendar/js/TreePanel.js
tine20/Calendar/translations/bg.po
tine20/Calendar/translations/ca.po
tine20/Calendar/translations/cs.po
tine20/Calendar/translations/da.po
tine20/Calendar/translations/de.po
tine20/Calendar/translations/es.po
tine20/Calendar/translations/es_MX.po
tine20/Calendar/translations/et.po
tine20/Calendar/translations/fa_IR.po
tine20/Calendar/translations/fi.po
tine20/Calendar/translations/fr.po
tine20/Calendar/translations/hr_HR.po
tine20/Calendar/translations/hu.po
tine20/Calendar/translations/it.po
tine20/Calendar/translations/ja.po
tine20/Calendar/translations/ko_KR.po
tine20/Calendar/translations/lt.po
tine20/Calendar/translations/nb.po
tine20/Calendar/translations/nl_NL.po
tine20/Calendar/translations/pl.po
tine20/Calendar/translations/pt_BR.po
tine20/Calendar/translations/ru.po
tine20/Calendar/translations/sk.po
tine20/Calendar/translations/sv_SE.po
tine20/Calendar/translations/template.pot
tine20/Calendar/translations/tr_TR.po
tine20/Calendar/translations/vi.po
tine20/Calendar/translations/zh_CN.po
tine20/Calendar/translations/zh_TW.po
tine20/Courses/translations/de.po
tine20/Courses/translations/es_MX.po
tine20/Courses/translations/et.po
tine20/Courses/translations/fi.po
tine20/Courses/translations/hr_HR.po
tine20/Courses/translations/hu.po
tine20/Courses/translations/it.po
tine20/Courses/translations/pl.po
tine20/Courses/translations/ru.po
tine20/Courses/translations/sv_SE.po
tine20/Courses/translations/tr_TR.po
tine20/Courses/translations/vi.po
tine20/Courses/translations/zh_TW.po
tine20/Crm/Model/Lead.php
tine20/Crm/js/AddressbookGridPanelHook.js
tine20/Crm/translations/bg.po
tine20/Crm/translations/ca.po
tine20/Crm/translations/cs.po
tine20/Crm/translations/da.po
tine20/Crm/translations/de.po
tine20/Crm/translations/es.po
tine20/Crm/translations/es_MX.po
tine20/Crm/translations/et.po
tine20/Crm/translations/fa_IR.po
tine20/Crm/translations/fi.po
tine20/Crm/translations/fr.po
tine20/Crm/translations/hr_HR.po
tine20/Crm/translations/hu.po
tine20/Crm/translations/it.po
tine20/Crm/translations/ja.po
tine20/Crm/translations/ko_KR.po
tine20/Crm/translations/lt.po
tine20/Crm/translations/nb.po
tine20/Crm/translations/nl_NL.po
tine20/Crm/translations/pl.po
tine20/Crm/translations/pt_BR.po
tine20/Crm/translations/ru.po
tine20/Crm/translations/sk.po
tine20/Crm/translations/sv_SE.po
tine20/Crm/translations/template.pot
tine20/Crm/translations/tr_TR.po
tine20/Crm/translations/vi.po
tine20/Crm/translations/zh_CN.po
tine20/Crm/translations/zh_TW.po
tine20/Felamimail/Backend/Folder.php
tine20/Felamimail/Controller/Account.php
tine20/Felamimail/Controller/Message.php
tine20/Felamimail/Controller/Sieve.php
tine20/Felamimail/HTMLPurifier/URIFilter/TransformURI.php
tine20/Felamimail/Model/Account.php
tine20/Felamimail/Model/Sieve/Vacation.php
tine20/Felamimail/Preference.php
tine20/Felamimail/Sieve/Backend/Sql.php
tine20/Felamimail/css/Felamimail.css
tine20/Felamimail/js/ContactGrid.js
tine20/Felamimail/js/ContactSearchCombo.js
tine20/Felamimail/js/Felamimail.js
tine20/Felamimail/js/GridPanel.js
tine20/Felamimail/js/GridPanelHook.js
tine20/Felamimail/js/MessageDisplayDialog.js
tine20/Felamimail/js/MessageEditDialog.js
tine20/Felamimail/js/Model.js
tine20/Felamimail/js/RecipientGrid.js
tine20/Felamimail/translations/bg.po
tine20/Felamimail/translations/ca.po
tine20/Felamimail/translations/cs.po
tine20/Felamimail/translations/da.po
tine20/Felamimail/translations/de.po
tine20/Felamimail/translations/es.po
tine20/Felamimail/translations/es_MX.po
tine20/Felamimail/translations/et.po
tine20/Felamimail/translations/fa_IR.po
tine20/Felamimail/translations/fi.po
tine20/Felamimail/translations/fr.po
tine20/Felamimail/translations/hr_HR.po
tine20/Felamimail/translations/hu.po
tine20/Felamimail/translations/it.po
tine20/Felamimail/translations/ko_KR.po
tine20/Felamimail/translations/lt.po
tine20/Felamimail/translations/nb.po
tine20/Felamimail/translations/nl_NL.po
tine20/Felamimail/translations/pl.po
tine20/Felamimail/translations/pt_BR.po
tine20/Felamimail/translations/ru.po
tine20/Felamimail/translations/sk.po
tine20/Felamimail/translations/sv_SE.po
tine20/Felamimail/translations/template.pot
tine20/Felamimail/translations/tr_TR.po
tine20/Felamimail/translations/vi.po
tine20/Felamimail/translations/zh_CN.po
tine20/Felamimail/translations/zh_TW.po
tine20/Filemanager/Acl/Rights.php
tine20/Filemanager/Controller.php
tine20/Filemanager/Controller/Node.php
tine20/Filemanager/Setup/Initialize.php
tine20/Filemanager/js/Filemanager.js
tine20/Filemanager/js/NodeEditDialog.js
tine20/Filemanager/js/NodeTreePanel.js
tine20/Filemanager/translations/cs.po
tine20/Filemanager/translations/da.po
tine20/Filemanager/translations/de.po
tine20/Filemanager/translations/es.po
tine20/Filemanager/translations/es_MX.po
tine20/Filemanager/translations/et.po
tine20/Filemanager/translations/fa_IR.po
tine20/Filemanager/translations/fi.po
tine20/Filemanager/translations/fr.po
tine20/Filemanager/translations/hr_HR.po
tine20/Filemanager/translations/hu.po
tine20/Filemanager/translations/it.po
tine20/Filemanager/translations/ko_KR.po
tine20/Filemanager/translations/lt.po
tine20/Filemanager/translations/nl_NL.po
tine20/Filemanager/translations/pl.po
tine20/Filemanager/translations/pt_BR.po
tine20/Filemanager/translations/ru.po
tine20/Filemanager/translations/sk.po
tine20/Filemanager/translations/sv_SE.po
tine20/Filemanager/translations/template.pot
tine20/Filemanager/translations/tr_TR.po
tine20/Filemanager/translations/vi.po
tine20/Filemanager/translations/zh_CN.po
tine20/Filemanager/translations/zh_TW.po
tine20/HumanResources/Setup/Update/Release7.php
tine20/HumanResources/Setup/setup.xml
tine20/HumanResources/translations/cs.po
tine20/HumanResources/translations/da.po
tine20/HumanResources/translations/de.po
tine20/HumanResources/translations/es.po
tine20/HumanResources/translations/es_MX.po
tine20/HumanResources/translations/et.po
tine20/HumanResources/translations/fa_IR.po
tine20/HumanResources/translations/fi.po
tine20/HumanResources/translations/fr.po
tine20/HumanResources/translations/hr_HR.po
tine20/HumanResources/translations/hu.po
tine20/HumanResources/translations/it.po
tine20/HumanResources/translations/ko_KR.po
tine20/HumanResources/translations/lt.po
tine20/HumanResources/translations/nl_NL.po
tine20/HumanResources/translations/pl.po
tine20/HumanResources/translations/pt_BR.po
tine20/HumanResources/translations/ru.po
tine20/HumanResources/translations/sk.po
tine20/HumanResources/translations/sv_SE.po
tine20/HumanResources/translations/template.pot
tine20/HumanResources/translations/tr_TR.po
tine20/HumanResources/translations/vi.po
tine20/HumanResources/translations/zh_CN.po
tine20/HumanResources/translations/zh_TW.po
tine20/Inventory/Import/examples/inv_tine_import.csv
tine20/Inventory/Model/InventoryItem.php
tine20/Inventory/translations/cs.po
tine20/Inventory/translations/da.po
tine20/Inventory/translations/de.po
tine20/Inventory/translations/es.po
tine20/Inventory/translations/es_MX.po
tine20/Inventory/translations/et.po
tine20/Inventory/translations/fa_IR.po
tine20/Inventory/translations/fi.po
tine20/Inventory/translations/fr.po
tine20/Inventory/translations/hr_HR.po
tine20/Inventory/translations/hu.po
tine20/Inventory/translations/it.po
tine20/Inventory/translations/ko_KR.po
tine20/Inventory/translations/lt.po
tine20/Inventory/translations/nl_NL.po
tine20/Inventory/translations/pl.po
tine20/Inventory/translations/pt_BR.po
tine20/Inventory/translations/ru.po
tine20/Inventory/translations/sk.po
tine20/Inventory/translations/sv_SE.po
tine20/Inventory/translations/template.pot
tine20/Inventory/translations/tr_TR.po
tine20/Inventory/translations/vi.po
tine20/Inventory/translations/zh_CN.po
tine20/Inventory/translations/zh_TW.po
tine20/Phone/js/AddressbookGridPanelHook.js
tine20/Phone/translations/es_MX.po
tine20/Phone/translations/et.po
tine20/Phone/translations/fa_IR.po
tine20/Phone/translations/fi.po
tine20/Phone/translations/fr.po
tine20/Phone/translations/hr_HR.po
tine20/Phone/translations/it.po
tine20/Phone/translations/ru.po
tine20/Phone/translations/sv_SE.po
tine20/Phone/translations/tr_TR.po
tine20/Phone/translations/vi.po
tine20/Phone/translations/zh_CN.po
tine20/Phone/translations/zh_TW.po
tine20/Projects/js/AddressbookGridPanelHook.js
tine20/Projects/js/ProjectEditDialog.js
tine20/Projects/js/ProjectGridPanel.js
tine20/Projects/translations/cs.po
tine20/Projects/translations/da.po
tine20/Projects/translations/de.po
tine20/Projects/translations/es.po
tine20/Projects/translations/es_MX.po
tine20/Projects/translations/et.po
tine20/Projects/translations/fa_IR.po
tine20/Projects/translations/fi.po
tine20/Projects/translations/fr.po
tine20/Projects/translations/hr_HR.po
tine20/Projects/translations/hu.po
tine20/Projects/translations/it.po
tine20/Projects/translations/ko_KR.po
tine20/Projects/translations/lt.po
tine20/Projects/translations/nb.po
tine20/Projects/translations/nl_NL.po
tine20/Projects/translations/pl.po
tine20/Projects/translations/pt_BR.po
tine20/Projects/translations/ru.po
tine20/Projects/translations/sk.po
tine20/Projects/translations/sv_SE.po
tine20/Projects/translations/template.pot
tine20/Projects/translations/tr_TR.po
tine20/Projects/translations/vi.po
tine20/Projects/translations/zh_CN.po
tine20/Projects/translations/zh_TW.po
tine20/Sales/translations/de.po
tine20/Sales/translations/es_MX.po
tine20/Sales/translations/fi.po
tine20/Sales/translations/fr.po
tine20/Sales/translations/hr_HR.po
tine20/Sales/translations/hu.po
tine20/Sales/translations/it.po
tine20/Sales/translations/pl.po
tine20/Sales/translations/pt_BR.po
tine20/Sales/translations/ru.po
tine20/Sales/translations/sv_SE.po
tine20/Sales/translations/vi.po
tine20/Sales/translations/zh_TW.po
tine20/Setup/Controller.php
tine20/Setup/js/AuthenticationPanel.js
tine20/Setup/translations/de.po
tine20/Setup/translations/es_MX.po
tine20/Setup/translations/et.po
tine20/Setup/translations/fi.po
tine20/Setup/translations/fr.po
tine20/Setup/translations/hr_HR.po
tine20/Setup/translations/hu.po
tine20/Setup/translations/it.po
tine20/Setup/translations/pl.po
tine20/Setup/translations/pt_BR.po
tine20/Setup/translations/ru.po
tine20/Setup/translations/sv_SE.po
tine20/Setup/translations/tr_TR.po
tine20/Setup/translations/vi.po
tine20/Setup/translations/zh_CN.po
tine20/Setup/translations/zh_TW.po
tine20/SimpleFAQ/SimpleFAQ.jsb2
tine20/SimpleFAQ/js/Model.js
tine20/SimpleFAQ/js/SearchCombo.js [new file with mode: 0644]
tine20/SimpleFAQ/js/SimpleFAQ.js
tine20/SimpleFAQ/translations/es_MX.po
tine20/SimpleFAQ/translations/et.po
tine20/SimpleFAQ/translations/fi.po
tine20/SimpleFAQ/translations/fr.po
tine20/SimpleFAQ/translations/hr_HR.po
tine20/SimpleFAQ/translations/hu.po
tine20/SimpleFAQ/translations/it.po
tine20/SimpleFAQ/translations/nl_NL.po
tine20/SimpleFAQ/translations/pl.po
tine20/SimpleFAQ/translations/ru.po
tine20/SimpleFAQ/translations/sv_SE.po
tine20/SimpleFAQ/translations/tr_TR.po
tine20/SimpleFAQ/translations/vi.po
tine20/SimpleFAQ/translations/zh_TW.po
tine20/Sipgate/Controller/Line.php
tine20/Sipgate/js/AddressbookGridPanelHook.js
tine20/Sipgate/js/ConnectionGridPanel.js
tine20/Sipgate/js/LineGridPanel.js
tine20/Sipgate/translations/de.po
tine20/Sipgate/translations/fi.po
tine20/Sipgate/translations/hr_HR.po
tine20/Sipgate/translations/pl.po
tine20/Sipgate/translations/pt_BR.po
tine20/Sipgate/translations/ru.po
tine20/Sipgate/translations/sv_SE.po
tine20/Sipgate/translations/vi.po
tine20/Sipgate/translations/zh_CN.po
tine20/Sipgate/translations/zh_TW.po
tine20/Tasks/translations/de.po
tine20/Tasks/translations/et.po
tine20/Tasks/translations/fa_IR.po
tine20/Tasks/translations/fi.po
tine20/Tasks/translations/fr.po
tine20/Tasks/translations/hr_HR.po
tine20/Tasks/translations/hu.po
tine20/Tasks/translations/it.po
tine20/Tasks/translations/pl.po
tine20/Tasks/translations/ru.po
tine20/Tasks/translations/sv_SE.po
tine20/Tasks/translations/vi.po
tine20/Tasks/translations/zh_TW.po
tine20/Timetracker/translations/de.po
tine20/Timetracker/translations/es_MX.po
tine20/Timetracker/translations/et.po
tine20/Timetracker/translations/fi.po
tine20/Timetracker/translations/fr.po
tine20/Timetracker/translations/hu.po
tine20/Timetracker/translations/it.po
tine20/Timetracker/translations/pl.po
tine20/Timetracker/translations/pt_BR.po
tine20/Timetracker/translations/ru.po
tine20/Timetracker/translations/sv_SE.po
tine20/Timetracker/translations/vi.po
tine20/Timetracker/translations/zh_TW.po
tine20/Tinebase/Backend/Sql/Abstract.php
tine20/Tinebase/Backend/Sql/Command/Interface.php
tine20/Tinebase/Backend/Sql/Command/Mysql.php
tine20/Tinebase/Backend/Sql/Command/Oracle.php
tine20/Tinebase/Backend/Sql/Command/Pgsql.php
tine20/Tinebase/Config.php
tine20/Tinebase/Config/Abstract.php
tine20/Tinebase/Controller.php
tine20/Tinebase/Core.php
tine20/Tinebase/DateTime.php
tine20/Tinebase/EmailUser/Sql.php
tine20/Tinebase/FileSystem.php
tine20/Tinebase/FileSystem/StreamWrapper.php
tine20/Tinebase/Frontend/Cli.php
tine20/Tinebase/Frontend/Http.php
tine20/Tinebase/Frontend/Json.php
tine20/Tinebase/Frontend/Json/Abstract.php
tine20/Tinebase/Group.php
tine20/Tinebase/Group/Sql.php
tine20/Tinebase/Import/Abstract.php
tine20/Tinebase/Model/Alarm.php
tine20/Tinebase/Model/Filter/CustomField.php
tine20/Tinebase/Model/ModificationLog.php
tine20/Tinebase/Model/PreferenceAccountFilter.php
tine20/Tinebase/Model/PreferenceFilter.php
tine20/Tinebase/Model/State.php
tine20/Tinebase/Model/StateFilter.php [new file with mode: 0644]
tine20/Tinebase/Model/TempFileFilter.php [new file with mode: 0644]
tine20/Tinebase/Model/Tree/FileObject.php
tine20/Tinebase/Model/Tree/Node/Path.php
tine20/Tinebase/PersistentFilter.php
tine20/Tinebase/Preference/Abstract.php
tine20/Tinebase/Record/Abstract.php
tine20/Tinebase/Record/RecordSet.php
tine20/Tinebase/Scheduler/Task.php
tine20/Tinebase/Server/Cli.php
tine20/Tinebase/Setup/Update/Release7.php
tine20/Tinebase/Setup/setup.xml
tine20/Tinebase/State.php
tine20/Tinebase/TempFile.php
tine20/Tinebase/Tinebase.jsb2
tine20/Tinebase/Translation.php
tine20/Tinebase/Tree/Node.php
tine20/Tinebase/User/Sql.php
tine20/Tinebase/View.php [new file with mode: 0644]
tine20/Tinebase/css/ux/grid/GridDropZone.css [new file with mode: 0644]
tine20/Tinebase/js/AppManager.js
tine20/Tinebase/js/LoginPanel.js
tine20/Tinebase/js/MainScreen.js
tine20/Tinebase/js/data/Record.js
tine20/Tinebase/js/extFixes.js
tine20/Tinebase/js/ux/grid/GridDropZone.js [new file with mode: 0644]
tine20/Tinebase/js/widgets/customfields/FilterModel.js
tine20/Tinebase/js/widgets/dialog/EditDialog.js
tine20/Tinebase/js/widgets/dialog/MultipleEditDialogPlugin.js
tine20/Tinebase/js/widgets/dialog/PreferencesPanel.js
tine20/Tinebase/js/widgets/grid/FilterPanel.js
tine20/Tinebase/js/widgets/grid/FilterStructureTreePanel.js
tine20/Tinebase/js/widgets/grid/FilterToolbar.js
tine20/Tinebase/js/widgets/grid/GridPanel.js
tine20/Tinebase/js/widgets/grid/LinkGridPanel.js
tine20/Tinebase/js/widgets/grid/QuickaddGridPanel.js
tine20/Tinebase/js/widgets/mainscreen/WestPanel.js
tine20/Tinebase/js/widgets/persistentfilter/Model.js
tine20/Tinebase/js/widgets/relation/GenericPickerGridPanel.js
tine20/Tinebase/translations/bg.po
tine20/Tinebase/translations/ca.po
tine20/Tinebase/translations/cs.po
tine20/Tinebase/translations/da.po
tine20/Tinebase/translations/de.po
tine20/Tinebase/translations/es.po
tine20/Tinebase/translations/es_MX.po
tine20/Tinebase/translations/et.po
tine20/Tinebase/translations/fa_IR.po
tine20/Tinebase/translations/fi.po
tine20/Tinebase/translations/fr.po
tine20/Tinebase/translations/hr_HR.po
tine20/Tinebase/translations/hu.po
tine20/Tinebase/translations/it.po
tine20/Tinebase/translations/ja.po
tine20/Tinebase/translations/ko_KR.po
tine20/Tinebase/translations/lt.po
tine20/Tinebase/translations/nb.po
tine20/Tinebase/translations/nl_NL.po
tine20/Tinebase/translations/pl.po
tine20/Tinebase/translations/pt_BR.po
tine20/Tinebase/translations/ru.po
tine20/Tinebase/translations/sk.po
tine20/Tinebase/translations/sv_SE.po
tine20/Tinebase/translations/template.pot
tine20/Tinebase/translations/tr_TR.po
tine20/Tinebase/translations/vi.po
tine20/Tinebase/translations/zh_CN.po
tine20/Tinebase/translations/zh_TW.po
tine20/Tinebase/views/jsclient.php
tine20/Voipmanager/translations/es_MX.po
tine20/Voipmanager/translations/fr.po
tine20/Voipmanager/translations/ru.po
tine20/Voipmanager/translations/sv_SE.po
tine20/Voipmanager/translations/vi.po
tine20/Voipmanager/translations/zh_CN.po
tine20/Voipmanager/translations/zh_TW.po
tine20/Zend/Mail/Protocol/Sieve.php
tine20/bootstrap.php
tine20/build.xml
tine20/langHelper.php
tine20/library/ExtJS/adapter/ext/ext-base-debug.js
tine20/library/ExtJS/adapter/ext/ext-base.js
tine20/library/Syncroton/lib/Syncroton/Command/Sync.php
tine20/library/Syncroton/tests/Syncroton/Command/SyncTests.php
tine20/themes/tine20/resources/css/layout.css [moved from tine20/styles/layout.css with 98% similarity]
tine20/themes/tine20/resources/css/tine20.css [moved from tine20/styles/tine20.css with 55% similarity]
tine20/themes/tine20/resources/images/tine20/box/corners-blue.gif [moved from tine20/styles/images/tine20/box/corners-blue.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/box/corners.gif [moved from tine20/styles/images/tine20/box/corners.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/box/l-blue.gif [moved from tine20/styles/images/tine20/box/l-blue.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/box/l.gif [moved from tine20/styles/images/tine20/box/l.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/box/r-blue.gif [moved from tine20/styles/images/tine20/box/r-blue.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/box/r.gif [moved from tine20/styles/images/tine20/box/r.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/box/tb-blue.gif [moved from tine20/styles/images/tine20/box/tb-blue.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/box/tb.gif [moved from tine20/styles/images/tine20/box/tb.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/arrow.gif [moved from tine20/styles/images/tine20/button/arrow.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/btn.gif [moved from tine20/styles/images/tine20/button/btn.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/group-cs.gif [moved from tine20/styles/images/tine20/button/group-cs.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/group-lr.gif [moved from tine20/styles/images/tine20/button/group-lr.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/group-tb.gif [moved from tine20/styles/images/tine20/button/group-tb.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/s-arrow-b-noline.gif [moved from tine20/styles/images/tine20/button/s-arrow-b-noline.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/s-arrow-b.gif [moved from tine20/styles/images/tine20/button/s-arrow-b.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/s-arrow-bo.gif [moved from tine20/styles/images/tine20/button/s-arrow-bo.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/s-arrow-noline.gif [moved from tine20/styles/images/tine20/button/s-arrow-noline.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/s-arrow-o.gif [moved from tine20/styles/images/tine20/button/s-arrow-o.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/button/s-arrow.gif [moved from tine20/styles/images/tine20/button/s-arrow.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/dd/drop-add.gif [moved from tine20/styles/images/tine20/tree/drop-add.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/dd/drop-no.gif [moved from tine20/styles/images/tine20/dd/drop-no.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/dd/drop-yes.gif [moved from tine20/styles/images/tine20/dd/drop-yes.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/clear-trigger.gif [moved from tine20/styles/images/tine20/form/clear-trigger.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/clear-trigger.psd [moved from tine20/styles/images/tine20/form/clear-trigger.psd with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/date-trigger.gif [moved from tine20/styles/images/tine20/form/date-trigger.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/date-trigger.psd [moved from tine20/styles/images/tine20/form/date-trigger.psd with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/error-tip-corners.gif [moved from tine20/styles/images/tine20/form/error-tip-corners.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/exclamation.gif [moved from tine20/styles/images/tine20/form/exclamation.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/search-trigger.gif [moved from tine20/styles/images/tine20/form/search-trigger.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/search-trigger.psd [moved from tine20/styles/images/tine20/form/search-trigger.psd with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/text-bg.gif [moved from tine20/styles/images/tine20/form/text-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/trigger.gif [moved from tine20/styles/images/tine20/form/trigger.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/form/trigger.psd [moved from tine20/styles/images/tine20/form/trigger.psd with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/col-move-bottom.gif [moved from tine20/styles/images/tine20/grid/col-move-bottom.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/col-move-top.gif [moved from tine20/styles/images/tine20/grid/col-move-top.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/columns.gif [moved from tine20/styles/images/tine20/grid/columns.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/dirty.gif [moved from tine20/styles/images/tine20/grid/dirty.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid-blue-split.gif [moved from tine20/styles/images/tine20/grid/grid-blue-split.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid-hrow.gif [moved from tine20/styles/images/tine20/grid/grid-hrow.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid-split.gif [moved from tine20/styles/images/tine20/grid/grid-split.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid3-hd-btn.gif [moved from tine20/styles/images/tine20/grid/grid3-hd-btn.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid3-hrow-over.gif [moved from tine20/styles/images/tine20/grid/grid3-hrow-over.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid3-hrow.gif [moved from tine20/styles/images/tine20/grid/grid3-hrow.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid3-special-col-bg.gif [moved from tine20/styles/images/tine20/grid/grid3-special-col-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/grid3-special-col-sel-bg.gif [moved from tine20/styles/images/tine20/grid/grid3-special-col-sel-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/group-by.gif [moved from tine20/styles/images/tine20/grid/group-by.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/group-collapse.gif [moved from tine20/styles/images/tine20/grid/group-collapse.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/group-expand.gif [moved from tine20/styles/images/tine20/grid/group-expand.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/hd-pop.gif [moved from tine20/styles/images/tine20/grid/hd-pop.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/hmenu-asc.gif [moved from tine20/styles/images/tine20/grid/hmenu-asc.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/hmenu-desc.gif [moved from tine20/styles/images/tine20/grid/hmenu-desc.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/hmenu-lock.gif [moved from tine20/styles/images/tine20/grid/hmenu-lock.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/hmenu-lock.png [moved from tine20/styles/images/tine20/grid/hmenu-lock.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/hmenu-unlock.gif [moved from tine20/styles/images/tine20/grid/hmenu-unlock.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/invalid_line.gif [moved from tine20/styles/images/tine20/grid/invalid_line.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/loading.gif [moved from tine20/styles/images/tine20/tree/loading.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-first-disabled.gif [moved from tine20/styles/images/tine20/grid/page-first-disabled.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-first.gif [moved from tine20/styles/images/tine20/grid/page-first.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-last-disabled.gif [moved from tine20/styles/images/tine20/grid/page-last-disabled.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-last.gif [moved from tine20/styles/images/tine20/grid/page-last.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-next-disabled.gif [moved from tine20/styles/images/tine20/grid/page-next-disabled.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-next.gif [moved from tine20/styles/images/tine20/grid/page-next.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-prev-disabled.gif [moved from tine20/styles/images/tine20/grid/page-prev-disabled.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/page-prev.gif [moved from tine20/styles/images/tine20/grid/page-prev.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/refresh.gif [moved from tine20/styles/images/tine20/grid/refresh.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/row-check-sprite.gif [moved from tine20/styles/images/tine20/grid/row-check-sprite.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/row-expand-sprite.gif [moved from tine20/styles/images/tine20/grid/row-expand-sprite.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/row-over.gif [moved from tine20/styles/images/tine20/grid/row-over.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/sort-hd.gif [moved from tine20/styles/images/tine20/grid/sort-hd.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/sort_asc.gif [moved from tine20/styles/images/tine20/grid/sort_asc.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/grid/sort_desc.gif [moved from tine20/styles/images/tine20/grid/sort_desc.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/layout/mini-bottom.gif [moved from tine20/styles/images/tine20/layout/mini-bottom.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/layout/mini-left.gif [moved from tine20/styles/images/tine20/layout/mini-left.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/layout/mini-right.gif [moved from tine20/styles/images/tine20/layout/mini-right.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/layout/mini-top.gif [moved from tine20/styles/images/tine20/layout/mini-top.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/layout/panel-title-light-bg.gif [moved from tine20/styles/images/tine20/layout/panel-title-light-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/menu/checked.gif [moved from tine20/styles/images/tine20/menu/checked.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/menu/group-checked.gif [moved from tine20/styles/images/tine20/menu/group-checked.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/menu/item-over.gif [moved from tine20/styles/images/tine20/menu/item-over.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/menu/menu-parent.gif [moved from tine20/styles/images/tine20/menu/menu-parent.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/menu/menu.gif [moved from tine20/styles/images/tine20/menu/menu.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/menu/unchecked.gif [moved from tine20/styles/images/tine20/menu/unchecked.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/naviactive.gif [moved from tine20/styles/images/tine20/naviactive.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/panel/corners-sprite.gif [moved from tine20/styles/images/tine20/panel/corners-sprite.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/panel/left-right.gif [moved from tine20/styles/images/tine20/panel/left-right.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/panel/light-hd.gif [moved from tine20/styles/images/tine20/panel/light-hd.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/panel/tool-sprites.gif [moved from tine20/styles/images/tine20/panel/tool-sprites.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/panel/top-bottom.gif [moved from tine20/styles/images/tine20/panel/top-bottom.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/panel/top-bottom.png [moved from tine20/styles/images/tine20/panel/top-bottom.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/panel/white-top-bottom.gif [moved from tine20/styles/images/tine20/panel/white-top-bottom.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_blue_1.gif [moved from tine20/styles/images/tine20/preview/bordercorner_blue_1.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_blue_2.gif [moved from tine20/styles/images/tine20/preview/bordercorner_blue_2.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_blue_3.gif [moved from tine20/styles/images/tine20/preview/bordercorner_blue_3.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_blue_4.gif [moved from tine20/styles/images/tine20/preview/bordercorner_blue_4.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_gray_1.gif [moved from tine20/styles/images/tine20/preview/bordercorner_gray_1.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_gray_2.gif [moved from tine20/styles/images/tine20/preview/bordercorner_gray_2.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_gray_3.gif [moved from tine20/styles/images/tine20/preview/bordercorner_gray_3.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/preview/bordercorner_gray_4.gif [moved from tine20/styles/images/tine20/preview/bordercorner_gray_4.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/progress/progress-bg-y.gif [moved from tine20/styles/images/tine20/progress/progress-bg-y.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/progress/progress-bg.gif [moved from tine20/styles/images/tine20/progress/progress-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/qtip/bg.gif [moved from tine20/styles/images/tine20/qtip/bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/qtip/close.gif [moved from tine20/styles/images/tine20/qtip/close.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/qtip/tip-anchor-sprite.gif [moved from tine20/styles/images/tine20/qtip/tip-anchor-sprite.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/qtip/tip-sprite.gif [moved from tine20/styles/images/tine20/qtip/tip-sprite.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shadow-c.png [moved from tine20/styles/images/tine20/shadow-c.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shadow-lr.png [moved from tine20/styles/images/tine20/shadow-lr.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shadow.png [moved from tine20/styles/images/tine20/shadow.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shared/glass-bg.gif [moved from tine20/styles/images/tine20/shared/glass-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shared/hd-sprite.gif [moved from tine20/styles/images/tine20/shared/hd-sprite.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shared/left-btn.gif [moved from tine20/styles/images/tine20/shared/left-btn.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shared/loading-balls.gif [moved from tine20/styles/images/tine20/shared/loading-balls.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/shared/right-btn.gif [moved from tine20/styles/images/tine20/shared/right-btn.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/sizer/e-handle.gif [moved from tine20/styles/images/tine20/sizer/e-handle.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/sizer/ne-handle-dark.gif [moved from tine20/styles/images/tine20/sizer/ne-handle-dark.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/sizer/ne-handle.gif [moved from tine20/styles/images/tine20/sizer/ne-handle.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/sizer/nw-handle.gif [moved from tine20/styles/images/tine20/sizer/nw-handle.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/sizer/s-handle.gif [moved from tine20/styles/images/tine20/sizer/s-handle.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/sizer/se-handle.gif [moved from tine20/styles/images/tine20/sizer/se-handle.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/sizer/sw-handle.gif [moved from tine20/styles/images/tine20/sizer/sw-handle.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/slider/slider-bg.png [moved from tine20/styles/images/tine20/slider/slider-bg.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/slider/slider-thumb.png [moved from tine20/styles/images/tine20/slider/slider-thumb.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/slider/slider-v-bg.png [moved from tine20/styles/images/tine20/slider/slider-v-bg.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/slider/slider-v-thumb.png [moved from tine20/styles/images/tine20/slider/slider-v-thumb.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/scroll-left.gif [moved from tine20/styles/images/tine20/tabs/scroll-left.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/scroll-right.gif [moved from tine20/styles/images/tine20/tabs/scroll-right.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tab-btm-inactive-left-bg.gif [moved from tine20/styles/images/tine20/tabs/tab-btm-inactive-left-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tab-btm-inactive-right-bg.gif [moved from tine20/styles/images/tine20/tabs/tab-btm-inactive-right-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tab-btm-left-bg.gif [moved from tine20/styles/images/tine20/tabs/tab-btm-left-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tab-btm-right-bg.gif [moved from tine20/styles/images/tine20/tabs/tab-btm-right-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tab-close.gif [moved from tine20/styles/images/tine20/tabs/tab-close.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tab-strip-bg.gif [moved from tine20/styles/images/tine20/tabs/tab-strip-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tab-strip-btm-bg.gif [moved from tine20/styles/images/tine20/tabs/tab-strip-btm-bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tabs/tabs-sprite.gif [moved from tine20/styles/images/tine20/tabs/tabs-sprite.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/toolbar/bg.gif [moved from tine20/styles/images/tine20/toolbar/bg.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/toolbar/btn-arrow-light.gif [moved from tine20/styles/images/tine20/toolbar/btn-arrow-light.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/toolbar/more.gif [moved from tine20/styles/images/tine20/toolbar/more.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/arrows.gif [moved from tine20/styles/images/tine20/tree/arrows.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/drop-add.gif [moved from tine20/styles/images/tine20/dd/drop-add.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/drop-between.gif [moved from tine20/styles/images/tine20/tree/drop-between.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/drop-over.gif [moved from tine20/styles/images/tine20/tree/drop-over.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/drop-under.gif [moved from tine20/styles/images/tine20/tree/drop-under.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-end-minus-nl.gif [moved from tine20/styles/images/tine20/tree/elbow-end-minus-nl.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-end-minus.gif [moved from tine20/styles/images/tine20/tree/elbow-end-minus.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-end-plus-nl.gif [moved from tine20/styles/images/tine20/tree/elbow-end-plus-nl.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-end-plus.gif [moved from tine20/styles/images/tine20/tree/elbow-end-plus.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-end.gif [moved from tine20/styles/images/tine20/tree/elbow-end.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-line.gif [moved from tine20/styles/images/tine20/tree/elbow-line.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-minus-nl.gif [moved from tine20/styles/images/tine20/tree/elbow-minus-nl.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-minus.gif [moved from tine20/styles/images/tine20/tree/elbow-minus.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-plus-nl.gif [moved from tine20/styles/images/tine20/tree/elbow-plus-nl.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/elbow-plus.gif [moved from tine20/styles/images/tine20/tree/elbow-plus.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/folder-open.gif [moved from tine20/styles/images/tine20/tree/folder-open.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/folder.gif [moved from tine20/styles/images/tine20/tree/folder.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/leaf.gif [moved from tine20/styles/images/tine20/tree/leaf.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/tree/loading.gif [moved from tine20/styles/images/tine20/grid/loading.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/icon-error.gif [moved from tine20/styles/images/tine20/window/icon-error.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/icon-info.gif [moved from tine20/styles/images/tine20/window/icon-info.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/icon-question.gif [moved from tine20/styles/images/tine20/window/icon-question.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/icon-warning.gif [moved from tine20/styles/images/tine20/window/icon-warning.gif with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/left-corners.png [moved from tine20/styles/images/tine20/window/left-corners.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/left-corners.psd [moved from tine20/styles/images/tine20/window/left-corners.psd with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/left-right.png [moved from tine20/styles/images/tine20/window/left-right.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/left-right.psd [moved from tine20/styles/images/tine20/window/left-right.psd with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/right-corners.png [moved from tine20/styles/images/tine20/window/right-corners.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/right-corners.psd [moved from tine20/styles/images/tine20/window/right-corners.psd with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/top-bottom.png [moved from tine20/styles/images/tine20/window/top-bottom.png with 100% similarity]
tine20/themes/tine20/resources/images/tine20/window/top-bottom.psd [moved from tine20/styles/images/tine20/window/top-bottom.psd with 100% similarity]

index 6023b9a..3af033f 100755 (executable)
@@ -150,6 +150,13 @@ function activateReleaseMode()
     sed -i -e "s/Tine.clientVersion.releaseTime[^;]*/Tine.clientVersion.releaseTime = '$DATETIME'/" $TEMPDIR/tine20/Tinebase/js/tineInit.js
 }
 
+function buildLangStats()
+{
+    echo -n "building lang stats ... "
+    php -f $TEMPDIR/tine20/langHelper.php -- --statistics
+    echo "done"
+}
+
 function buildClient()
 {
     echo -n "building javascript clients ... "
@@ -223,6 +230,9 @@ function createArchives()
                     # cleanup jsb2tk
                     (cd $TEMPDIR/tine20/library/jsb2tk;  rm -rf JSBuilder2 tests)
                     
+                    # save langStats
+                    (mv $TEMPDIR/tine20/langstatistics.json $TEMPDIR/tine20/Tinebase/translations/langstatistics.json)
+                    
                     echo -n "building "
                     local FILES="Addressbook Admin Setup Tinebase Zend images library styles docs config.inc.php.dist index.php langHelper.php LICENSE PRIVACY README RELEASENOTES CREDITS setup.php tine20.php bootstrap.php worker.php"
                     (cd $TEMPDIR/tine20; tar cjf ../../packages/tine20/$RELEASE/tine20-${UCFILE}_$RELEASE.tar.bz2 $FILES)
@@ -373,6 +383,7 @@ createDirectories
 checkout "$GITURL" "$GITBRANCH"
 setupPackageDir
 activateReleaseMode
+buildLangStats
 buildClient
 createArchives
 createSpecialArchives
index 92bb0ec..a2c773a 100644 (file)
@@ -1,3 +1,9 @@
+tine20 (2013.03.2-0) natty; urgency=low
+
+  * New upstream release "Kristina" Service Release 1
+
+ -- Cornelius Weiß <c.weiss@metaways.de>  Thu, 28 Mar 2013 15:30:00 +0100
+
 tine20 (2013.03.1-0) natty; urgency=low
 
   * New upstream release "Kristina"
index c9a1b67..e700356 100644 (file)
@@ -4,7 +4,7 @@
  *
  * @package     Setup
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2008-2011 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2008-2013 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Philipp Schüle <p.schuele@metaways.de>
  *
  */
@@ -125,39 +125,45 @@ class Setup_ControllerTest extends PHPUnit_Framework_TestCase
     public function testSaveAuthenticationRedirectSettings()
     {
         $originalRedirectSettings = array(
-          Tinebase_Config::REDIRECTURL => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL, ''),
-          Tinebase_Config::REDIRECTTOREFERRER => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTTOREFERRER, '')
+            Tinebase_Config::REDIRECTURL => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL, ''),
+            Tinebase_Config::REDIRECTTOREFERRER => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTTOREFERRER, FALSE)
         );
          
         $newRedirectSettings = array(
-          Tinebase_Config::REDIRECTURL => 'http://tine20.org',
-          Tinebase_Config::REDIRECTTOREFERRER => 1
+            Tinebase_Config::REDIRECTURL => 'http://tine20.org',
+            Tinebase_Config::REDIRECTTOREFERRER => TRUE
         );
         
         $this->_uit->saveAuthentication(array('redirectSettings' => $newRedirectSettings));
         
         $storedRedirectSettings = array(
-          Tinebase_Config::REDIRECTURL => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL, ''),
-          Tinebase_Config::REDIRECTTOREFERRER => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTTOREFERRER, '')
+            Tinebase_Config::REDIRECTURL => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL),
+            Tinebase_Config::REDIRECTTOREFERRER => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTTOREFERRER)
         );
         
-        $this->assertEquals($storedRedirectSettings, $newRedirectSettings);
-        
+        $configNames = array(Tinebase_Config::REDIRECTURL, Tinebase_Config::REDIRECTTOREFERRER);
+        foreach ($configNames as $configName) {
+            $this->assertEquals($storedRedirectSettings[$configName], $newRedirectSettings[$configName],
+                'new setting should match stored settings: ' . print_r($newRedirectSettings, TRUE));
+        }
         
-        //test empty redirectUrl
+        // test empty redirectUrl
         $newRedirectSettings = array(
-          Tinebase_Config::REDIRECTURL => '',
-          Tinebase_Config::REDIRECTTOREFERRER => 0
+            Tinebase_Config::REDIRECTURL => '',
+            Tinebase_Config::REDIRECTTOREFERRER => FALSE
         );
         
         $this->_uit->saveAuthentication(array('redirectSettings' => $newRedirectSettings));
         
         $storedRedirectSettings = array(
-          Tinebase_Config::REDIRECTURL => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL, ''),
-          Tinebase_Config::REDIRECTTOREFERRER => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTTOREFERRER, '')
+            Tinebase_Config::REDIRECTURL => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTURL),
+            Tinebase_Config::REDIRECTTOREFERRER => Tinebase_Config::getInstance()->get(Tinebase_Config::REDIRECTTOREFERRER)
         );
         
-        $this->assertEquals($storedRedirectSettings, $newRedirectSettings);
+        foreach ($configNames as $configName) {
+            $this->assertEquals($storedRedirectSettings[$configName], $newRedirectSettings[$configName],
+                'new setting should match stored settings (with empty redirect URL): ' . print_r($newRedirectSettings, TRUE));
+        }
         
         $this->_uit->saveAuthentication($originalRedirectSettings);
     }
index 1c23599..7884d66 100644 (file)
@@ -4,7 +4,7 @@
  * 
  * @package     Calendar
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @copyright   Copyright (c) 2009 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2009-2013 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Cornelius Weiss <c.weiss@metaways.de>
  */
 
  */
 require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
 
-if (!defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Calendar_Backend_SqlTest::main');
-}
-
 /**
  * Test class for Calendar_Backend_Sql
  * 
@@ -24,10 +20,10 @@ if (!defined('PHPUnit_MAIN_METHOD')) {
  */
 class Calendar_Backend_SqlTest extends Calendar_TestCase
 {
-    
     public function testCreateEvent()
     {
         $event = $this->_getEvent();
+        $event->creation_time = Tinebase_DateTime::now();
         $persistentEvent = $this->_backend->create($event);
         
         $event->attendee->cal_event_id = $persistentEvent->getId();
@@ -38,6 +34,8 @@ class Calendar_Backend_SqlTest extends Calendar_TestCase
         $loadedPersitentEvent = $this->_backend->get($persistentEvent->getId());
         $this->assertEquals($event->summary, $loadedPersitentEvent->summary);
         $this->_assertAttendee($event->attendee, $loadedPersitentEvent->attendee);
+        
+        return $loadedPersitentEvent;
     }
     
     public function testUpdateEvent()
@@ -274,9 +272,30 @@ class Calendar_Backend_SqlTest extends Calendar_TestCase
         $this->assertEquals(count($_expected), count($_actual));
     }
     
-}
-    
-
-if (PHPUnit_MAIN_METHOD == 'Calendar_Backend_SqlTest::main') {
-    Calendar_Backend_SqlTest::main();
+    /**
+     * testDeleteDuplicateEvents
+     * 
+     * @see 0008182: event with lots of exceptions breaks calendar sync
+     */
+    public function testDeleteDuplicateEvents()
+    {
+        $this->_backend->deleteByProperty('Wakeup', 'summary');
+        
+        $event1 = $this->testCreateEvent();
+        sleep(1);
+        $event2 = $this->testCreateEvent();
+        sleep(1);
+        $event3 = $this->testCreateEvent();
+        
+        $filter = new Calendar_Model_EventFilter(array(array(
+            'field'    => 'summary',
+            'operator' => 'equals',
+            'value'    => 'Wakeup',
+        )));
+        $deletedDuplicates = $this->_backend->deleteDuplicateEvents($filter, FALSE);
+        
+        $this->assertGreaterThan(1, $deletedDuplicates);
+        $this->_backend->get($event1->getId());
+        $this->assertEquals(0, $event1->is_deleted);
+    }
 }
index 9cba966..83cbe20 100644 (file)
@@ -82,6 +82,24 @@ class Calendar_Controller_EventTests extends Calendar_TestCase
         Tinebase_Core::set(Tinebase_Core::USERTIMEZONE, $currentTz);
     }
     
+    public function testConcurrentUpdate()
+    {
+        $event = $this->testCreateEvent();
+        
+        sleep(1);
+        $resolvableConcurrentEvent1 = clone $event;
+        $resolvableConcurrentEvent1->dtstart = $resolvableConcurrentEvent1->dtstart->addMonth(1);
+        $resolvableConcurrentEvent1->dtend = $resolvableConcurrentEvent1->dtend->addMonth(1);
+        $resolvableConcurrentEvent1Update = $this->_controller->update($resolvableConcurrentEvent1);
+        
+        sleep(1);
+        $resolvableConcurrentEvent2 = clone $event;
+        $resolvableConcurrentEvent2->summary = 'Updated Event';
+        $resolvableConcurrentEvent2Update = $this->_controller->update($resolvableConcurrentEvent2);
+        
+        $this->assertEquals($resolvableConcurrentEvent1Update->dtstart, $resolvableConcurrentEvent2Update->dtstart);
+    }
+    
     public function testUpdateAttendeeStatus()
     {
         $event = $this->_getEvent();
index 6af2c56..0db1536 100644 (file)
@@ -335,7 +335,7 @@ class Calendar_Controller_RecurTest extends Calendar_TestCase
         $this->assertEquals(1, count($weekviewEvents), '17.6. is an exception date and must not be part of this weekview');
     }
     
-    public function testCreateRecurExceptionPreservAttendeeStatus()
+    public function testCreateRecurExceptionPreserveAttendeeStatus()
     {
         $from = new Tinebase_DateTime('2012-03-01 00:00:00');
         $until = new Tinebase_DateTime('2012-03-31 23:59:59');
index 5874a0f..4ce6db7 100644 (file)
@@ -153,13 +153,54 @@ class Calendar_Frontend_WebDAV_EventTest extends Calendar_TestCase
         
         $id = Tinebase_Record_Abstract::generateUID();
         $event = Calendar_Frontend_WebDAV_Event::create($this->objects['initialContainer'], "$id.ics", $vcalendarStream);
+        $this->_checkExdate($event);
     
+        return $event;
+    }
+    
+    /**
+     * check event exdate
+     * 
+     * @param Calendar_Frontend_WebDAV_Event $event
+     */
+    protected function _checkExdate(Calendar_Frontend_WebDAV_Event $event)
+    {
         $record = $event->getRecord();
-//         print_r($record->exdate->is_deleted);
+        $exdate = $record->exdate[0];
         $this->assertEquals('New Event', $record->summary);
-        $this->assertEquals(Tinebase_Core::getUser()->contact_id, $record->exdate[0]->organizer);
-        $this->assertEquals(Tinebase_Core::getUser()->contact_id, $record->exdate[0]->attendee[0]->user_id);
-        return $event;
+        $this->assertEquals(Tinebase_Core::getUser()->contact_id, $exdate->organizer,
+            'organizer mismatch, expected :' . print_r(Addressbook_Controller_Contact::getInstance()->get(Tinebase_Core::getUser()->contact_id)->toArray(), TRUE) .
+            'got: ' . print_r(Addressbook_Controller_Contact::getInstance()->get($exdate->organizer)->toArray(), TRUE));
+        $this->assertTrue(in_array(Tinebase_Core::getUser()->contact_id, $exdate->attendee->user_id), 'user contact id not found in exdate attendee: ' . print_r($exdate->attendee->toArray(), TRUE));
+        foreach ($exdate->attendee as $attender) {
+            $this->assertTrue(! empty($attender->displaycontainer_id), 'displaycontainer_id not set for attender: ' . print_r($attender->toArray(), TRUE));
+        }
+    }
+    
+    /**
+     * testCreateRepeatingEventAndPutExdate
+     * 
+     * @see 0008172: displaycontainer_id not set when recur exception is created
+     */
+    public function testCreateRepeatingEventAndPutExdate()
+    {
+        if (!empty($_SERVER['HTTP_USER_AGENT'])) {
+            $oldUserAgent = $_SERVER['HTTP_USER_AGENT'];
+        }
+        
+        $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.21) Gecko/20110831 Lightning/1.0b2 Thunderbird/3.1.13';
+        
+        $vcalendarStream = $this->_getVCalendar(dirname(__FILE__) . '/../../Import/files/lightning_repeating_weekly.ics');
+        $id = '353de608-4b50-41e6-9f6c-35889584fe8d';
+        $event = Calendar_Frontend_WebDAV_Event::create($this->objects['initialContainer'], "$id.ics", $vcalendarStream);
+        $existingEvent = $event->getRecord();
+        
+        // put exception
+        $vcalendarStreamException = $this->_getVCalendar(dirname(__FILE__) . '/../../Import/files/lightning_repeating_weekly_exception.ics');
+        $event = new Calendar_Frontend_WebDAV_Event($this->objects['initialContainer'], $existingEvent);
+        $event->put($vcalendarStreamException);
+        
+        $this->_checkExdate($event);
     }
     
     /**
@@ -604,14 +645,23 @@ class Calendar_Frontend_WebDAV_EventTest extends Calendar_TestCase
     {
         $vcalendar = file_get_contents($_filename);
         
+        $unittestUserEmail = Tinebase_Core::getUser()->accountEmailAddress;
         $vcalendar = preg_replace(
             array(
                 '/l.kneschke@metaway\n s.de/', 
-                '/pwulf\n @tine20.org/'
+                '/unittest@\n tine20.org/',
+                '/un\n ittest@tine20.org/',
+                '/unittest@tine20.org/',
+                '/unittest@ti\n ne20.org/',
+                '/pwulf\n @tine20.org/',
             ), 
             array(
-                Tinebase_Core::getUser()->accountEmailAddress, 
-                array_value('pwulf', Zend_Registry::get('personas'))->accountEmailAddress
+                $unittestUserEmail,
+                $unittestUserEmail,
+                $unittestUserEmail,
+                $unittestUserEmail,
+                $unittestUserEmail,
+                array_value('pwulf', Zend_Registry::get('personas'))->accountEmailAddress,
             ), 
             $vcalendar
         );
diff --git a/tests/tine20/Calendar/Import/files/lightning_repeating_weekly.ics b/tests/tine20/Calendar/Import/files/lightning_repeating_weekly.ics
new file mode 100644 (file)
index 0000000..cf09bff
--- /dev/null
@@ -0,0 +1,33 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20130416T130532Z
+LAST-MODIFIED:20130416T130536Z
+DTSTAMP:20130416T130536Z
+UID:353de608-4b50-41e6-9f6c-35889584fe8d
+SUMMARY:New Event
+RRULE:FREQ=WEEKLY
+DTSTART;TZID=Europe/Berlin:20130416T153000
+DTEND;TZID=Europe/Berlin:20130416T163000
+CLASS:PUBLIC
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
diff --git a/tests/tine20/Calendar/Import/files/lightning_repeating_weekly_exception.ics b/tests/tine20/Calendar/Import/files/lightning_repeating_weekly_exception.ics
new file mode 100644 (file)
index 0000000..7441f3d
--- /dev/null
@@ -0,0 +1,64 @@
+BEGIN:VCALENDAR
+PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
+VERSION:2.0
+BEGIN:VTIMEZONE
+TZID:Europe/Berlin
+X-LIC-LOCATION:Europe/Berlin
+BEGIN:DAYLIGHT
+TZOFFSETFROM:+0100
+TZOFFSETTO:+0200
+TZNAME:CEST
+DTSTART:19700329T020000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
+END:DAYLIGHT
+BEGIN:STANDARD
+TZOFFSETFROM:+0200
+TZOFFSETTO:+0100
+TZNAME:CET
+DTSTART:19701025T030000
+RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
+END:STANDARD
+END:VTIMEZONE
+BEGIN:VEVENT
+CREATED:20130416T130537Z
+LAST-MODIFIED:20130416T130545Z
+DTSTAMP:20130416T130545Z
+UID:353de608-4b50-41e6-9f6c-35889584fe8d
+SUMMARY:New Event
+STATUS:CONFIRMED
+ORGANIZER;CN="Admin Account, Tine 2.0";EMAIL=unittest@tine20.org:mailto:un
+ ittest@tine20.org
+ATTENDEE;RSVP=FALSE;CN="Admin Account, Tine 2.0";PARTSTAT=ACCEPTED;CUTYPE=
+ INDIVIDUAL;ROLE=REQ-PARTICIPANT;EMAIL=unittest@tine20.org:mailto:unittest@
+ tine20.org
+RRULE:FREQ=WEEKLY
+DTSTART;TZID=Europe/Berlin:20130416T153000
+DTEND;TZID=Europe/Berlin:20130416T163000
+SEQUENCE:0
+CLASS:PUBLIC
+TRANSP:OPAQUE
+X-TINE20-CONTAINER:41
+X-MOZ-GENERATION:1
+END:VEVENT
+BEGIN:VEVENT
+CREATED:20130416T130539Z
+LAST-MODIFIED:20130416T130545Z
+DTSTAMP:20130416T130545Z
+UID:353de608-4b50-41e6-9f6c-35889584fe8d
+SUMMARY:New Event
+STATUS:CONFIRMED
+RECURRENCE-ID;TZID=Europe/Berlin:20130423T153000
+ORGANIZER;CN="Admin Account, Tine 2.0";PARTSTAT=DECLINED;EMAIL=unittest@ti
+ ne20.org:mailto:unittest@tine20.org
+ATTENDEE;RSVP=FALSE;CN="Admin Account, Tine 2.0";PARTSTAT=ACCEPTED;CUTYPE=
+ INDIVIDUAL;ROLE=REQ-PARTICIPANT;EMAIL=unittest@tine20.org:mailto:unittest@
+ tine20.org
+DTSTART;TZID=Europe/Berlin:20130423T153000
+DTEND;TZID=Europe/Berlin:20130423T163000
+SEQUENCE:0
+CLASS:PUBLIC
+TRANSP:OPAQUE
+X-TINE20-CONTAINER:41
+X-MOZ-GENERATION:1
+END:VEVENT
+END:VCALENDAR
\ No newline at end of file
index 4b3a5c2..4b4d671 100644 (file)
@@ -49,13 +49,15 @@ class Calendar_JsonTests extends Calendar_TestCase
     
     /**
      * testCreateEvent
+     * 
+     * @param $now should the current date be used
      */
-    public function testCreateEvent()
+    public function testCreateEvent($now = FALSE)
     {
         $scleverDisplayContainerId = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::DEFAULTCALENDAR, $this->_personas['sclever']->getId());
         $contentSeqBefore = Tinebase_Container::getInstance()->getContentSequence($scleverDisplayContainerId);
         
-        $eventData = $this->_getEvent()->toArray();
+        $eventData = $this->_getEvent($now)->toArray();
         
         $tag = Tinebase_Tags::getInstance()->createTag(new Tinebase_Model_Tag(array(
             'name' => 'phpunit-' . substr(Tinebase_Record_Abstract::generateUID(), 0, 10),
@@ -84,7 +86,7 @@ class Calendar_JsonTests extends Calendar_TestCase
     
     public function testStripWindowsLinebreaks()
     {
-        $e = $this->_getEvent();
+        $e = $this->_getEvent(TRUE);
         $e->description = 'Hello my friend,' . chr(13) . chr(10) .'bla bla bla.'  . chr(13) . chr(10) .'good bye.';
         $persistentEventData = $this->_uit->saveEvent($e->toArray());
         $loadedEventData = $this->_uit->getEvent($persistentEventData['id']);
@@ -97,7 +99,7 @@ class Calendar_JsonTests extends Calendar_TestCase
     public function testCreateEventWithNonExistantAttender()
     {
         $testEmail = 'unittestnotexists@example.org';
-        $eventData = $this->_getEvent()->toArray();
+        $eventData = $this->_getEvent(TRUE)->toArray();
         $eventData['attendee'][] = $this->_getUserTypeAttender($testEmail);
         
         $persistentEventData = $this->_uit->saveEvent($eventData);
@@ -133,7 +135,7 @@ class Calendar_JsonTests extends Calendar_TestCase
      */
     public function testCreateEventWithAlarm()
     {
-        $eventData = $this->_getEventWithAlarm()->toArray();
+        $eventData = $this->_getEventWithAlarm(TRUE)->toArray();
         $persistentEventData = $this->_uit->saveEvent($eventData);
         $loadedEventData = $this->_uit->getEvent($persistentEventData['id']);
         
@@ -216,7 +218,7 @@ class Calendar_JsonTests extends Calendar_TestCase
      */
     public function testSearchEvents()
     {
-        $eventData = $this->testCreateEvent();
+        $eventData = $this->testCreateEvent(TRUE); 
         
         $filter = array(
             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId()),
@@ -252,6 +254,24 @@ class Calendar_JsonTests extends Calendar_TestCase
         
         $this->_assertJsonEvent($eventData, $resultEventData, 'failed to search event');
     }
+    
+    /**
+     * #7688: Internal Server Error on calendar search
+     * 
+     * add period filter if none is given
+     * 
+     * https://forge.tine20.org/mantisbt/view.php?id=7688
+     */
+    public function testSearchEventsWithOutPeriodFilter()
+    {
+        $eventData = $this->testCreateRecurEvent();
+        $filter = array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId()));
+        
+        $searchResultData = $this->_uit->searchEvents($filter, array());
+        $returnedFilter = $searchResultData['filter'];
+        $this->assertEquals(2, count($returnedFilter), 'Two filters shoud have been returned!');
+        $this->assertTrue($returnedFilter[1]['field'] == 'period' || $returnedFilter[0]['field'] == 'period', 'One returned filter shoud be a period filter');
+    }
 
     /**
      * testSearchEvents with organizer = me filter
@@ -260,7 +280,7 @@ class Calendar_JsonTests extends Calendar_TestCase
      */
     public function testSearchEventsWithOrganizerMeFilter()
     {
-        $eventData = $this->testCreateEvent();
+        $eventData = $this->testCreateEvent(TRUE);
         
         $filter = array(
             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId()),
@@ -282,7 +302,7 @@ class Calendar_JsonTests extends Calendar_TestCase
      */
     public function testSearchEventsWithAlarm()
     {
-        $eventData = $this->_getEventWithAlarm()->toArray();
+        $eventData = $this->_getEventWithAlarm(TRUE)->toArray();
         $persistentEventData = $this->_uit->saveEvent($eventData);
         
         $filter = array(
@@ -443,6 +463,61 @@ class Calendar_JsonTests extends Calendar_TestCase
     }
     
     /**
+     * testCreateRecurExceptionWithOtherUser
+     * 
+     * @see 0008172: displaycontainer_id not set when recur exception is created
+     */
+    public function testCreateRecurExceptionWithOtherUser()
+    {
+        $recurSet = array_value('results', $this->testSearchRecuringIncludes());
+        
+        // create persistent exception (just status update)
+        $persistentException = $recurSet[1];
+        $scleverAttender = $this->_findAttender($persistentException['attendee'], 'sclever');
+        $attendeeBackend = new Calendar_Backend_Sql_Attendee();
+        $status_authkey = $attendeeBackend->get($scleverAttender['id'])->status_authkey;
+        $scleverAttender['status'] = Calendar_Model_Attender::STATUS_ACCEPTED;
+        $scleverAttender['status_authkey'] = $status_authkey;
+        foreach ($persistentException['attendee'] as $key => $attender) {
+            if ($attender['id'] === $scleverAttender['id']) {
+                $persistentException['attendee'][$key] = $scleverAttender;
+                break;
+            }
+        }
+        
+        // sclever has only READ grant
+        Tinebase_Container::getInstance()->setGrants($this->_testCalendar, new Tinebase_Record_RecordSet('Tinebase_Model_Grants', array(array(
+            'account_id'    => $this->_testUser->getId(),
+            'account_type'  => 'user',
+            Tinebase_Model_Grants::GRANT_READ     => true,
+            Tinebase_Model_Grants::GRANT_ADD      => true,
+            Tinebase_Model_Grants::GRANT_EDIT     => true,
+            Tinebase_Model_Grants::GRANT_DELETE   => true,
+            Tinebase_Model_Grants::GRANT_PRIVATE  => true,
+            Tinebase_Model_Grants::GRANT_ADMIN    => true,
+            Tinebase_Model_Grants::GRANT_FREEBUSY => true,
+        ), array(
+            'account_id'    => $this->_personas['sclever']->getId(),
+            'account_type'  => 'user',
+            Tinebase_Model_Grants::GRANT_READ     => true,
+            Tinebase_Model_Grants::GRANT_FREEBUSY => true,
+        ))), TRUE);
+        
+        $unittestUser = Tinebase_Core::getUser();
+        Tinebase_Core::set(Tinebase_Core::USER, $this->_personas['sclever']);
+        
+        // create persistent exception
+        $createdException = $this->_uit->createRecurException($persistentException, FALSE, FALSE);
+        Tinebase_Core::set(Tinebase_Core::USER, $unittestUser);
+        
+        $sclever = $this->_findAttender($createdException['attendee'], 'sclever');
+        $this->assertEquals('Susan Clever', $sclever['user_id']['n_fn']);
+        $this->assertEquals(Calendar_Model_Attender::STATUS_ACCEPTED, $sclever['status'], 'status mismatch: ' . print_r($sclever, TRUE));
+        $this->assertTrue(is_array($sclever['displaycontainer_id']));
+        $this->assertEquals($this->_personasDefaultCals['sclever']['id'], $sclever['displaycontainer_id']['id']);
+    }
+    
+    /**
      * testUpdateRecurSeries
      */
     public function testUpdateRecurSeries()
@@ -547,7 +622,7 @@ class Calendar_JsonTests extends Calendar_TestCase
      */
     public function testMeAsAttenderFilter()
     {
-        $eventData = $this->testCreateEvent();
+        $eventData = $this->testCreateEvent(TRUE);
         
         $filter = array(
             array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId()),
@@ -586,7 +661,7 @@ class Calendar_JsonTests extends Calendar_TestCase
             Tinebase_Model_Grants::GRANT_FREEBUSY => true,
         ))), TRUE);
         
-        $eventData = $this->testCreateEvent();
+        $eventData = $this->testCreateEvent(TRUE);
         $eventData['container_id'] = $this->_personasDefaultCals['sclever']->getId();
         $eventData['attendee'] = array(array(
             'user_id' => $this->_personasContacts['sclever']->getId()
@@ -866,7 +941,7 @@ class Calendar_JsonTests extends Calendar_TestCase
         $editableResoureData = $this->testSaveResource();
         $nonEditableResoureData = $this->testSaveResource(array('readGrant'));
         
-        $event = $this->_getEvent();
+        $event = $this->_getEvent(TRUE);
         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(
             array(
                 'user_type'  => Calendar_Model_Attender::USERTYPE_RESOURCE,
index a3ec0ed..0af1925 100644 (file)
@@ -76,7 +76,6 @@ abstract class Calendar_TestCase extends PHPUnit_Framework_TestCase
     public function setUp()
     {
         $this->_transactionId = Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
-        
         $this->_backend = new Calendar_Backend_Sql();
         
         $this->_personas = Zend_Registry::get('personas');
@@ -130,10 +129,11 @@ abstract class Calendar_TestCase extends PHPUnit_Framework_TestCase
     
     /**
      * returns a simple event
-     *
+     * 
+     * @param bool $now
      * @return Calendar_Model_Event
      */
-    protected function _getEvent($_now=FALSE)
+    protected function _getEvent($now = FALSE)
     {
         $event = new Calendar_Model_Event(array(
             'summary'     => 'Wakeup',
@@ -151,7 +151,7 @@ abstract class Calendar_TestCase extends PHPUnit_Framework_TestCase
             Tinebase_Model_Grants::GRANT_DELETE  => true,
         ));
         
-        if ($_now) {
+        if ($now) {
             $event->dtstart = Tinebase_DateTime::now();
             $event->dtend = Tinebase_DateTime::now()->addMinute(15);
         }
@@ -162,13 +162,12 @@ abstract class Calendar_TestCase extends PHPUnit_Framework_TestCase
     /**
      * returns a simple event
      *
+     * @param bool $now use date of now
      * @return Calendar_Model_Event
-     * 
-     * @todo add options?
      */
-    protected function _getEventWithAlarm()
+    protected function _getEventWithAlarm($now = FALSE)
     {
-        $event = $this->_getEvent();
+        $event = $this->_getEvent($now);
         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(
             array(
                 'minutes_before'    => 0
index 959607f..0cc8bbe 100644 (file)
@@ -284,7 +284,7 @@ class Courses_JsonTest extends PHPUnit_Framework_TestCase
         $pref = $coursesPrefs['results'][0];
         
         $this->assertEquals(Tinebase_Preference_Abstract::DEFAULTPERSISTENTFILTER, $pref['name']);
-        $this->assertEquals(2, count($pref['options']));
+        $this->assertGreaterThanOrEqual(2, count($pref['options']));
     }
 
     /**
index 7a9f962..e596b1d 100644 (file)
@@ -1362,6 +1362,19 @@ class Felamimail_Controller_MessageTest extends PHPUnit_Framework_TestCase
         $cachedMessage = $this->messageTestHelper('mw_newsletter_multipart_related.eml');
     }
     
+    /**
+     * testFacebookNotification
+     * 
+     * @see 0008016: links in facebook/twitter emails are removed
+     */
+    public function testFacebookNotification()
+    {
+        $cachedMessage = $this->messageTestHelper('facebook_notification.eml');
+        $message = $this->_controller->getCompleteMessage($cachedMessage);
+        
+        $this->assertContains('http://www.facebook.com/n/?notifications&amp;id=295475095891&amp;'
+            . 'mid=7a0ffadG5af33a8a9c98Ga61c449Gdd&amp;bcode=1.1362559617.Abl6w95TdWQc0VVS&amp;n_m=tine20%40metaways.de', $message->body);
+    }
     
     /********************************* protected helper funcs *************************************/
     
index b9376c9..57da6e5 100644 (file)
@@ -948,6 +948,8 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
     
     /**
      * set and get vacation sieve script
+     * 
+     * @see 0007768: Sieve - Vacation notify frequency not being set (Cyrus)
      */
     public function testGetSetVacation()
     {
@@ -986,7 +988,7 @@ class Felamimail_JsonTest extends PHPUnit_Framework_TestCase
             'id'                    => $this->_account->getId(),
             'subject'               => 'unittest vacation subject',
             'from'                  => $this->_account->from . ' <' . $this->_account->email . '>',
-            'days'                  => 7,
+            'days'                  => 3,
             'enabled'               => TRUE,
             'reason'                => 'unittest vacation message<br /><br />signature',
             'mime'                  => NULL,
index 717c051..814863f 100644 (file)
@@ -102,4 +102,19 @@ class Felamimail_Model_MessageTest extends PHPUnit_Framework_TestCase
             . '<blockquote class="felamimail-body-blockquote"><blockquote class="felamimail-body-blockquote">lala<br />'
             . '</blockquote><br />xyz<br /></blockquote></blockquote><br /><br /><blockquote class="felamimail-body-blockquote">jojo<br /></blockquote>jojo<br />', $result);
     }
+    
+    /**
+     * testReplaceUris
+     * 
+     * @see 0008020: link did not get an anchor in html mail
+     */
+    public function testReplaceUris()
+    {
+        $message = new Felamimail_Model_Message(array(
+            'body'  =>  'http://www.facebook.com/media/set/?set=a.164136103742229.1073741825.100004375207149&type=1&l=692e495b17'
+        ));
+        
+        $result = Felamimail_Message::replaceUris($message->body);
+        $this->assertContains('a href=', $result);
+    }
 }
diff --git a/tests/tine20/Felamimail/files/facebook_notification.eml b/tests/tine20/Felamimail/files/facebook_notification.eml
new file mode 100644 (file)
index 0000000..bf767fd
--- /dev/null
@@ -0,0 +1,178 @@
+Return-Path: <notification+zj4oafzf6coc@facebookmail.com>\r
+Received: from mail02.metaways.net ([10.129.3.249])\r
+       by mail03.metaways.net (Dovecot) with LMTP id zXoaJkYCN1FwTwAA5ANymA\r
+       ; Wed, 06 Mar 2013 09:47:07 +0100\r
+Received: from mx02.metaways.net ([127.0.0.1])\r
+       by mail02.metaways.net (Dovecot) with LMTP id 4jigNYsCN1G1dgAAk4785w\r
+       ; Wed, 06 Mar 2013 09:47:07 +0100\r
+Received: from mx-out.facebook.com (outmail024.snc7.facebook.com [69.171.232.158])\r
+       by mx02.metaways.net (Postfix) with ESMTP id 5258D4063\r
+       for <unittest@tine20.org>; Wed,  6 Mar 2013 09:47:05 +0100 (CET)\r
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=facebookmail.com;\r
+       s=s1024-2011-q2; t=1362559618;\r
+       bh=DR8jvSJgyVskh9A9cfeuH6S6sZYAjI19Q7WNL/ip3r4=;\r
+       h=Date:To:From:Subject:MIME-Version:Content-Type;\r
+       b=aAkyDobBhyJgAzHhIKpd4tQGCe/Y2Z8J9/TPhbB/TouGuXxEn576wVKOhjYZjrlLp\r
+        ClM6NaO4T/xYsdDNKsGatkPZpN1QJHumsmXiViKjbybslLFCh4EdDpjysLpkbKcGt7\r
+        ZuuOZFmIKUzyn0qs+uUanfwD6aXO6pxNNE6jsHY4=\r
+Received: from [10.216.118.91] ([10.216.118.91:48339])\r
+       by smout021.snc7.facebook.com (envelope-from <notification+zj4oafzf6coc@facebookmail.com>)\r
+       (ecelerity 3.5.1.37927 r(/root/Momo-dev:tip)) with ECSTREAM\r
+       id 25/F4-15373-28207315; Wed, 06 Mar 2013 00:46:58 -0800\r
+X-Facebook: from zuckmail ([MTI3LjAuMC4x]) \r
+       by www.facebook.com with HTTP (ZuckMail);\r
+Date: Wed, 6 Mar 2013 00:46:57 -0800\r
+To: unittest@tine20.org\r
+From: "Facebook" <notification+zj4oafzf6coc@facebookmail.com>\r
+Reply-to: Facebook <notification+zj4oafzf6coc@facebookmail.com>\r
+Subject: =?UTF-8?B?Qm9qYW4gUmFmbGUgZ2Vm?=\r
+ =?UTF-8?B?w6RsbHQgVGluZSAyLjA=?=\r
+Message-ID: <1c0e681cd9a1b29b656550de8da3af37@www.facebook.com>\r
+X-Priority: 3\r
+X-Mailer: ZuckMail [version 1.00]\r
+Errors-To: notification+zj4oafzf6coc@facebookmail.com\r
+X-Facebook-Notify: page_new_likes; mailid=7a0ffadG5af33a8a9c98Ga61c449Gdd\r
+X-FACEBOOK-PRIORITY: 0\r
+X-Auto-Response-Suppress: All\r
+MIME-Version: 1.0\r
+Content-Type: multipart/alternative;\r
+       boundary="b1_1c0e681cd9a1b29b656550de8da3af37"\r
+X-Spam-Status: No, score=-0.1 required=5.0 tests=AWL,DKIM_SIGNED,DKIM_VALID,\r
+       DKIM_VALID_AU,HTML_MESSAGE,T_REMOTE_IMAGE autolearn=disabled version=3.3.1\r
+X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail02.metaways.net\r
+X-Tine20TestMessage: facebook_notification.eml\r
+\r
+\r
+--b1_1c0e681cd9a1b29b656550de8da3af37\r
+Content-Type: text/plain; charset="UTF-8"\r
+Content-Transfer-Encoding: quoted-printable\r
+\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r
+http://www.facebook.com/n/?tine20org&mid=3D7a0ffadG5af33a8a9c98Ga61c449Gdd=\r
+&bcode=3D1.1362559617.Abl6w95TdWQc0VVS&n_m=3Dtine20%40metaways.de\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r
+\r
+Hallo,\r
+\r
+firstname lastname gef=C3=A4llt Tine 2.0.\r
+\r
+Gr=C3=BC=C3=9Fe,\r
+Das Facebook-Team\r
+\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=\r
+=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D\r
+Diese Nachricht wurde an unittest@tine20.org gesendet. Falls du diese =\r
+E-Mails in Zukunft nicht von Facebook erhalten m=C3=B6chtest, folge dem =\r
+Link unten, um sie abzubestellen.\r
+http://www.facebook.com/o.php?k=3DAS0kfnK7FOKXeB5X&u=3D100000705715352&mid=\r
+=3D7a0ffadG5af33a8a9c98Ga61c449Gdd\r
+Facebook, Inc., Attention: Department 415, PO Box 10005, Palo Alto, CA =\r
+94303\r
+\r
+\r
+--b1_1c0e681cd9a1b29b656550de8da3af37\r
+Content-Type: text/html; charset="UTF-8"\r
+Content-Transfer-Encoding: quoted-printable\r
+\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional =\r
+//EN"><html><head><title>Facebook</title><meta http-equiv=3D"Content-Type" =\r
+content=3D"text/html; charset=3Dutf-8" /></head><body style=3D"margin: 0; =\r
+padding: 0;" dir=3D"ltr"><table cellspacing=3D"0" cellpadding=3D"0" =\r
+id=3D"email_table" style=3D"border-collapse:collapse;width:98%;" =\r
+border=3D"0"><tr><td id=3D"email_content" =\r
+style=3D"font-size:12px;font-family:&#039;lucida =\r
+grande&#039;,tahoma,verdana,arial,sans-serif;"><table cellspacing=3D"0" =\r
+cellpadding=3D"0" style=3D"border-collapse:collapse;width:620px;"><tr><td =\r
+style=3D"font-size:16px;font-family:&#039;lucida grande&#039;,tahoma,verda=\r
+na,arial,sans-serif;background:#3b5998;color:#FFFFFF;font-weight:bold;vert=\r
+ical-align:baseline;letter-spacing:-0.03em;text-align:left;padding:10px =\r
+38px 4px;"><a style=3D"text-decoration: none;" href=3D"http://www.facebook=\r
+.com/n/?tine20org&amp;mid=3D7a0ffadG5af33a8a9c98Ga61c449Gdd&amp;bcode=3D1.=\r
+1362559617.Abl6w95TdWQc0VVS&amp;n_m=3Dtine20%40metaways.de"><span =\r
+style=3D"background:#3b5998;color:#FFFFFF;font-weight:bold;font-family:&#0=\r
+39;lucida =\r
+grande&#039;,tahoma,verdana,arial,sans-serif;vertical-align:middle; =\r
+font-size:16px;letter-spacing:-0.03em;text-align:left;vertical-align:basel=\r
+ine;">facebook</span></a></td></tr></table><table cellspacing=3D"0" =\r
+cellpadding=3D"0" style=3D"border-collapse:collapse;width:620px;"><tr><td =\r
+style=3D"font-size:11px;font-family:LucidaGrande,tahoma,verdana,arial,sans=\r
+-serif;padding:10px 25px;background-color:#fff;border-left:1px solid =\r
+#ccc;border-right:1px solid #ccc;border-top:1px solid =\r
+#ccc;border-bottom:1px solid #ccc;color:#333333;"><table cellspacing=3D"0" =\r
+cellpadding=3D"0" width=3D"100%" =\r
+style=3D"border-collapse:collapse;"><tr><td style=3D"font-size:11px;font-f=\r
+amily:LucidaGrande,tahoma,verdana,arial,sans-serif;padding:10px =\r
+25px;color:#333333;width:620px;"><table cellspacing=3D"0" =\r
+cellpadding=3D"0" width=3D"100%" =\r
+style=3D"border-collapse:collapse;"><tr><td style=3D"font-size:11px;font-f=\r
+amily:LucidaGrande,tahoma,verdana,arial,sans-serif;padding-bottom:10px;"><=\r
+table cellspacing=3D"0" cellpadding=3D"0" =\r
+style=3D"border-collapse:collapse;"><tr><td valign=3D"top" =\r
+style=3D"padding-right:10px;font-size: 0px;"><a href=3D"http://www.faceboo=\r
+k.com/n/?rafle&amp;mid=3D7a0ffadG5af33a8a9c98Ga61c449Gdd&amp;bcode=3D1.136=\r
+2559617.Abl6w95TdWQc0VVS&amp;n_m=3Dtine20%40metaways.de" =\r
+style=3D"color:#3b5998;text-decoration:none;"><img src=3D"http://profile.a=\r
+k.fbcdn.net/hprofile-ak-ash4/274974_663397731_151710037_q.jpg" =\r
+style=3D"border:0;" /></a></td><td valign=3D"top" =\r
+style=3D"width:100%;"><span style=3D"font-size: 13px;">firstname lastname =\r
+gef=C3=A4llt Tine 2.0.</span></td></tr></table></td></tr><tr><td =\r
+style=3D"font-size:11px;font-family:LucidaGrande,tahoma,verdana,arial,sans=\r
+-serif;"><table cellspacing=3D"0" cellpadding=3D"0" border=3D"0" =\r
+style=3D"border-collapse:collapse;width:100%;"><tr><td =\r
+style=3D"font-size:11px;font-family:LucidaGrande,tahoma,verdana,arial,sans=\r
+-serif;padding:10px;background-color:#f2f2f2;border-left:none;border-right=\r
+:none;border-top:1px solid #ccc;border-bottom:1px solid #ccc;"><table =\r
+cellspacing=3D"0" cellpadding=3D"0" =\r
+style=3D"border-collapse:collapse;"><tr><td style=3D"font-size:11px;font-f=\r
+amily:LucidaGrande,tahoma,verdana,arial,sans-serif;padding-right:10px;"><t=\r
+able cellspacing=3D"0" cellpadding=3D"0" =\r
+style=3D"border-collapse:collapse;"><tr><td style=3D"border-width: =\r
+1px;border-style: solid;border-color: #29447E #29447E =\r
+#1a356e;background-color: #5b74a8;"><table cellspacing=3D"0" =\r
+cellpadding=3D"0" style=3D"border-collapse:collapse;"><tr><td =\r
+style=3D"font-size:11px;font-family:LucidaGrande,tahoma,verdana,arial,sans=\r
+-serif;padding:2px 6px 4px;border-top:1px solid #8a9cc2;"><a =\r
+href=3D"http://www.facebook.com/n/?tine20org&amp;mid=3D7a0ffadG5af33a8a9c9=\r
+8Ga61c449Gdd&amp;bcode=3D1.1362559617.Abl6w95TdWQc0VVS&amp;n_m=3Dtine20%40=\r
+metaways.de" style=3D"color:#3b5998;text-decoration:none;"><span =\r
+style=3D"font-weight:bold;white-space:nowrap;color: #fff;font-size: =\r
+11px;">Aktualisiere Tine =\r
+2.0</span></a></td></tr></table></td></tr></table></td><td =\r
+style=3D"font-size:11px;font-family:LucidaGrande,tahoma,verdana,arial,sans=\r
+-serif;"><table cellspacing=3D"0" cellpadding=3D"0" =\r
+style=3D"border-collapse:collapse;"><tr><td style=3D"border-width: =\r
+1px;border-style: solid;border-color: #999 #999 #888;background-color: =\r
+#eee;"><table cellspacing=3D"0" cellpadding=3D"0" =\r
+style=3D"border-collapse:collapse;"><tr><td style=3D"font-size:11px;font-f=\r
+amily:LucidaGrande,tahoma,verdana,arial,sans-serif;padding:2px 6px =\r
+4px;border-top:1px solid #fff;"><a href=3D"http://www.facebook.com/n/?noti=\r
+fications&amp;id=3D295475095891&amp;mid=3D7a0ffadG5af33a8a9c98Ga61c449Gdd&=\r
+amp;bcode=3D1.1362559617.Abl6w95TdWQc0VVS&amp;n_m=3Dtine20%40metaways.de" =\r
+style=3D"color:#3b5998;text-decoration:none;"><span =\r
+style=3D"font-weight:bold;white-space:nowrap;color: #333;font-size: =\r
+11px;">Alle Benachrichtigungen anzeigen</span></a></td></tr></table></td><=\r
+/tr></table></td></tr></table></td></tr></table></td></tr></table></td></t=\r
+r></table></td></tr></table><table cellspacing=3D"0" cellpadding=3D"0" =\r
+border=3D"0" style=3D"border-collapse:collapse;width:620px;"><tr><td =\r
+style=3D"font-size:11px;font-family:&#039;lucida grande&#039;, tahoma, =\r
+verdana, arial, sans-serif;padding:10px;background-color:#fff;border-left:=\r
+none;border-right:none;border-top:none;border-bottom:none;color:#999999;bo=\r
+rder:none;">Diese Nachricht wurde an <a =\r
+href=3D"mailto:tine20&#064;metaways.de" =\r
+style=3D"color:#3b5998;text-decoration:none;">tine20&#064;metaways.de</a> =\r
+gesendet. Falls du diese E-Mails in Zukunft nicht von Facebook erhalten =\r
+m=C3=B6chtest, <a href=3D"http://www.facebook.com/o.php?k=3DAS0kfnK7FOKXeB=\r
+5X&amp;u=3D100000705715352&amp;mid=3D7a0ffadG5af33a8a9c98Ga61c449Gdd" =\r
+style=3D"color:#3b5998;text-decoration:none;">bestelle sie ab</a>.<br =\r
+/>Facebook, Inc., Attention: Department 415, PO Box 10005, Palo Alto, CA =\r
+94303</td></tr></table><span style=3D"width:620px;"><img =\r
+src=3D"http://www.facebook.com/email_open_log_pic.php?mid=3D7a0ffadG5af33a=\r
+8a9c98Ga61c449Gdd" style=3D"border:0;width:1px;height:1px;" =\r
+/></span></td></tr></table></body></html>\r
+\r
+\r
+\r
+--b1_1c0e681cd9a1b29b656550de8da3af37--\r
+\r
index c63c6a2..e489c05 100644 (file)
@@ -4,7 +4,7 @@
  * 
  * @package     Filemanager
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2010-2010 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2010-2013 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
  */
 require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'TestHelper.php';
 
-if (! defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Filemanager_AllTests::main');
-}
-
 class Filemanager_AllTests
 {
     public static function main ()
@@ -32,7 +28,3 @@ class Filemanager_AllTests
         return $suite;
     }
 }
-
-if (PHPUnit_MAIN_METHOD == 'Filemanager_AllTests::main') {
-    Filemanager_AllTests::main();
-}
index 1058ead..50bb4ef 100644 (file)
@@ -4,7 +4,7 @@
  * 
  * @package     Filemanager
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2012-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2012-2013 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Lars Kneschke <l.kneschke@metaways.de>
  */
 
  */
 require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
 
-if (! defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Filemanager_Frontend_AllTests::main');
-}
-
 class Filemanager_Frontend_AllTests
 {
     public static function main ()
@@ -33,7 +29,3 @@ class Filemanager_Frontend_AllTests
         return $suite;
     }
 }
-
-if (PHPUnit_MAIN_METHOD == 'Filemanager_Frontend_AllTests::main') {
-    Filemanager_Frontend_AllTests::main();
-}
index cf7e717..3c1224f 100644 (file)
@@ -69,6 +69,13 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
     protected $_otherUserContainer;
     
     /**
+     * the test user
+     * 
+     * @var Tinebase_Model_FullUser
+     */
+    protected $_originalTestUser;
+    
+    /**
      * Runs the test methods of this class.
      *
      * @access public
@@ -93,6 +100,7 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
         $this->_json = new Filemanager_Frontend_Json();
         $this->_fsController = Tinebase_FileSystem::getInstance();
         $this->_application = Tinebase_Application::getInstance()->getApplicationByName('Filemanager');
+        $this->_originalTestUser = Tinebase_Core::getUser();
         
         $this->_setupTestContainers();
     }
@@ -168,6 +176,8 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
      */
     protected function tearDown()
     {
+        Tinebase_Core::set(Tinebase_Core::USER, $this->_originalTestUser);
+        
         if (isset($this->_objects['paths'])) {
             foreach ($this->_objects['paths'] as $path) {
                 try {
@@ -393,16 +403,16 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
      * 
      * @return array created node
      */
-    public function testCreateContainerNodeInPersonalFolder()
+    public function testCreateContainerNodeInPersonalFolder($containerName = 'testcontainer')
     {
-        $testPath = '/' . Tinebase_Model_Container::TYPE_PERSONAL . '/' . Tinebase_Core::getUser()->accountLoginName . '/testcontainer';
+        $testPath = '/' . Tinebase_Model_Container::TYPE_PERSONAL . '/' . Tinebase_Core::getUser()->accountLoginName . '/' . $containerName;
         $result = $this->_json->createNodes($testPath, Tinebase_Model_Tree_Node::TYPE_FOLDER, array(), FALSE);
         $createdNode = $result[0];
         
         $this->_objects['containerids'][] = $createdNode['name']['id'];
         
         $this->assertTrue(is_array($createdNode['name']));
-        $this->assertEquals('testcontainer', $createdNode['name']['name']);
+        $this->assertEquals($containerName, $createdNode['name']['name']);
         $this->assertEquals(Tinebase_Core::getUser()->getId(), $createdNode['created_by']['accountId']);
         
         return $createdNode;
@@ -514,6 +524,24 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
         
         return $result;
     }
+    
+    /**
+     * testCreateFileCountTempDir
+     * 
+     * @see 0007370: Unable to upload files
+     */
+    public function testCreateFileCountTempDir()
+    {
+        $tmp = Tinebase_Core::getTempDir();
+        $filecountInTmpBefore = count(scandir($tmp));
+        
+        $this->testCreateFileNodeWithTempfile();
+        
+        // check if tempfile has been created in tine20 tempdir
+        $filecountInTmpAfter = count(scandir($tmp));
+        
+        $this->assertEquals($filecountInTmpBefore + 2, $filecountInTmpAfter, '2 tempfiles should have been created');
+    }
 
     /**
      * testCreateDirectoryNodesInShared
@@ -586,7 +614,45 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
         
         return $dirpaths;
     }
+    
+    /**
+     * testCreateDirectoryNodeInPersonalWithSameNameAsOtherUsersDir
+     * 
+     * @see 0008044: could not create a personal folder with the name of a folder of another user
+     */
+    public function testCreateDirectoryNodeInPersonalWithSameNameAsOtherUsersDir()
+    {
+        $personalContainerNode = $this->testCreateContainerNodeInPersonalFolder();
+        
+        $personas = Zend_Registry::get('personas');
+        Tinebase_Core::set(Tinebase_Core::USER, $personas['sclever']);
+        $personalContainerNodeOfsclever = $this->testCreateContainerNodeInPersonalFolder();
+        
+        $this->assertEquals('/personal/sclever/testcontainer', $personalContainerNodeOfsclever['path']);
+    }
+    
+    /**
+     * testRenameDirectoryNodeInPersonalToSameNameAsOtherUsersDir
+     * 
+     * @see 0008046: Rename personal folder to personal folder of another user
+     */
+    public function testRenameDirectoryNodeInPersonalToSameNameAsOtherUsersDir()
+    {
+        $personalContainerNode = $this->testCreateContainerNodeInPersonalFolder();
+        
+        $personas = Zend_Registry::get('personas');
+        Tinebase_Core::set(Tinebase_Core::USER, $personas['sclever']);
+        $personalContainerNodeOfsclever = $this->testCreateContainerNodeInPersonalFolder('testcontainer2');
         
+        $this->assertEquals('/personal/sclever/testcontainer2', $personalContainerNodeOfsclever['path']);
+        
+        // rename
+        $newPath = '/personal/sclever/testcontainer';
+        $result = $this->_json->moveNodes(array($personalContainerNodeOfsclever['path']), array($newPath), FALSE);
+        $this->assertEquals(1, count($result));
+        $this->assertEquals($newPath, $result[0]['path']);
+    }
+    
     /**
      * testCopyFolderNodes
      */
@@ -944,9 +1010,9 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
     }
     
     /**
-     * test cleanup of deleted files
+     * test cleanup of deleted files (filesystem)
      */
-    public function testDeletedFileCleanup()
+    public function testDeletedFileCleanupFromFilesystem()
     {
         // remove all files with size 0 first
         $size0Nodes = Tinebase_FileSystem::getInstance()->searchNodes(new Tinebase_Model_Tree_Node_Filter(array(array(
@@ -957,16 +1023,45 @@ class Filemanager_Frontend_JsonTests extends PHPUnit_Framework_TestCase
         }
         
         $this->testDeleteFileNodes();
-        $result = Tinebase_FileSystem::getInstance()->clearDeletedFiles();
+        $result = Tinebase_FileSystem::getInstance()->clearDeletedFilesFromFilesystem();
         $this->assertGreaterThan(0, $result, 'should cleanup one file or more');
         $this->tearDown();
         
         $this->testDeleteFileNodes();
-        $result = Tinebase_FileSystem::getInstance()->clearDeletedFiles();
+        $result = Tinebase_FileSystem::getInstance()->clearDeletedFilesFromFilesystem();
         $this->assertEquals(1, $result, 'should cleanup one file');
     }
 
     /**
+     * test cleanup of deleted files (database)
+     * 
+     * @see 0008062: add cleanup script for deleted files
+     */
+    public function testDeletedFileCleanupFromDatabase()
+    {
+        $fileNode = $this->testCreateFileNodeWithTempfile();
+        
+        // get "real" filesystem path + unlink
+        $fileObjectBackend = new Tinebase_Tree_FileObject();
+        $fileObject = $fileObjectBackend->get($fileNode['object_id']);
+        unlink($fileObject->getFilesystemPath());
+        
+        $result = Tinebase_FileSystem::getInstance()->clearDeletedFilesFromDatabase();
+        $this->assertEquals(1, $result, 'should cleanup one file');
+
+        $result = Tinebase_FileSystem::getInstance()->clearDeletedFilesFromDatabase();
+        $this->assertEquals(0, $result, 'should cleanup no file');
+        
+        // node should no longer be found
+        try {
+            $this->_json->getNode($fileNode['id']);
+            $this->fail('tree node still exists: ' . print_r($fileNode, TRUE));
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            $this->assertEquals('Tinebase_Model_Tree_Node record with id = ' . $fileNode['id'] . ' not found!', $tenf->getMessage());
+        }
+    }
+    
+    /**
      * testDeleteDirectoryNodes
      */
     public function testDeleteDirectoryNodes()
index 3fd8345..0396491 100644 (file)
@@ -100,16 +100,16 @@ class Inventory_Import_CsvTest extends PHPUnit_Framework_TestCase
         $translatedString = sprintf($translation->_("The following fields weren't imported: %s"), "\n");
         
         $this->assertEquals($result['results'][0]['name'], 'Tine 2.0 für Einsteiger');
-        $this->assertEquals($result['results'][0]['added_date'], '2013-01-11 00:00:00');
+        $this->assertEquals($result['results'][0]['added_date']->setTimezone('Europe/Berlin')->toString(), '2013-01-11 00:00:00');
         $this->assertEquals($result['results'][0]['inventory_id'], '12345');
         $this->assertContains($translatedString, $result['results'][0]['description']);
         
         $this->assertEquals($result['results'][1]['name'], 'Tine 2.0 für Tolle Leute - second mapping set');
-        $this->assertEquals($result['results'][1]['added_date'], '2012-01-11 00:00:00');
+        $this->assertEquals($result['results'][1]['added_date']->setTimezone('Europe/Berlin')->toString(), '2012-01-11 00:00:00');
         $this->assertEquals($result['results'][1]['inventory_id'], '1333431646');
         
         $this->assertEquals($result['results'][2]['name'], 'Tine 2.0 für Profis');
-        $this->assertEquals($result['results'][2]['added_date'], '2012-01-11 00:00:00');
+        $this->assertEquals($result['results'][2]['added_date']->setTimezone('Europe/Berlin')->toString(), '2012-01-11 00:00:00');
         $this->assertEquals($result['results'][2]['inventory_id'], '1333431666');
         $this->assertContains($translatedString, $result['results'][2]['description']);
         
@@ -137,15 +137,60 @@ class Inventory_Import_CsvTest extends PHPUnit_Framework_TestCase
         $translatedString = sprintf($translation->_("The following fields weren't imported: %s"), "\n");
         
         $this->assertEquals($result['results'][0]['name'], 'Tine 2.0 für Einsteiger');
-        $this->assertEquals($result['results'][0]['added_date'], '2013-01-11 00:00:00');
+        $this->assertEquals($result['results'][0]['added_date']->setTimezone('Europe/Berlin')->toString(), '2013-01-11 00:00:00');
         $this->assertEquals($result['results'][0]['inventory_id'], '');
         $this->assertContains($translatedString, $result['results'][0]['description']);
         
         $this->assertEquals($result['results'][1]['name'], 'Tine 2.0 für Profis');
-        $this->assertEquals($result['results'][1]['added_date'], '2012-01-11 00:00:00');
+        $this->assertEquals($result['results'][1]['added_date']->setTimezone('Europe/Berlin')->toString(), '2012-01-11 00:00:00');
         $this->assertEquals($result['results'][1]['inventory_id'], '1333431666');
     }
     
+     /**
+     * Test if different Datetime formats are correctly imported, if datetime_pattern is set
+     */
+    public function testImportOfDatetimeFormats ()
+    {
+        $filename = dirname(__FILE__) . '/files/inv_tine_import_csv_nohook.xml';
+        $applicationId = Tinebase_Application::getInstance()->getApplicationByName('Inventory')->getId();
+        $definition = Tinebase_ImportExportDefinition::getInstance()->getFromFile($filename, $applicationId);
+        
+        $this->_filename = dirname(__FILE__) . '/files/inv_tine_import_datetimes.csv';
+        $this->_deleteImportFile = FALSE;
+        
+        $result = $this->_doImport(array(), $definition);
+        $this->_deletePersonalInventoryItems = TRUE;
+        
+        $this->assertEquals('2013-12-31 00:00:00', $result['results'][0]['added_date']->setTimezone('Europe/Berlin')->toString(), 'Datetime and datetime_pattern should match');
+        $this->assertEquals('2013-12-31 00:00:00', $result['results'][0]['removed_date']->setTimezone('Europe/Berlin')->toString(), 'Datetime and datetime_pattern should match');
+        $this->assertNull($result['results'][1]['added_date'], 'Datetime and datetime_pattern do not match,  therefore should return null');
+        $this->assertNull( $result['results'][1]['added_date'], 'Datetime and datetime_pattern do not match,  therefore should return null');
+    }
+    
+    /**
+     * Tests if import of the example file works
+     */
+    public function testImportOfExampleFile ()
+    {
+        $filename = dirname(__FILE__) . '/files/inv_tine_import_csv_nohook.xml';
+        $applicationId = Tinebase_Application::getInstance()->getApplicationByName('Inventory')->getId();
+        $definition = Tinebase_ImportExportDefinition::getInstance()->getFromFile($filename, $applicationId);
+        
+        $this->_filename = dirname(dirname(dirname(dirname(dirname(__FILE__))))) . '/tine20/Inventory/Import/examples/inv_tine_import.csv'; 
+        $this->_deleteImportFile = FALSE;
+        
+        $result = $this->_doImport(array(), $definition);
+        $this->_deletePersonalInventoryItems = TRUE;
+        
+        $translation = Tinebase_Translation::getTranslation('Tinebase');
+        $translatedString = sprintf($translation->_("The following fields weren't imported: %s"), "\n");
+        
+        $this->assertEquals($result['results'][0]['name'], 'Tine 2.0 für Einsteiger');
+        $this->assertEquals($result['results'][0]['added_date']->setTimezone('Europe/Berlin')->toString(), '2013-12-06 00:00:00');
+        $this->assertEquals($result['results'][0]['inventory_id'], '133331666');
+        $this->assertContains($translatedString, $result['results'][0]['description']);
+    }
+    
     /**
      * import helper
      *
@@ -157,7 +202,6 @@ class Inventory_Import_CsvTest extends PHPUnit_Framework_TestCase
     protected function _doImport(array $_options, $_definition, Inventory_Model_InventoryItemFilter $_exportFilter = NULL)
     {
         $definition = ($_definition instanceof Tinebase_Model_ImportExportDefinition) ? $_definition : Tinebase_ImportExportDefinition::getInstance()->getByName($_definition);
-        
         $this->_instance = Inventory_Import_Csv::createFromDefinition($definition, $_options);
         
         // export first
index b6bdcab..604c383 100644 (file)
@@ -15,7 +15,7 @@
     <example>Inventory/Import/examples/inv_tine_import.csv</example>
     <extension>csv</extension>
     <postMappingHook>
-        <path>Inventory/Import/files/testScript.php</path>
+        <path>../tests/tine20/Inventory/Import/files/testScript.php</path>
     </postMappingHook>
     <autotags>
         <tag>
index b7a4dff..bbe1954 100644 (file)
         <field>
             <source>Anschaffung</source>
             <destination>added_date</destination>
+            <typecast>datetime</typecast>
+            <datetime_pattern>!Y-m-d</datetime_pattern>
+        </field>
+        <field>
+            <source>Entfernt</source>
+            <destination>removed_date</destination>
+            <typecast>datetime</typecast>
+            <datetime_pattern>!d.m.y</datetime_pattern>
         </field>
         <field>
             <source>Inventarnummer</source>
diff --git a/tests/tine20/Inventory/Import/files/inv_tine_import_datetimes.csv b/tests/tine20/Inventory/Import/files/inv_tine_import_datetimes.csv
new file mode 100644 (file)
index 0000000..cfa6eb6
--- /dev/null
@@ -0,0 +1,3 @@
+Titel,Anschaffung,Entfernt
+Tine 2.0 für Einsteiger,2013-12-31,31.12.13
+Tine 2.0 für Einsteiger,31.12.13,2013-12-31
\ No newline at end of file
index 08ba18f..a6ce4f3 100644 (file)
@@ -31,6 +31,18 @@ class Inventory_JsonTest extends Inventory_TestCase
     }
     
     /**
+     * tests if model gets created properly
+     */
+    public function testModelCreation()
+    {
+        $fields = Inventory_Model_InventoryItem::getConfiguration()->getFields();
+        $this->assertArrayHasKey('container_id', $fields);
+        
+        $filters = Inventory_Model_InventoryItem::getConfiguration()->getFilterModel();
+        $this->assertArrayHasKey('container_id', $filters['_filterModel']);
+    }
+    
+    /**
      * test creation of an InventoryItem
      */
     public function testCreateInventoryItem()
index d5738a1..f6df0a2 100644 (file)
@@ -227,7 +227,7 @@ class Tasks_ControllerTest extends PHPUnit_Framework_TestCase //Tinebase_Abstrac
      * @see 0007108: inspect and solve concurrency conflicts when setting lead relations
      * @see 0000996: add changes in relations/linked objects to modlog/history
      */
-    public function testConcurrencyDateTime()
+    public function testConcurrencyDateTimeSameValues()
     {
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " 1. Update");
         $utask = $this->testUpdateTask();
@@ -253,6 +253,25 @@ class Tasks_ControllerTest extends PHPUnit_Framework_TestCase //Tinebase_Abstrac
         }
     }
     
+    public function testConcurrencyDateTimeResolveable()
+    {
+        $utask = $this->testUpdateTask();
+        
+        $resolvableConcurrencyTask = clone $utask;
+        $resolvableConcurrencyTask->due = $utask->due->addMonth(1);
+        $this->_controller->update($resolvableConcurrencyTask);
+        
+        $resolvableConcurrencyTask2 = clone $utask;
+        $resolvableConcurrencyTask2->summary = 'Update of test task 1';
+        
+        try {
+            $updatedTask = $this->_controller->update($resolvableConcurrencyTask2);
+            $this->assertEquals($resolvableConcurrencyTask->due, $updatedTask->due);
+        } catch (Tinebase_Timemachine_Exception_ConcurrencyConflict $ttecc) {
+            $this->fail($ttecc);
+        }
+    }
+    
     /**
      * test if non resolvable concurrency problem gets detected
      *
index 291ed42..8b1966e 100644 (file)
@@ -62,6 +62,7 @@ class Tinebase_AllTests
         $suite->addTestSuite('Tinebase_TagsTest');
         $suite->addTestSuite('Tinebase_Log_AllTests');
         $suite->addTestSuite('Tinebase_Redis_QueueTest');
+        $suite->addTestSuite('Tinebase_TempFileTest');
         
         $suite->addTest(Tinebase_User_AllTests::suite());
         $suite->addTest(Tinebase_Group_AllTests::suite());
index d728425..d6fe5c7 100644 (file)
  */
 require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'TestHelper.php';
 
-if (!defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Tinebase_DateTimeTest::main');
-}
-
 /**
- * Test class for Tinebase_AsyncJob
+ * Test class for Tinebase_DateTimeTest
  */
 class Tinebase_DateTimeTest extends PHPUnit_Framework_TestCase
 {
-    
     /**
      * Sets up the fixture.
      * This method is called before a test is executed.
@@ -117,8 +112,3 @@ class Tinebase_DateTimeTest extends PHPUnit_Framework_TestCase
         $this->assertEquals('2012-01-16 15:30:00', $tdt->toString());
     }
 }
-
-if (PHPUnit_MAIN_METHOD == 'Tinebase_DateTimeTest::main') {
-    Tinebase_DateTimeTest::main();
-}
-
index 1e3eb09..0bc00bd 100644 (file)
  */
 require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
 
-if (!defined('PHPUnit_MAIN_METHOD')) {
-    define('PHPUnit_MAIN_METHOD', 'Tinebase_Filesystem_StreamWrapperTest::main');
-}
-
 /**
  * Test class for Tinebase_User
  */
-class Tinebase_Filesystem_StreamWrapperTest extends PHPUnit_Framework_TestCase
+class Tinebase_FileSystem_StreamWrapperTest extends PHPUnit_Framework_TestCase
 {
     /**
      * @var array test objects
@@ -70,7 +66,7 @@ class Tinebase_Filesystem_StreamWrapperTest extends PHPUnit_Framework_TestCase
     {
         Tinebase_TransactionManager::getInstance()->rollBack();
         Tinebase_FileSystem::getInstance()->clearStatCache();
-        Tinebase_FileSystem::getInstance()->clearDeletedFiles();
+        Tinebase_FileSystem::getInstance()->clearDeletedFilesFromFilesystem();
     }
     
     public function testMkdir()
@@ -177,9 +173,4 @@ class Tinebase_Filesystem_StreamWrapperTest extends PHPUnit_Framework_TestCase
         
         $this->assertTrue(in_array('phpunit2.txt', $children));
     }
-}        
-    
-
-if (PHPUnit_MAIN_METHOD == 'Tinebase_Filesystem_StreamWrapperTest::main') {
-    Tinebase_Filesystem_StreamWrapperTest::main();
 }
index 2da85d0..bee2dee 100644 (file)
@@ -77,7 +77,7 @@ class Tinebase_FileSystemTest extends PHPUnit_Framework_TestCase
     {
         Tinebase_TransactionManager::getInstance()->rollBack();
         Tinebase_FileSystem::getInstance()->clearStatCache();
-        Tinebase_FileSystem::getInstance()->clearDeletedFiles();
+        Tinebase_FileSystem::getInstance()->clearDeletedFilesFromFilesystem();
     }
     
     public function testMkdir()
index 39d9404..f9bf2ba 100644 (file)
@@ -5,8 +5,8 @@
  * @package     Tinebase
  * @subpackage  Json
  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
- * @author      Philipp Schuele <p.schuele@metaways.de>
- * @copyright   Copyright (c) 2007-2010 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Philipp Schüle <p.schuele@metaways.de>
+ * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
  *
  */
 
  */
 require_once dirname(dirname(dirname(__FILE__))) . DIRECTORY_SEPARATOR . 'TestHelper.php';
 
-if (!defined('PHPUnit_MAIN_METHOD')) {
-    Tinebase_Frontend_JsonTest::main();
-}
-
 /**
  * Test class for Tinebase_Group
  */
@@ -36,13 +32,6 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
     protected $_objects = array();
     
     /**
-     * clear preferences after test?
-     * 
-     * @var boolean
-     */
-    protected $_clearPrefs = FALSE;
-    
-    /**
      * Runs the test methods of this class.
      */
     public static function main()
@@ -57,6 +46,8 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
+        Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
+        
         $this->_instance = new Tinebase_Frontend_Json();
         
         $this->_objects['record'] = array(
@@ -77,25 +68,19 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
 
         $this->_objects['note'] = new Tinebase_Model_Note(array(
             'note_type_id'      => 1,
-            'note'              => 'phpunit test note',    
+            'note'              => 'phpunit test note',
             'record_model'      => $this->_objects['record']['model'],
-            'record_backend'    => $this->_objects['record']['backend'],       
+            'record_backend'    => $this->_objects['record']['backend'],
             'record_id'         => $this->_objects['record']['id']
         ));
     }
     
     /**
-     * tear down prefs
+     * tear down
      */
     public function tearDown()
     {
-        if ($this->_clearPrefs) {
-            $query = Tinebase_Core::getDb()->quoteInto(
-                'DELETE FROM ' . Tinebase_Core::getDb()->quoteIdentifier(SQL_TABLE_PREFIX . 'preferences') .' WHERE ' .Tinebase_Core::getDb()->quoteIdentifier('application_id') .' = ?', 
-                Tinebase_Application::getInstance()->getApplicationByName('Tinebase')->getId()
-            );
-            Tinebase_Core::getDb()->query($query);
-        }
+        Tinebase_TransactionManager::getInstance()->rollBack();
         
         // reset tz in core
         Tinebase_Core::set(Tinebase_Core::USERTIMEZONE, Tinebase_Core::getPreference()->getValue(Tinebase_Preference::TIMEZONE));
@@ -289,8 +274,6 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      */
     public function testSearchPreferencesWithOptions()
     {
-        $this->_clearPrefs = TRUE;
-        
         // add new default pref
         $pref = $this->_getPreferenceWithOptions();
         $pref = Tinebase_Core::getPreference()->create($pref);
@@ -323,8 +306,6 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      */
     public function testSearchPreferencesOfOtherUsers()
     {
-        $this->_clearPrefs = TRUE;
-        
         // add new default pref
         $pref = $this->_getPreferenceWithOptions();
         $pref->account_id   = '2';
@@ -346,8 +327,6 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      */
     public function testSavePreferences()
     {
-        $this->_clearPrefs = TRUE;
-        
         $prefData = $this->_getUserPreferenceData();
         $this->_instance->savePreferences($prefData, false);
 
@@ -365,7 +344,7 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
             
                 $this->assertTrue(is_array($result['options']), 'options missing');
                 $this->assertGreaterThan(100, count($result['options']));
-            }            
+            }
         }
         $this->assertEquals($prefData, $savedPrefData);
     }
@@ -375,8 +354,6 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      */
     public function testGetSetChangeDefaultPref()
     {
-        $this->_clearPrefs = TRUE;
-        
         $locale = $this->_getLocalePref();
         foreach ($locale['options'] as $option) {
             if ($option[0] == Tinebase_Model_Preference::DEFAULT_VALUE) {
@@ -394,7 +371,7 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
         $this->assertEquals('auto', Tinebase_Core::getPreference()->{Tinebase_Preference::LOCALE});
         
         // set new default locale
-        $prefData['Tinebase'][$locale['id']] = array('value' => 'de', 'type' => 'default', 'name' => Tinebase_Preference::LOCALE);
+        $prefData['Tinebase']['default' . $locale['id']] = array('value' => 'de', 'type' => 'default', 'name' => Tinebase_Preference::LOCALE);
         $this->_instance->savePreferences($prefData, true);
         
         $updatedLocale = $this->_getLocalePref();
@@ -431,7 +408,7 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      */
     public function testGetAdminPreferences()
     {
-        $this->_clearPrefs = TRUE;
+        $this->testGetSetChangeDefaultPref();
         
         // set new default locale
         $locale = $this->_getLocalePref();
@@ -445,14 +422,14 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
                 $this->assertEquals(Tinebase_Model_Preference::DEFAULT_VALUE, $pref['value']);
             } else {
                 $this->assertEquals(Tinebase_Model_Preference::TYPE_ADMIN, $pref['type']);
-                $this->assertEquals('de', $pref['value']);
+                $this->assertEquals('de', $pref['value'], print_r($pref, TRUE));
             }
         }
 
         // check as user
         $locale = $this->_getLocalePref();
-        $this->assertEquals(Tinebase_Model_Preference::TYPE_ADMIN, $locale['type']);
-        $this->assertEquals(Tinebase_Model_Preference::DEFAULT_VALUE, $locale['value']);
+        $this->assertEquals(Tinebase_Model_Preference::TYPE_ADMIN, $locale['type'], 'pref should be of type admin: ' . print_r($locale, TRUE));
+        $this->assertEquals(Tinebase_Model_Preference::DEFAULT_VALUE, $locale['value'], 'pref should be default value: ' . print_r($locale, TRUE));
     }
     
     /**
@@ -461,8 +438,6 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      */
     public function testSaveAdminPreferences()
     {
-        $this->_clearPrefs = TRUE;
-        
         // add new default pref
         $pref = $this->_getPreferenceWithOptions();
         $pref = Tinebase_Core::getPreference()->create($pref);
@@ -483,8 +458,6 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
     
     /**
      * save state and load it with registry data
-     *
-     * @todo save old state and recover it after the test
      */
     public function testSaveAndGetState()
     {
@@ -493,13 +466,13 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
             'zzing' => 'zzang'
         );
         
-        Tinebase_State::getInstance()->saveStateInfo($testData);
+        foreach ($testData as $key => $value) {
+            Tinebase_State::getInstance()->setState($key, $value);
+        }
         
         $stateInfo = Tinebase_State::getInstance()->loadStateInfo();
         
         $this->assertEquals($testData, $stateInfo);
-        
-        //$registryData = $this->_instance->getAllRegistryData();
     }
     
     /**
@@ -507,7 +480,7 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
      * 
      * @return void
      * 
-     * @todo add more assertions
+     * @see 0007934: change pw button active even if it is not allowed
      */
     public function testGetAllRegistryData()
     {
@@ -519,6 +492,13 @@ class Tinebase_Frontend_JsonTest extends PHPUnit_Framework_TestCase
             Addressbook_Controller_Contact::getInstance()->getContactByUserId($currentUser->getId())->toArray(), 
             $registryData['Tinebase']['userContact']
         );
+        $this->assertEquals(TRUE, $registryData['Tinebase']['config']['changepw']['value'], 'changepw should be TRUE');
+        
+        Tinebase_Config::getInstance()->set('changepw', 0);
+        $registryData = $this->_instance->getAllRegistryData();
+        $changepwValue = $registryData['Tinebase']['config']['changepw']['value'];
+        $this->assertEquals(FALSE, $changepwValue, 'changepw should be (bool) false');
+        $this->assertTrue(is_bool($changepwValue), 'changepw should be (bool) false: ' . var_export($changepwValue, TRUE));
     }
     
     /**
index 7795eb8..3d80523 100644 (file)
@@ -4,7 +4,7 @@
  * 
  * @package     Tinebase
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2009-2013 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Philipp Schüle <p.schuele@metaways.de>
  * 
  */
@@ -195,7 +195,7 @@ class Tinebase_PreferenceTest extends PHPUnit_Framework_TestCase
     /**
      * test search for preferences for anyone of calendar
      * 
-     * @see http://forge.tine20.org/mantisbt/view.php?id=5298
+     * @see 0005298: wrong default favorite in admin pref panel
      */
     public function testSearchCalendarPreferencesForAnyone()
     {
@@ -230,6 +230,22 @@ class Tinebase_PreferenceTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(), $filterPref['application_id'], print_r($filterPref, TRUE));
     }
     
+    /**
+     * testDeleteAdminPrefByChangingUserPref
+     * 
+     * @see 0008052: Change in user preference alters admin preferences
+     */
+    public function testDeleteAdminPrefByChangingUserPref()
+    {
+        $defaultValue = 'Europe/Nicosia';
+        $defaultPref = $this->_createTestPreference(Tinebase_Preference::TIMEZONE, 'Europe/Nicosia', Tinebase_Model_Preference::TYPE_DEFAULT);
+
+        $this->_instance->{Tinebase_Preference::TIMEZONE} = 'Europe/Berlin';
+        
+        $defaultPref = $this->_instance->get($defaultPref->getId());
+        $this->assertEquals($defaultValue, $defaultPref->value, 'defaultpref value overwritten: ' . print_r($defaultPref->toArray(), TRUE));
+    }
+    
     /******************** protected helper funcs ************************/
     
     /**
@@ -266,18 +282,20 @@ class Tinebase_PreferenceTest extends PHPUnit_Framework_TestCase
     /**
      * create test preference
      * 
-     * @param string $_prefName
+     * @param string $prefName
+     * @param string $value,
+     * @param string $type
      * @return Tinebase_Model_Preference
      */
-    protected function _createTestPreference($_prefName)
+    protected function _createTestPreference($prefName, $value = 'forced value', $type = Tinebase_Model_Preference::TYPE_FORCED)
     {
         $pref = new Tinebase_Model_Preference(array(
             'application_id'    => Tinebase_Application::getInstance()->getApplicationByName('Tinebase')->getId(),
-            'name'              => $_prefName,
-            'value'             => 'forced value',
+            'name'              => $prefName,
+            'value'             => $value,
             'account_id'        => '0',
             'account_type'      => Tinebase_Acl_Rights::ACCOUNT_TYPE_ANYONE,
-            'type'              => Tinebase_Model_Preference::TYPE_FORCED
+            'type'              => $type
         ));
         $pref = $this->_instance->create($pref);
         
diff --git a/tests/tine20/Tinebase/TempFileTest.php b/tests/tine20/Tinebase/TempFileTest.php
new file mode 100644 (file)
index 0000000..c572151
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Tine 2.0 - http://www.tine20.org
+ * 
+ * @package     Tinebase
+ * @license     http://www.gnu.org/licenses/agpl.html
+ * @copyright   Copyright (c) 2013 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @author      Philipp Schüle <p.schuele@metaways.de>
+ */
+
+/**
+ * Test helper
+ */
+require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'TestHelper.php';
+
+/**
+ * Test class for Tinebase_TempFileTest
+ */
+class Tinebase_TempFileTest extends PHPUnit_Framework_TestCase
+{
+    /**
+     * unit under test (UIT)
+     * @var Tinebase_TempFile
+     */
+    protected $_instance;
+    
+    /**
+     * Sets up the fixture.
+     * This method is called before a test is executed.
+     *
+     * @access protected
+     */
+    protected function setUp()
+    {
+        Tinebase_TransactionManager::getInstance()->startTransaction(Tinebase_Core::getDb());
+        $this->_instance = Tinebase_TempFile::getInstance();
+    }
+    
+    /**
+     * Tears down the fixture
+     * This method is called after a test is executed.
+     *
+     * @access protected
+     */
+    protected function tearDown()
+    {
+        Tinebase_TransactionManager::getInstance()->rollBack();
+    }
+    
+    /**
+     * testCreateTempFileWithNonUTF8Filename
+     * 
+     * @see 0008184: files with umlauts in filename cannot be attached with safari
+     */
+    public function testCreateTempFileWithNonUTF8Filename()
+    {
+        $filename = file_get_contents(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . 'brokenname.txt');
+        $path = tempnam(Tinebase_Core::getTempDir(), 'tine_tempfile_test_');
+        
+        $tempFile = $this->_instance->createTempFile($path, $filename);
+        $this->assertEquals("_tüt", $tempFile->name);
+    }
+}
index 9c1f203..1d13d89 100644 (file)
@@ -5,7 +5,7 @@
  * @package     Tinebase
  * @subpackage  User
  * @license     http://www.gnu.org/licenses/agpl.html
- * @copyright   Copyright (c) 2009-2012 Metaways Infosystems GmbH (http://www.metaways.de)
+ * @copyright   Copyright (c) 2009-2013 Metaways Infosystems GmbH (http://www.metaways.de)
  * @author      Philipp Schüle <p.schuele@metaways.de>
  */
 
@@ -220,4 +220,22 @@ class Tinebase_User_EmailUser_Smtp_PostfixTest extends PHPUnit_Framework_TestCas
             $this->assertTrue($foundDestinations == $destinations, print_r($destinations, TRUE));
         }
     }
+    
+    /**
+     * testLotsOfAliases
+     * 
+     * @see 0007194: alias table in user admin dialog truncated
+     */
+    public function testLotsOfAliases()
+    {
+        $user = $this->testAddUser();
+        $aliases = array();
+        for ($i = 0; $i < 100; $i++) {
+            $aliases[] = 'blablablablablablablablalbalbbl' . $i . '@' . $this->_mailDomain;
+        }
+        $user->smtpUser->emailAliases = $aliases;
+        $testUser = $this->_backend->updateUser($user);
+        
+        $this->assertEquals(100, count($testUser->smtpUser->emailAliases));
+    }
 }
index 1c2e0aa..515fa92 100644 (file)
@@ -198,7 +198,11 @@ class Tinebase_UserTest extends PHPUnit_Framework_TestCase
                 $this->fail('Expected Tinebase_Exception_PasswordPolicyViolation with message: ' . $expectedMessage . ' / used pw: ' . $pw);
             }
         } catch (Tinebase_Exception_PasswordPolicyViolation $tppv) {
-            $this->assertContains('Password failed to match the following policy requirements: ' . $expectedMessage, $tppv->getMessage());
+            if ($pwIsValid) {
+                $this->fail('pw is valid, got message: ' . $tppv->getMessage());
+            } else {
+                $this->assertContains('Password failed to match the following policy requirements: ' . $expectedMessage, $tppv->getMessage());
+            }
         }
     }
 
@@ -217,5 +221,6 @@ class Tinebase_UserTest extends PHPUnit_Framework_TestCase
         $this->_assertPolicy('cle', 'pwPolicyForbidUsername');
         $this->_assertPolicy('ver', 'pwPolicyForbidUsername');
         $this->_assertPolicy('sclever123', '', TRUE); // valid
+        $this->_assertPolicy('', '', TRUE); // valid
     }
 }
diff --git a/tests/tine20/Tinebase/files/brokenname.txt b/tests/tine20/Tinebase/files/brokenname.txt
new file mode 100644 (file)
index 0000000..9d6bba4
--- /dev/null
@@ -0,0 +1 @@
+_tüt
\ No newline at end of file
index 5fb31b4..ead8a6e 100644 (file)
@@ -337,33 +337,13 @@ class ActiveSync_Setup_Update_Release5 extends Setup_Update_Abstract
      */
     public function update_6()
     {
-        $this->_backend->dropForeignKey('acsync_folder', 'acsync_folder::device_id--acsync_device::id');
-        
-        $declaration = new Setup_Backend_Schema_Index_Xml('
-            <index>
-                <name>acsync_folder::device_id--acsync_device::id</name>
-                <field>
-                    <name>device_id</name>
-                </field>
-                <foreign>true</foreign>
-                <reference>
-                    <table>acsync_device</table>
-                    <field>id</field>
-                    <ondelete>cascade</ondelete>
-                    <onupdate>cascade</onupdate>
-                </reference>
-            </index> 
-        ');
-        $this->_backend->addForeignKey('acsync_folder', $declaration);
-
         $this->validateTableVersion('acsync_device', '2');
         
-        $this->_resetSyncKeyFK();
-
-        // drop acsync_content FK before truncating acsync_device -> @see 0005942: problems with update script 5.6 -> 5.7
-        $this->_backend->dropForeignKey('acsync_content', 'acsync_content::device_id--acsync_device::id');
+        $this->_dropDeviceFKs();
+        
         $this->_backend->truncateTable('acsync_device');
-        $this->_addContentDeviceFK();
+        
+        $this->_addDeviceFKs();
         
         $declaration = new Setup_Backend_Schema_Index_Xml('
             <index>
@@ -385,11 +365,40 @@ class ActiveSync_Setup_Update_Release5 extends Setup_Update_Abstract
     }
     
     /**
-     * reset acsync_synckey / device id FK
+     * drop FKs before truncating acsync_device -> @see 0005942: problems with update script 5.6 -> 5.7
      */
-    protected function _resetSyncKeyFK()
+    protected function _dropDeviceFKs()
+    {
+        $keysToDrop = array(
+            'acsync_content' => 'acsync_content::device_id--acsync_device::id',
+            'acsync_folder'  => 'acsync_folder::device_id--acsync_device::id',
+            'acsync_synckey' => 'acsync_synckey::device_id--acsync_device::id',
+        );
+        foreach ($keysToDrop as $table => $name) {
+            try {
+                $this->_backend->dropForeignKey($table, $name);
+            } catch (Zend_Db_Statement_Exception $zdse) {
+                if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ .
+                    " Error when dropping $name ->" . $zdse);
+            }
+        }
+    }
+    
+    /**
+     * add FKs to acsync_device -> @see 0005942: problems with update script 5.6 -> 5.7
+     */
+    protected function _addDeviceFKs()
+    {
+        $this->_addFolderFK();
+        $this->_addContentDeviceFK();
+        $this->_addSyncKeyFK();
+    }
+    
+    /**
+     * add acsync_synckey::device_id--acsync_device::id
+     */
+    protected function _addSyncKeyFK()
     {
-        $this->_backend->dropForeignKey('acsync_synckey', 'acsync_synckey::device_id--acsync_device::id');
         $declaration = new Setup_Backend_Schema_Index_Xml('
         <index>
             <name>acsync_synckey::device_id--acsync_device::id</name>
@@ -407,6 +416,29 @@ class ActiveSync_Setup_Update_Release5 extends Setup_Update_Abstract
         ');
         $this->_backend->addForeignKey('acsync_synckey', $declaration);
     }
+
+    /**
+     * add acsync_folder::device_id--acsync_device::id
+     */
+    protected function _addFolderFK()
+    {
+        $declaration = new Setup_Backend_Schema_Index_Xml('
+            <index>
+                <name>acsync_folder::device_id--acsync_device::id</name>
+                <field>
+                    <name>device_id</name>
+                </field>
+                <foreign>true</foreign>
+                <reference>
+                    <table>acsync_device</table>
+                    <field>id</field>
+                    <ondelete>cascade</ondelete>
+                    <onupdate>cascade</onupdate>
+                </reference>
+            </index> 
+        ');
+        $this->_backend->addForeignKey('acsync_folder', $declaration);
+    }
     
     /**
      * update to 5.7
@@ -417,8 +449,6 @@ class ActiveSync_Setup_Update_Release5 extends Setup_Update_Abstract
      */
     public function update_7()
     {
-        $this->_resetSyncKeyFK();
-        
         $this->validateTableVersion('acsync_content', '4');
         
         $declaration = new Setup_Backend_Schema_Field_Xml('
@@ -429,11 +459,15 @@ class ActiveSync_Setup_Update_Release5 extends Setup_Update_Abstract
             </field>
         ');
         $this->_backend->addCol('acsync_content', $declaration);
-                
+        
         $this->setTableVersion('acsync_content', '5');
         
+        $this->_dropDeviceFKs();
+        
         $this->_backend->truncateTable('acsync_device');
         
+        $this->_addDeviceFKs();
+        
         $this->setApplicationVersion('ActiveSync', '5.8');
     }
     
index bf7ed9f..056befa 100644 (file)
@@ -1,12 +1,13 @@
 # 
 # Translators:
-#   <sn@cbox.dk>, 2012.
+# cboxdk <sn@cbox.dk>, 2012
+# cboxdk <sn@cbox.dk>, 2013
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
 "POT-Creation-Date: 2008-05-17 22:12+0100\n"
-"PO-Revision-Date: 2012-09-19 08:56+0000\n"
-"Last-Translator: corneliusweiss <mail@corneliusweiss.de>\n"
+"PO-Revision-Date: 2013-03-31 14:40+0000\n"
+"Last-Translator: cboxdk <sn@cbox.dk>\n"
 "Language-Team: Danish (http://www.transifex.com/projects/p/tine20/language/da/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -19,11 +20,11 @@ msgstr ""
 
 #: Config.php:31
 msgid "Default policy for new devices"
-msgstr ""
+msgstr "Standard politik for nye enheder"
 
 #: Config.php:33
 msgid "Enter the id of the policy to apply to newly created devices."
-msgstr ""
+msgstr "Indtast ID'et for politikken du vil tildele nyligt oprettede enheder"
 
 #: Setup/setup.xml:542 Setup/Update/Release6.php:290
 msgid "Default Policy"
index 88f49fb..b43678d 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-#   <p.schuele@metaways.de>, 2012.
+# pschuele <p.schuele@metaways.de>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index feadd13..04c76b2 100644 (file)
@@ -1,12 +1,13 @@
 # 
 # Translators:
-#   <sahkari@saunalahti.fi>, 2012.
+# maukka <huru_ukko@hotmail.com>, 2013
+# sahkari <sahkari@saunalahti.fi>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
 "POT-Creation-Date: 2008-05-17 22:12+0100\n"
-"PO-Revision-Date: 2012-12-01 06:00+0000\n"
-"Last-Translator: sahkari <sahkari@saunalahti.fi>\n"
+"PO-Revision-Date: 2013-03-04 19:20+0000\n"
+"Last-Translator: maukka <huru_ukko@hotmail.com>\n"
 "Language-Team: Finnish (http://www.transifex.com/projects/p/tine20/language/fi/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -89,7 +90,7 @@ msgstr "Palautetut synkronointi suodattimet"
 
 #: js/Application.js:91 js/Application.js:103
 msgid "{0} filter for device \"{1}\" is now \"{2}\""
-msgstr ""
+msgstr "Laitteen \"{1}\" suodatin {0} on nyt \"{2}\""
 
 #: js/Application.js:94
 msgid "resetted"
index 926b245..a892d68 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-#   <inscription@arrakeen.net>, 2012.
+# Gurney <inscription@arrakeen.net>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index 3c1cb41..39fb3da 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-#   <brankablag@gmail.com>, 2012.
+# brankablag <brankablag@gmail.com>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index 7bd1301..0b8bd0d 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-# Tamás Faragó <>, 2012.
+# Tamás Faragó <>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index 6f2ddfd..4133c20 100644 (file)
@@ -1,12 +1,13 @@
 # 
 # Translators:
-#   <v.anzisi@gurusys.it>, 2012.
+# sambar <samuel.barbera@email.it>, 2013
+# gurusys <v.anzisi@gurusys.it>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
 "POT-Creation-Date: 2008-05-17 22:12+0100\n"
-"PO-Revision-Date: 2012-11-04 01:25+0000\n"
-"Last-Translator: gurusys <v.anzisi@gurusys.it>\n"
+"PO-Revision-Date: 2013-03-20 13:43+0000\n"
+"Last-Translator: sambar <samuel.barbera@email.it>\n"
 "Language-Team: Italian (http://www.transifex.com/projects/p/tine20/language/it/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -39,7 +40,7 @@ msgstr "Rubrica predefinita"
 
 #: Preference.php:76
 msgid "The default addressbook to create new contacts in."
-msgstr ""
+msgstr "Rubrica predefinita per la creazione dei nuovi contatti"
 
 #: Preference.php:79
 msgid "Default Calendar"
@@ -47,7 +48,7 @@ msgstr "Calendario predefinito"
 
 #: Preference.php:80
 msgid "The default calendar to create new events in."
-msgstr ""
+msgstr "Il calendario predefinito per la creazione di nuovi eventi"
 
 #: Preference.php:83
 msgid "Default Task List"
@@ -55,7 +56,7 @@ msgstr "Elenco Attività predefinito"
 
 #: Preference.php:84
 msgid "The default task list to create new tasks in."
-msgstr ""
+msgstr "Lista predefinita di attività in cui crearne una nuova."
 
 #: js/Model.js:42
 msgid "Device"
@@ -81,15 +82,15 @@ msgstr "Nessun Device registrato in ActiveSync"
 
 #: js/Application.js:65
 msgid "Set as {0} Filter"
-msgstr ""
+msgstr "Imposta come filtro {0}"
 
 #: js/Application.js:90
 msgid "Resetted Sync Filter"
-msgstr ""
+msgstr "Filtro Sync Resettato"
 
 #: js/Application.js:91 js/Application.js:103
 msgid "{0} filter for device \"{1}\" is now \"{2}\""
-msgstr ""
+msgstr "{0} filtro per il dispositivo \"{1}\" è ora \"{2}\""
 
 #: js/Application.js:94
 msgid "resetted"
@@ -97,4 +98,4 @@ msgstr "resettato"
 
 #: js/Application.js:102
 msgid "Set Sync Filter"
-msgstr ""
+msgstr "Imposta Filtro Sync"
index 9a23f8f..098e271 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-#  <dduckk79@gmail.com>, 2013.
+# dduckk <dduckk79@gmail.com>, 2013
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index c23067d..5044041 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-#   <bertjan.meinders@bjsoft.nl>, 2012.
+# BJ <bertjan.meinders@bjsoft.nl>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index 31e5613..c3ca5bd 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-# Wojciech Kaczmarek <wojciech_kaczmarek@wp.pl>, 2012.
+# Wojciech Kaczmarek <wojciech_kaczmarek@wp.pl>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index 50846a5..826da4b 100644 (file)
@@ -1,7 +1,7 @@
 # 
 # Translators:
-# Nikolay Parukhin <parukhin@gmail.com>, 2012.
-#   <parukhin@gmail.com>, 2012.
+# Nikolay Parukhin <parukhin@gmail.com>, 2012
+# Nikolay Parukhin <parukhin@gmail.com>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index d7d4f4c..dc9b7a9 100644 (file)
@@ -1,7 +1,7 @@
 # 
 # Translators:
-# Niklas Ye <niklas@idontgetlaid.com>, 2013.
-#   <tulken_hultan@hotmail.com>, 2012.
+# niklasye <niklas@idontgetlaid.com>, 2013
+# BrianLuckBad <tulken_hultan@hotmail.com>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index 5415dfa..568ba97 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-#   <mail@demiveo.de>, 2012.
+# demiveo <mail@demiveo.de>, 2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index 7867d14..c7e5ee3 100644 (file)
@@ -1,6 +1,6 @@
 # 
 # Translators:
-# sao sang <saosangmo@yahoo.com>, 2013.
+# saosangm <saosangmo@yahoo.com>, 2013
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
index c30f447..0987bf5 100644 (file)
@@ -1,12 +1,13 @@
 # 
 # Translators:
-#   <spacen_zj@hotmail.com>, 2012.
+# vehery <spacen_zj@hotmail.com>, 2012
+# yinxiaodong <xindev@gmail.com>, 2013
 msgid ""
 msgstr ""
 "Project-Id-Version: Tine 2.0\n"
 "POT-Creation-Date: 2008-05-17 22:12+0100\n"
-"PO-Revision-Date: 2012-09-19 08:56+0000\n"
-"Last-Translator: corneliusweiss <mail@corneliusweiss.de>\n"
+"PO-Revision-Date: 2013-03-10 07:32+0000\n"
+"Last-Translator: yinxiaodong <xindev@gmail.com>\n"
 "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/tine20/language/zh_CN/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -19,11 +20,11 @@ msgstr ""
 
 #: Config.php:31
 msgid "Default policy for new devices"
-msgstr ""
+msgstr "新设备使用默认策略"
 
 #: Config.php:33
 msgid "Enter the id of the policy to apply to newly created devices."
-msgstr ""
+msgstr "输入ID的策略应用到新创建的设备。"
 
 #: Setup/setup.xml:542 Setup/Update/Release6.php:290
 msgid "Default Policy"
@@ -31,7 +32,7 @@ msgstr "默认策略"
 
 #: Setup/setup.xml:547 Setup/Update/Release6.php:295
 msgid "Default Policy installed during setup"
-msgstr ""
+msgstr "安装过程中使用默认策略"
 
 #: Preference.php:75
 msgid "Default Addressbook"
@@ -55,12 +56,12 @@ msgstr "任务列表"
 
 #: Preference.php:84
 msgid "The default task list to create new tasks in."
-msgstr ""
+msgstr "在默认的任务列表中创建新的任务。"
 
 #: js/Model.js:42
 msgid "Device"
 msgid_plural "Devices"
-msgstr[0] ""
+msgstr[0] "设备"
 
 #: js/Model.js:42
 msgid "Devices"
@@ -88,7 +89,7 @@ msgstr "重置同步过滤器"
 
 #: js/Application.js:91 js/Application.js:103
 msgid "{0} filter for device \"{1}\" is now \"{2}\""
-msgstr ""
+msgstr "{0} 过滤设备 \"{1}\" 现在是 \"{2}\""
 
 #: js/Application.js:94
 msgid "resetted"
index ddb25f1..2caa379 100644 (file)
@@ -1,92 +1,98 @@
+# 
+# Translators:
 msgid ""
 msgstr ""
-"Project-Id-Version: Tine 2.0 - ActiveSync\n"
-"Report-Msgid-Bugs-To: \n"
+"Project-Id-Version: Tine 2.0\n"
 "POT-Creation-Date: 2008-05-17 22:12+0100\n"
-"PO-Revision-Date: 2012-02-10 12:00+0000\n"
+"PO-Revision-Date: 2012-04-02 13:30+0000\n"
 "Last-Translator: Cornelius Weiss <c.weiss@metaways.de>\n"
-"Language-Team: Tine 2.0 Translators\n"
-"Language: \n"
+"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/tine20/language/zh_TW/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"Language: zh_TW\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
-"X-Launchpad-Export-Date: 2012-03-02 09:32+0000\n"
-"X-Generator: Launchpad (build 14886)\n"
-"X-Poedit-Country: TAIWAN\n"
-"X-Poedit-Language: Chinese\n"
+"X-Poedit-Country: GB\n"
+"X-Poedit-Language: en\n"
 "X-Poedit-SourceCharset: utf-8\n"
 
-#: js/Application.js:30
-msgid "Active Sync"
+#: Config.php:31
+msgid "Default policy for new devices"
 msgstr ""
 
-#: js/Application.js:46
-msgid "Select a Device"
+#: Config.php:33
+msgid "Enter the id of the policy to apply to newly created devices."
 msgstr ""
 
-#: js/Application.js:60
-msgid "No ActiveSync Device registered"
+#: Setup/setup.xml:542 Setup/Update/Release6.php:290
+msgid "Default Policy"
 msgstr ""
 
-#: js/Application.js:68
-msgid "Set as {0} Filter"
+#: Setup/setup.xml:547 Setup/Update/Release6.php:295
+msgid "Default Policy installed during setup"
 msgstr ""
 
-#: js/Application.js:93
-msgid "Resetted Sync Filter"
+#: Preference.php:75
+msgid "Default Addressbook"
 msgstr ""
 
-#: js/Application.js:94 js/Application.js:106
-msgid "{0} filter for device \"{1}\" is now \"{2}\""
+#: Preference.php:76
+msgid "The default addressbook to create new contacts in."
 msgstr ""
 
-#: js/Application.js:97
-msgid "resetted"
+#: Preference.php:79
+msgid "Default Calendar"
 msgstr ""
 
-#: js/Application.js:105
-msgid "Set Sync Filter"
+#: Preference.php:80
+msgid "The default calendar to create new events in."
+msgstr ""
+
+#: Preference.php:83
+msgid "Default Task List"
+msgstr ""
+
+#: Preference.php:84
+msgid "The default task list to create new tasks in."
 msgstr ""
 
-#: js/Model.js:45
+#: js/Model.js:42
 msgid "Device"
 msgid_plural "Devices"
 msgstr[0] ""
-msgstr[1] ""
 
-#: js/Model.js:45
+#: js/Model.js:42
 msgid "Devices"
 msgstr ""
 
-#: Preference.php:79
-msgid "Default Addressbook"
+#: js/Application.js:27
+msgid "Active Sync"
 msgstr ""
 
-#: Preference.php:80
-msgid "The default addressbook to create new contacts in."
+#: js/Application.js:43
+msgid "Select a Device"
 msgstr ""
 
-#: Preference.php:83
-msgid "Default Calendar"
+#: js/Application.js:57
+msgid "No ActiveSync Device registered"
 msgstr ""
 
-#: Preference.php:84
-msgid "The default calendar to create new events in."
+#: js/Application.js:65
+msgid "Set as {0} Filter"
 msgstr ""
 
-#: Preference.php:87
-msgid "Default Task List"
+#: js/Application.js:90
+msgid "Resetted Sync Filter"
 msgstr ""
 
-#: Preference.php:88
-msgid "The default task list to create new tasks in."
+#: js/Application.js:91 js/Application.js:103
+msgid "{0} filter for device \"{1}\" is now \"{2}\""
 msgstr ""
 
-#: Setup/setup.xml:527
-msgid "Default Policy"
+#: js/Application.js:94
+msgid "resetted"
 msgstr ""
 
-#: Setup/setup.xml:532
-msgid "Default Policy installed during setup"
+#: js/Application.js:102
+msgid "Set Sync Filter"
 msgstr ""
index 39f251b..b3a8906 100644 (file)
           "path": "js/"
         },
         {
-          "text": "Model.js",
+          "text": "ContactModel.js",
+          "path": "js/"
+        },
+        {
+          "text": "ListModel.js",
+          "path": "js/"
+        },
+        {
+          "text": "EmailModel.js",
           "path": "js/"
         },
         {
           "path": "js/"
         },
         {
+          "text": "ListGridDetailsPanel.js",
+          "path": "js/"
+        },
+        {
           "text": "ContactGrid.js",
           "path": "js/"
         },
           "path": "js/"
         },
         {
+          "text": "ListEditDialog.js",
+          "path": "js/"
+        },
+        {
+          "text": "ListMemberGridPanel.js",
+          "path": "js/"
+        },
+        {
+          "text": "ListGrid.js",
+          "path": "js/"
+        },
+        {
           "text": "SearchCombo.js",
           "path": "js/"
         },
@@ -65,4 +89,4 @@
       ]
     }
   ]
-}
\ No newline at end of file
+}
index 7141a61..9a65d8f 100644 (file)
@@ -68,6 +68,34 @@ class Addressbook_Backend_List extends Tinebase_Backend_Sql_Abstract
     );
 
     /**
+     * the constructor
+     * 
+     * allowed options:
+     *  - modelName
+     *  - tableName
+     *  - tablePrefix
+     *  - modlogActive
+     *  - useSubselectForCount
+     *  
+     * @param Zend_Db_Adapter_Abstract $_db (optional)
+     * @param array $_options (optional)
+     * @throws Tinebase_Exception_Backend_Database
+     */
+    public function __construct($_dbAdapter = NULL, $_options = array())
+    {
+        parent::__construct($_dbAdapter, $_options);
+        
+        $this->_additionalColumns['emails'] = new Zend_Db_Expr('(' . 
+            $this->_db->select()
+                ->from($this->_tablePrefix . 'addressbook', array($this->_dbCommand->getAggregate('email')))
+                ->where($this->_db->quoteIdentifier('id') . ' IN ?', $this->_db->select()
+                    ->from(array('addressbook_list_members' => $this->_tablePrefix . 'addressbook_list_members'), array('contact_id'))
+                    ->where($this->_db->quoteIdentifier('addressbook_list_members.list_id') . ' = ' . $this->_db->quoteIdentifier('addressbook_lists.id'))
+            ) . 
+        ')');
+    }
+
+    /**
      * converts record into raw data for adapter
      *
      * @param  Tinebase_Record_Abstract $_record
index cac3c3a..c375a92 100644 (file)
@@ -80,7 +80,9 @@ class Addressbook_Controller extends Tinebase_Controller_Event implements Tineba
                 $this->createPersonalFolder($_eventObject->account);
                 break;
             case 'Admin_Event_DeleteAccount':
-                $this->deletePersonalFolder($_eventObject->account);
+                foreach ($_eventObject->accountIds as $accountId) {
+                    $this->deletePersonalFolder($accountId);
+                }
                 break;
         }
     }
index b5798f2..1d9ab6c 100755 (executable)
@@ -61,6 +61,44 @@ class Addressbook_Frontend_Json extends Tinebase_Frontend_Json_Abstract
     {
         return $this->_search($filter, $paging, Addressbook_Controller_Contact::getInstance(), 'Addressbook_Model_ContactFilter');
     }    
+
+    /**
+     * Search for Email Addresses with the Email Model in Lists and Contacts
+     *
+     * @param  array $filter
+     * @param  array $paging
+     * @return array
+     *
+     * Record Proxy Pluralizer doesnt correctly pluralize EmailAddress, thus EmailAddresss is used
+     *
+     */
+    public function searchEmailAddresss($filter, $paging)
+    {
+        $results = array();
+        $contacts = $this->_search($filter, $paging, Addressbook_Controller_Contact::getInstance(), 'Addressbook_Model_ContactFilter');
+        foreach ($contacts["results"] as $contact) {
+            array_push($results, array("n_fileas" => $contact["n_fileas"], "emails" => $contact["email"], "email" => $contact["email"], "email_home" => $contact["email_home"]));
+        }
+
+        $dont_add = false;
+        if (isset($paging["start"])) {
+            $paging["start"] = $paging["start"] - $contacts["totalcount"] + count($results);
+            $paging["limit"] = $paging["limit"] - count($results);
+            if (($paging["limit"] <= 0) || ($paging["start"] < 0)) {
+                $dont_add = true;
+                $paging["limit"] = 1;
+                $paging["start"] = 0;
+            }
+        }
+        
+        $lists = $this->_search($filter, $paging, Addressbook_Controller_List::getInstance(), 'Addressbook_Model_ListFilter');
+        if (!$dont_add) {
+            foreach ($lists["results"] as $list) {
+                array_push($results, array("n_fileas" => $list["name"], "emails" => $list["emails"]));
+            }
+         }
+         return array("results" => $results, "totalcount" => $lists["totalcount"]+$contacts["totalcount"]);
+    } 
     
     /**
      * return autocomplete suggestions for a given property and value
@@ -100,6 +138,31 @@ class Addressbook_Frontend_Json extends Tinebase_Frontend_Json_Abstract
     }
     
     /**
+     * get one list identified by $id
+     *
+     * @param string $id
+     * @return array
+     */
+    public function getList($id)
+    {
+        return $this->_get($id, Addressbook_Controller_List::getInstance());
+    }
+
+    /**
+     * save one list
+     *
+     * if $recordData['id'] is empty the list gets added, otherwise it gets updated
+     *
+     * @param  array $recordData an array of list properties
+     * @param  boolean $duplicateCheck
+     * @return array
+     */
+    public function saveList($recordData, $duplicateCheck = FALSE)
+    {
+        return $this->_save($recordData, Addressbook_Controller_List::getInstance(), 'List', 'id', array($duplicateCheck));
+    }
+
+    /**
      * Search for lists matching given arguments
      *
      * @param  array $filter
@@ -159,9 +222,13 @@ class Addressbook_Frontend_Json extends Tinebase_Frontend_Json_Abstract
     public function parseAddressData($address)
     {
         $result = Addressbook_Controller_Contact::getInstance()->parseAddressData($address);
+        $contactData = $this->_recordToJson($result['contact']);
+        
+        unset($contactData['jpegphoto']);
+        unset($contactData['salutation']);
         
         return array(
-            'contact'             => $this->_recordToJson($result['contact']),
+            'contact'             => $contactData,
             'unrecognizedTokens'  => $result['unrecognizedTokens'],
         );
     }
index 6ad88cb..696c8d6 100644 (file)
@@ -69,6 +69,7 @@ class Addressbook_Model_List extends Tinebase_Record_Abstract
         'is_deleted'            => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         'deleted_time'          => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         'deleted_by'            => array(Zend_Filter_Input::ALLOW_EMPTY => true),
+        'emails'                => array(Zend_Filter_Input::ALLOW_EMPTY => true),
         
         // list specific fields
         'name'                  => array('presence' => 'required'),
index b538758..ed84028 100644 (file)
@@ -34,13 +34,13 @@ class Addressbook_Model_ListHiddenFilter extends Tinebase_Model_Filter_Bool
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Query all lists.');
         } else {
             if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Only query visible lists.');
-            
-            $_select->join(
+            $_select->joinLeft(
                 /* table  */ array('groupvisibility' => $db->table_prefix . 'groups'), 
                 /* on     */ $db->quoteIdentifier('groupvisibility.list_id') . ' = ' . $db->quoteIdentifier('addressbook_lists.id'),
                 /* select */ array()
             );
             $_select->where($db->quoteIdentifier('groupvisibility.visibility').' = ?', 'displayed');
+            $_select->orWhere($db->quoteInto($db->quoteIdentifier('addressbook_lists.type'). ' = ?', Addressbook_Model_List::LISTTYPE_LIST));
         }
     }
 }
index 01ec1cd..387f30e 100644 (file)
@@ -104,8 +104,8 @@ class Addressbook_Setup_DemoData extends Tinebase_Setup_DemoData_Abstract
         if (! (file_exists($csvFile) && file_exists($imageFile))) {
             die('File does not exist!');
         }
-        $fhcsv = fopen($csvFile, 'r+');
-        $fhimages = fopen($imageFile, 'r+');
+        $fhcsv = fopen($csvFile, 'r');
+        $fhimages = fopen($imageFile, 'r');
         $i=0;
         
         $femalePhotoIndex = 0;
@@ -170,8 +170,8 @@ class Addressbook_Setup_DemoData extends Tinebase_Setup_DemoData_Abstract
             if ($imageData) {
                 $be->_saveImage($record->getId(), $imageData);
             }
-        } catch (Tinebase_Exception_Duplicate $e) {
-            echo 'Duplicate won\'t be imported. Skipping: ' . $data['n_given'] .' ' . $data['n_family'] . ($data['org_name'] ? ' ('.$data['org_name'].') ' : '') . PHP_EOL;
+        } catch (Exception $e) {
+            echo 'Skipping: ' . $data['n_given'] .' ' . $data['n_family'] . ($data['org_name'] ? ' ('.$data['org_name'].') ' : '') . $e->getMessage() . PHP_EOL;
         }
     }
     
index 6fef1f8..c03b939 100644 (file)
@@ -31,4 +31,27 @@ class Addressbook_Setup_Update_Release7 extends Setup_Update_Abstract
         
         $this->setApplicationVersion('Addressbook', '7.1');
     }
+
+    /**
+     * update to 7.2
+     * - make name in address_book_lists non-unique
+     * 
+     */
+    public function update_1()
+    {     &