calendar choosing, timezone fix, import all
this is version 1.0 =)
This commit is contained in:
parent
af3fcfb457
commit
e64d8415bc
@ -34,6 +34,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
this.initForm()
|
this.initForm()
|
||||||
],
|
],
|
||||||
buttons: [
|
buttons: [
|
||||||
|
this.createSubmitAllButton(),
|
||||||
this.createSubmitButton(),
|
this.createSubmitButton(),
|
||||||
this.createCancelButton()
|
this.createCancelButton()
|
||||||
]
|
]
|
||||||
@ -81,7 +82,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
var parsedData = new Array(eventdata.events.length);
|
var parsedData = new Array(eventdata.events.length);
|
||||||
|
|
||||||
for(var i=0; i < eventdata.events.length; i++) {
|
for(var i=0; i < eventdata.events.length; i++) {
|
||||||
parsedData[i] = new Array(eventdata.events[i]["SUMMARY"], parseInt(eventdata.events[i]["DTSTART"]), parseInt(eventdata.events[i]["DTEND"]), eventdata.events[i]["LOCATION"], eventdata.events[i]["DESCRIPTION"]);
|
parsedData[i] = new Array(eventdata.events[i]["SUMMARY"], new Date(parseInt(eventdata.events[i]["DTSTART"])), new Date(parseInt(eventdata.events[i]["DTEND"])), eventdata.events[i]["LOCATION"], eventdata.events[i]["DESCRIPTION"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,16 +127,16 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
|
|
||||||
createSelectBox: function() {
|
createSelectBox: function() {
|
||||||
ctx = container.getContextByName('calendar');
|
ctx = container.getContextByName('calendar');
|
||||||
model = ctx.getModel();
|
model = ctx.getModel();
|
||||||
defaultFolder = model.getDefaultFolder();
|
defaultFolder = model.getDefaultFolder(); // @type: Zarafa.hierarchy.data.MAPIFolderRecord
|
||||||
subFolders = defaultFolder.getChildren();
|
subFolders = defaultFolder.getChildren();
|
||||||
|
|
||||||
var myStore = new Ext.data.ArrayStore({
|
var myStore = new Ext.data.ArrayStore({
|
||||||
fields: ['calendar_id', 'calendar_displayname'],
|
fields: ['calendar_id', 'calendar_displayname'],
|
||||||
idIndex: 0 // id for each record will be the first element
|
idIndex: 0 // id for each record will be the first element
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Calendar Record holds the name and real name of the calender */
|
/* Calendar Record holds the name and real name of the calender */
|
||||||
var CalendarRecord = Ext.data.Record.create([
|
var CalendarRecord = Ext.data.Record.create([
|
||||||
{name: 'realname', type: "string"},
|
{name: 'realname', type: "string"},
|
||||||
{name: 'displayname', type: "string"}
|
{name: 'displayname', type: "string"}
|
||||||
@ -144,85 +145,103 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
/* Store the default folder */
|
/* Store the default folder */
|
||||||
var myNewRecord = new CalendarRecord({
|
var myNewRecord = new CalendarRecord({
|
||||||
realname: defaultFolder.getDefaultFolderKey(),
|
realname: defaultFolder.getDefaultFolderKey(),
|
||||||
displayname: defaultFolder.getDisplayName()
|
displayname: defaultFolder.getDisplayName()
|
||||||
});
|
});
|
||||||
myStore.add(myNewRecord);
|
myStore.add(myNewRecord);
|
||||||
|
|
||||||
for(i=0;i<subFolders.length;i++) {
|
for(i=0;i<subFolders.length;i++) {
|
||||||
/* Store all subfolders */
|
/* Store all subfolders */
|
||||||
myNewRecord = new CalendarRecord({
|
myNewRecord = new CalendarRecord({
|
||||||
realname: subFolders[i].getDisplayName(), // TODO: get the real path...
|
realname: subFolders[i].getDisplayName(), // TODO: get the real path...
|
||||||
displayname: subFolders[i].getDisplayName()
|
displayname: subFolders[i].getDisplayName()
|
||||||
});
|
});
|
||||||
myStore.add(myNewRecord);
|
myStore.add(myNewRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* commit the changes to the store */
|
/* commit the changes to the store */
|
||||||
myStore.commitChanges();
|
myStore.commitChanges();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
xtype: "selectbox",
|
xtype: "selectbox",
|
||||||
editable: false,
|
ref: 'calendarselector',
|
||||||
name: "choosen_calendar",
|
id: 'calendarselector',
|
||||||
width: 100,
|
editable: false,
|
||||||
fieldLabel: "Select a calender",
|
name: "choosen_calendar",
|
||||||
store: myStore,
|
width: 100,
|
||||||
valueField: 'realname',
|
fieldLabel: "Select a calender",
|
||||||
displayField: 'displayname',
|
store: myStore,
|
||||||
labelSeperator: ":",
|
valueField: 'realname',
|
||||||
border: false,
|
displayField: 'displayname',
|
||||||
anchor: "100%",
|
labelSeperator: ":",
|
||||||
scope: this,
|
border: false,
|
||||||
allowBlank: false
|
anchor: "100%",
|
||||||
}
|
scope: this,
|
||||||
|
allowBlank: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createUploadField: function() {
|
createUploadField: function() {
|
||||||
return {
|
return {
|
||||||
xtype: "fileuploadfield",
|
xtype: "fileuploadfield",
|
||||||
ref: 'fileuploadfield',
|
ref: 'fileuploadfield',
|
||||||
columnWidth: 1.0,
|
columnWidth: 1.0,
|
||||||
id: 'form-file',
|
id: 'form-file',
|
||||||
name: 'icsdata',
|
name: 'icsdata',
|
||||||
emptyText: 'Select an .ics calendar',
|
emptyText: 'Select an .ics calendar',
|
||||||
border: false,
|
border: false,
|
||||||
anchor: "100%",
|
anchor: "100%",
|
||||||
scope: this,
|
scope: this,
|
||||||
allowBlank: false,
|
allowBlank: false,
|
||||||
listeners: {
|
listeners: {
|
||||||
'fileselected': this.onFileSelected,
|
'fileselected': this.onFileSelected,
|
||||||
scope: this
|
scope: this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createSubmitButton: function() {
|
createSubmitButton: function() {
|
||||||
return {
|
return {
|
||||||
xtype: "button",
|
xtype: "button",
|
||||||
ref: "submitButton",
|
ref: "submitButton",
|
||||||
id: "submitButton",
|
id: "submitButton",
|
||||||
disabled: true,
|
disabled: true,
|
||||||
width: 100,
|
width: 100,
|
||||||
border: false,
|
border: false,
|
||||||
text: _("Import"),
|
text: _("Import"),
|
||||||
anchor: "100%",
|
anchor: "100%",
|
||||||
handler: this.importAllEvents,
|
handler: this.importCheckedEvents,
|
||||||
scope: this,
|
scope: this,
|
||||||
allowBlank: false
|
allowBlank: false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
createSubmitAllButton: function() {
|
||||||
|
return {
|
||||||
|
xtype: "button",
|
||||||
|
ref: "submitAllButton",
|
||||||
|
id: "submitAllButton",
|
||||||
|
disabled: true,
|
||||||
|
width: 100,
|
||||||
|
border: false,
|
||||||
|
text: _("Import All"),
|
||||||
|
anchor: "100%",
|
||||||
|
handler: this.importAllEvents,
|
||||||
|
scope: this,
|
||||||
|
allowBlank: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
createCancelButton: function() {
|
createCancelButton: function() {
|
||||||
return {
|
return {
|
||||||
xtype: "button",
|
xtype: "button",
|
||||||
width: 100,
|
width: 100,
|
||||||
border: false,
|
border: false,
|
||||||
text: _("Cancel"),
|
text: _("Cancel"),
|
||||||
anchor: "100%",
|
anchor: "100%",
|
||||||
handler: this.close,
|
handler: this.close,
|
||||||
scope: this,
|
scope: this,
|
||||||
allowBlank: false
|
allowBlank: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -230,7 +249,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
* in the {@link Ext.ux.form.FileUploadField} and the dialog is closed
|
* in the {@link Ext.ux.form.FileUploadField} and the dialog is closed
|
||||||
* @param {Ext.ux.form.FileUploadField} uploadField being added a file to
|
* @param {Ext.ux.form.FileUploadField} uploadField being added a file to
|
||||||
*/
|
*/
|
||||||
onFileSelected : function(uploadField) {
|
onFileSelected : function(uploadField) {
|
||||||
var form = this.addFormPanel.getForm();
|
var form = this.addFormPanel.getForm();
|
||||||
|
|
||||||
if (form.isValid()) {
|
if (form.isValid()) {
|
||||||
@ -238,7 +257,8 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
waitMsg: 'Uploading and parsing calendar...',
|
waitMsg: 'Uploading and parsing calendar...',
|
||||||
url: 'plugins/calendarimporter/php/upload.php',
|
url: 'plugins/calendarimporter/php/upload.php',
|
||||||
failure: function(file, action) {
|
failure: function(file, action) {
|
||||||
Ext.getCmp('submitButton').disable(); // momstly called...
|
Ext.getCmp('submitButton').disable();
|
||||||
|
Ext.getCmp('submitAllButton').disable();
|
||||||
Ext.MessageBox.show({
|
Ext.MessageBox.show({
|
||||||
title : _('Error'),
|
title : _('Error'),
|
||||||
msg : _(action.result.errors[action.result.errors.type]),
|
msg : _(action.result.errors[action.result.errors.type]),
|
||||||
@ -249,6 +269,7 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
success: function(file, action){
|
success: function(file, action){
|
||||||
uploadField.reset();
|
uploadField.reset();
|
||||||
Ext.getCmp('submitButton').enable();
|
Ext.getCmp('submitButton').enable();
|
||||||
|
Ext.getCmp('submitAllButton').enable();
|
||||||
this.timezone = action.result.response.calendar["X-WR-TIMEZONE"];
|
this.timezone = action.result.response.calendar["X-WR-TIMEZONE"];
|
||||||
this.insert(this.items.length,this.createGrid(action.result.response));
|
this.insert(this.items.length,this.createGrid(action.result.response));
|
||||||
this.doLayout();
|
this.doLayout();
|
||||||
@ -284,22 +305,94 @@ Zarafa.plugins.calendarimporter.dialogs.ImportPanel = Ext.extend(Ext.form.FormPa
|
|||||||
return newRecord;
|
return newRecord;
|
||||||
},
|
},
|
||||||
|
|
||||||
importAllEvents: function () {
|
importAllEvents: function () {
|
||||||
//receive existing calendar store
|
//receive existing calendar store
|
||||||
var calendarStore = new Zarafa.calendar.AppointmentStore();
|
var selIndex = this.calendarselector.selectedIndex;
|
||||||
var calendarFolder = container.getHierarchyStore().getDefaultFolder('calendar');
|
var calValue = this.calendarselector.value;
|
||||||
|
|
||||||
//receive Records from grid rows
|
if(selIndex == -1) { // no calendar choosen
|
||||||
var newRecords = this.eventgrid.selModel.getSelections();
|
Ext.MessageBox.show({
|
||||||
Ext.each(newRecords, function(newRecord) {
|
title : _('Error'),
|
||||||
var record = this.convertToAppointmentRecord(calendarFolder,newRecord.data);
|
msg : _('You have to choose a calendar!'),
|
||||||
console.log(record);
|
icon : Ext.MessageBox.ERROR,
|
||||||
calendarStore.add(record);
|
buttons : Ext.MessageBox.OK
|
||||||
}, this);
|
});
|
||||||
calendarStore.save();
|
} else {
|
||||||
this.dialog.close();
|
|
||||||
|
var calendarStore = new Zarafa.calendar.AppointmentStore();
|
||||||
|
var calendarFolder = container.getHierarchyStore().getDefaultFolder('calendar');
|
||||||
|
if(calValue != "calendar") {
|
||||||
|
var subFolders = calendarFolder.getChildren();
|
||||||
|
|
||||||
|
for(i=0;i<subFolders.length;i++) {
|
||||||
|
// loo up right folder
|
||||||
|
// TODO: improve!!
|
||||||
|
if(subFolders[i].getDisplayName() == calValue) {
|
||||||
|
calendarFolder = subFolders[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//receive Records from grid rows
|
||||||
|
this.eventgrid.selModel.selectAll(); // select all entries
|
||||||
|
var newRecords = this.eventgrid.selModel.getSelections();
|
||||||
|
Ext.each(newRecords, function(newRecord) {
|
||||||
|
var record = this.convertToAppointmentRecord(calendarFolder,newRecord.data);
|
||||||
|
calendarStore.add(record);
|
||||||
|
}, this);
|
||||||
|
calendarStore.save();
|
||||||
|
this.dialog.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
importCheckedEvents: function () {
|
||||||
|
//receive existing calendar store
|
||||||
|
var selIndex = this.calendarselector.selectedIndex;
|
||||||
|
var calValue = this.calendarselector.value;
|
||||||
|
|
||||||
|
if(selIndex == -1) { // no calendar choosen
|
||||||
|
Ext.MessageBox.show({
|
||||||
|
title : _('Error'),
|
||||||
|
msg : _('You have to choose a calendar!'),
|
||||||
|
icon : Ext.MessageBox.ERROR,
|
||||||
|
buttons : Ext.MessageBox.OK
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if(this.eventgrid.selModel.getCount() < 1) {
|
||||||
|
Ext.MessageBox.show({
|
||||||
|
title : _('Error'),
|
||||||
|
msg : _('You have to choose at least one event to import!'),
|
||||||
|
icon : Ext.MessageBox.ERROR,
|
||||||
|
buttons : Ext.MessageBox.OK
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var calendarStore = new Zarafa.calendar.AppointmentStore();
|
||||||
|
var calendarFolder = container.getHierarchyStore().getDefaultFolder('calendar');
|
||||||
|
if(calValue != "calendar") {
|
||||||
|
var subFolders = calendarFolder.getChildren();
|
||||||
|
|
||||||
|
for(i=0;i<subFolders.length;i++) {
|
||||||
|
// loo up right folder
|
||||||
|
// TODO: improve!!
|
||||||
|
if(subFolders[i].getDisplayName() == calValue) {
|
||||||
|
calendarFolder = subFolders[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//receive Records from grid rows
|
||||||
|
var newRecords = this.eventgrid.selModel.getSelections();
|
||||||
|
Ext.each(newRecords, function(newRecord) {
|
||||||
|
var record = this.convertToAppointmentRecord(calendarFolder,newRecord.data);
|
||||||
|
calendarStore.add(record);
|
||||||
|
}, this);
|
||||||
|
calendarStore.save();
|
||||||
|
this.dialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ext.reg('calendarimporter.importpanel', Zarafa.plugins.calendarimporter.dialogs.ImportPanel);
|
Ext.reg('calendarimporter.importpanel', Zarafa.plugins.calendarimporter.dialogs.ImportPanel);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
<!DOCTYPE plugin SYSTEM "manifest.dtd">
|
<!DOCTYPE plugin SYSTEM "manifest.dtd">
|
||||||
<plugin version="2">
|
<plugin version="2">
|
||||||
<info>
|
<info>
|
||||||
<version>0.1</version>
|
<version>1.0</version>
|
||||||
<name>calendarimporter</name>
|
<name>calendarimporter</name>
|
||||||
<title>ICS Calendar Importer</title>
|
<title>ICS Calendar Importer</title>
|
||||||
<author>Christoph Haas</author>
|
<author>Christoph Haas</author>
|
||||||
|
@ -5,10 +5,12 @@
|
|||||||
* PHP Version 5
|
* PHP Version 5
|
||||||
*
|
*
|
||||||
* @category Parser
|
* @category Parser
|
||||||
|
* @author Martin Thoma
|
||||||
* @author Christoph Haas <mail@h44z.net>
|
* @author Christoph Haas <mail@h44z.net>
|
||||||
|
* @modified 17.11.2012 by Christoph Haas (original at http://code.google.com/p/ics-parser/)
|
||||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||||
* @version SVN: 13
|
* @version SVN: 16
|
||||||
* @example $ical = new ical('MyCal.ics');
|
* @example $ical = new ical('calendar.ics');
|
||||||
* print_r( $ical->events() );
|
* print_r( $ical->events() );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -18,393 +20,322 @@
|
|||||||
* @param {string} filename The name of the file which should be parsed
|
* @param {string} filename The name of the file which should be parsed
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
class ICal
|
class ICal {
|
||||||
{
|
/* How many ToDos are in this ical? */
|
||||||
/* How many ToDos are in this ical? */
|
public /** @type {int} */ $todo_count = 0;
|
||||||
public /** @type {int} */ $todo_count = 0;
|
|
||||||
|
|
||||||
/* How many events are in this ical? */
|
/* How many events are in this ical? */
|
||||||
public /** @type {int} */ $event_count = 0;
|
public /** @type {int} */ $event_count = 0;
|
||||||
|
|
||||||
/* The parsed calendar */
|
/* The parsed calendar */
|
||||||
public /** @type {Array} */ $cal;
|
public /** @type {Array} */ $cal;
|
||||||
|
|
||||||
/* Error message store... null default */
|
/* Error message store... null default */
|
||||||
public /** @type {String} */ $errors;
|
public /** @type {String} */ $errors;
|
||||||
|
|
||||||
/* Which keyword has been added to cal at last? */
|
/* Which keyword has been added to cal at last? */
|
||||||
private /** @type {string} */ $_lastKeyWord;
|
private /** @type {string} */ $_lastKeyWord;
|
||||||
|
|
||||||
/**
|
/* The default timezone, used to convert UTC Time */
|
||||||
* Creates the iCal-Object
|
private /** @type {string} */ $default_timezone = "Europe/Vienna";
|
||||||
*
|
|
||||||
* @param {string} $filename The path to the iCal-file
|
|
||||||
*
|
|
||||||
* @return Object The iCal-Object
|
|
||||||
*/
|
|
||||||
public function __construct($filename)
|
|
||||||
{
|
|
||||||
if (!$filename) {
|
|
||||||
$this->errors = "No filename specified";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
||||||
if (stristr($lines[0], 'BEGIN:VCALENDAR') === false) {
|
|
||||||
$this->errors = "Not a valid ical file";
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
// TODO: Fix multiline-description problem (see http://tools.ietf.org/html/rfc2445#section-4.8.1.5)
|
|
||||||
foreach ($lines as $line) {
|
|
||||||
$line = trim($line);
|
|
||||||
$add = $this->keyValueFromString($line);
|
|
||||||
if ($add === false) {
|
|
||||||
$this->addCalendarComponentWithKeyAndValue($type, false, $line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($keyword, $value) = $add;
|
|
||||||
|
|
||||||
switch ($line) {
|
|
||||||
// http://www.kanzaki.com/docs/ical/vtodo.html
|
|
||||||
case "BEGIN:VTODO":
|
|
||||||
$this->todo_count++;
|
|
||||||
$type = "VTODO";
|
|
||||||
break;
|
|
||||||
|
|
||||||
// http://www.kanzaki.com/docs/ical/vevent.html
|
|
||||||
case "BEGIN:VEVENT":
|
|
||||||
//echo "vevent gematcht";
|
|
||||||
$this->event_count++;
|
|
||||||
$type = "VEVENT";
|
|
||||||
break;
|
|
||||||
|
|
||||||
//all other special strings
|
|
||||||
case "BEGIN:VCALENDAR":
|
|
||||||
case "BEGIN:DAYLIGHT":
|
|
||||||
// http://www.kanzaki.com/docs/ical/vtimezone.html
|
|
||||||
case "BEGIN:VTIMEZONE":
|
|
||||||
case "BEGIN:STANDARD":
|
|
||||||
$type = $value;
|
|
||||||
break;
|
|
||||||
case "END:VTODO": // end special text - goto VCALENDAR key
|
|
||||||
case "END:VEVENT":
|
|
||||||
case "END:VCALENDAR":
|
|
||||||
case "END:DAYLIGHT":
|
|
||||||
case "END:VTIMEZONE":
|
|
||||||
case "END:STANDARD":
|
|
||||||
$type = "VCALENDAR";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->addCalendarComponentWithKeyAndValue($type,
|
|
||||||
$keyword,
|
|
||||||
$value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->cal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the iCal-Object
|
* Creates the iCal-Object
|
||||||
*
|
*
|
||||||
* @param {string} $filecontent The content of the iCal-file
|
* @param {string} $filename The path to the iCal-file
|
||||||
*
|
*
|
||||||
* @return Object The iCal-Object
|
* @return Object The iCal-Object
|
||||||
*/
|
*/
|
||||||
public function setContent($filecontent)
|
public function __construct($filename) {
|
||||||
{
|
if (!$filename) {
|
||||||
if (!$filecontent) {
|
$this->errors = "No filename specified";
|
||||||
$this->errors = "No filecontent";
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$lines = explode("\n", $filecontent);
|
$lines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||||
if (stristr($lines[0], 'BEGIN:VCALENDAR') === false) {
|
if (stristr($lines[0], 'BEGIN:VCALENDAR') === false) {
|
||||||
$this->errors = "Not a valid ical file";
|
$this->errors = "Not a valid ical file";
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// TODO: Fix multiline-description problem (see http://tools.ietf.org/html/rfc2445#section-4.8.1.5)
|
|
||||||
foreach ($lines as $line) {
|
|
||||||
$line = trim($line);
|
|
||||||
$add = $this->keyValueFromString($line);
|
|
||||||
if ($add === false) {
|
|
||||||
$this->addCalendarComponentWithKeyAndValue($type, false, $line);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
list($keyword, $value) = $add;
|
foreach ($lines as $line) {
|
||||||
|
$line = trim($line);
|
||||||
|
$add = $this->keyValueFromString($line);
|
||||||
|
if ($add === false) {
|
||||||
|
$this->addCalendarComponentWithKeyAndValue($type, false, $line);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch ($line) {
|
list($keyword, $value) = $add;
|
||||||
// http://www.kanzaki.com/docs/ical/vtodo.html
|
|
||||||
case "BEGIN:VTODO":
|
|
||||||
$this->todo_count++;
|
|
||||||
$type = "VTODO";
|
|
||||||
break;
|
|
||||||
|
|
||||||
// http://www.kanzaki.com/docs/ical/vevent.html
|
switch ($line) {
|
||||||
case "BEGIN:VEVENT":
|
// http://www.kanzaki.com/docs/ical/vtodo.html
|
||||||
//echo "vevent gematcht";
|
case "BEGIN:VTODO":
|
||||||
$this->event_count++;
|
$this->todo_count++;
|
||||||
$type = "VEVENT";
|
$type = "VTODO";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//all other special strings
|
// http://www.kanzaki.com/docs/ical/vevent.html
|
||||||
case "BEGIN:VCALENDAR":
|
case "BEGIN:VEVENT":
|
||||||
case "BEGIN:DAYLIGHT":
|
//echo "vevent gematcht";
|
||||||
// http://www.kanzaki.com/docs/ical/vtimezone.html
|
$this->event_count++;
|
||||||
case "BEGIN:VTIMEZONE":
|
$type = "VEVENT";
|
||||||
case "BEGIN:STANDARD":
|
break;
|
||||||
$type = $value;
|
|
||||||
break;
|
|
||||||
case "END:VTODO": // end special text - goto VCALENDAR key
|
|
||||||
case "END:VEVENT":
|
|
||||||
case "END:VCALENDAR":
|
|
||||||
case "END:DAYLIGHT":
|
|
||||||
case "END:VTIMEZONE":
|
|
||||||
case "END:STANDARD":
|
|
||||||
$type = "VCALENDAR";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$this->addCalendarComponentWithKeyAndValue($type,
|
|
||||||
$keyword,
|
|
||||||
$value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->cal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
//all other special strings
|
||||||
* Add to $this->ical array one value and key.
|
case "BEGIN:VCALENDAR":
|
||||||
*
|
case "BEGIN:DAYLIGHT":
|
||||||
* @param {string} $component This could be VTODO, VEVENT, VCALENDAR, ...
|
// http://www.kanzaki.com/docs/ical/vtimezone.html
|
||||||
* @param {string} $keyword The keyword, for example DTSTART
|
case "BEGIN:VTIMEZONE":
|
||||||
* @param {string} $value The value, for example 20110105T090000Z
|
case "BEGIN:STANDARD":
|
||||||
*
|
$type = $value;
|
||||||
* @return {None}
|
break;
|
||||||
*/
|
case "END:VTODO": // end special text - goto VCALENDAR key
|
||||||
public function addCalendarComponentWithKeyAndValue($component,
|
case "END:VEVENT":
|
||||||
$keyword,
|
case "END:VCALENDAR":
|
||||||
$value)
|
case "END:DAYLIGHT":
|
||||||
{
|
case "END:VTIMEZONE":
|
||||||
if ($keyword == false) {
|
case "END:STANDARD":
|
||||||
$keyword = $this->last_keyword;
|
$type = "VCALENDAR";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->addCalendarComponentWithKeyAndValue($type, $keyword, $value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->cal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch ($component) {
|
/**
|
||||||
case 'VEVENT':
|
* Add to $this->ical array one value and key.
|
||||||
|
*
|
||||||
|
* @param {string} $component This could be VTODO, VEVENT, VCALENDAR, ...
|
||||||
|
* @param {string} $keyword The keyword, for example DTSTART
|
||||||
|
* @param {string} $value The value, for example 20110105T090000Z
|
||||||
|
*
|
||||||
|
* @return {None}
|
||||||
|
*/
|
||||||
|
public function addCalendarComponentWithKeyAndValue($component, $keyword, $value) {
|
||||||
|
if ($keyword == false) {
|
||||||
|
$keyword = $this->last_keyword;
|
||||||
|
|
||||||
|
switch ($component) {
|
||||||
|
case 'VEVENT':
|
||||||
if (stristr($keyword, "DTSTART") or stristr($keyword, "DTEND")) {
|
if (stristr($keyword, "DTSTART") or stristr($keyword, "DTEND")) {
|
||||||
$ts = $this->iCalDateToUnixTimestamp($value);
|
$ts = $this->iCalDateToUnixTimestamp($value);
|
||||||
$value = $ts * 1000;
|
$value = $ts * 1000;
|
||||||
}
|
}
|
||||||
$value = str_replace("\\n", "\n", $value);
|
$value = str_replace("\\n", "\n", $value);
|
||||||
$value = $this->cal[$component][$this->event_count - 1]
|
$value = $this->cal[$component][$this->event_count - 1]
|
||||||
[$keyword].$value;
|
[$keyword].$value;
|
||||||
break;
|
break;
|
||||||
case 'VTODO' :
|
case 'VTODO' :
|
||||||
$value = $this->cal[$component][$this->todo_count - 1]
|
$value = $this->cal[$component][$this->todo_count - 1]
|
||||||
[$keyword].$value;
|
[$keyword].$value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stristr($keyword, "DTSTART") or stristr($keyword, "DTEND")) {
|
if (stristr($keyword, "DTSTART") or stristr($keyword, "DTEND")) {
|
||||||
$keyword = explode(";", $keyword);
|
$keyword = explode(";", $keyword);
|
||||||
$keyword = $keyword[0]; // remove additional content like VALUE=DATE
|
$keyword = $keyword[0]; // remove additional content like VALUE=DATE
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ($component) {
|
if (stristr($keyword, "TIMEZONE")) {
|
||||||
case "VTODO":
|
$this->default_timezone = $value; // store the calendertimezone
|
||||||
$this->cal[$component][$this->todo_count - 1][$keyword] = $value;
|
}
|
||||||
//$this->cal[$component][$this->todo_count]['Unix'] = $unixtime;
|
|
||||||
break;
|
switch ($component) {
|
||||||
case "VEVENT":
|
case "VTODO":
|
||||||
|
$this->cal[$component][$this->todo_count - 1][$keyword] = $value;
|
||||||
|
//$this->cal[$component][$this->todo_count]['Unix'] = $unixtime;
|
||||||
|
break;
|
||||||
|
case "VEVENT":
|
||||||
if (stristr($keyword, "DTSTART") or stristr($keyword, "DTEND")) {
|
if (stristr($keyword, "DTSTART") or stristr($keyword, "DTEND")) {
|
||||||
$ts = $this->iCalDateToUnixTimestamp($value);
|
$ts = $this->iCalDateToUnixTimestamp($value);
|
||||||
$value = $ts * 1000;
|
$value = $ts * 1000;
|
||||||
}
|
}
|
||||||
$value = str_replace("\\n", "\n", $value);
|
$value = str_replace("\\n", "\n", $value);
|
||||||
$this->cal[$component][$this->event_count - 1][$keyword] = $value;
|
$this->cal[$component][$this->event_count - 1][$keyword] = $value;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$this->cal[$component][$keyword] = $value;
|
$this->cal[$component][$keyword] = $value;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$this->last_keyword = $keyword;
|
$this->last_keyword = $keyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a key-value pair of a string.
|
|
||||||
*
|
|
||||||
* @param {string} $text which is like "VCALENDAR:Begin" or "LOCATION:"
|
|
||||||
*
|
|
||||||
* @return {array} array("VCALENDAR", "Begin")
|
|
||||||
*/
|
|
||||||
public function keyValueFromString($text)
|
|
||||||
{
|
|
||||||
preg_match("/(^[^a-z:]+)[:]([\w\W]*)/", $text, $matches);
|
|
||||||
error_log("Matching: " . count($matches) . " " . $text);
|
|
||||||
if (count($matches) == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$matches = array_splice($matches, 1, 2);
|
|
||||||
return $matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return Unix timestamp from ical date time format
|
|
||||||
*
|
|
||||||
* @param {string} $icalDate A Date in the format YYYYMMDD[T]HHMMSS[Z] or
|
|
||||||
* YYYYMMDD[T]HHMMSS
|
|
||||||
*
|
|
||||||
* @return {int}
|
|
||||||
*/
|
|
||||||
public function iCalDateToUnixTimestamp($icalDate)
|
|
||||||
{
|
|
||||||
$icalDate = str_replace('T', '', $icalDate);
|
|
||||||
$icalDate = str_replace('Z', '', $icalDate);
|
|
||||||
|
|
||||||
$pattern = '/([0-9]{4})'; // 1: YYYY
|
|
||||||
$pattern .= '([0-9]{2})'; // 2: MM
|
|
||||||
$pattern .= '([0-9]{2})'; // 3: DD
|
|
||||||
$pattern .= '([0-9]{0,2})'; // 4: HH
|
|
||||||
$pattern .= '([0-9]{0,2})'; // 5: MM
|
|
||||||
$pattern .= '([0-9]{0,2})/'; // 6: SS
|
|
||||||
preg_match($pattern, $icalDate, $date);
|
|
||||||
|
|
||||||
// Unix timestamp can't represent dates before 1970
|
|
||||||
if ($date[1] <= 1970) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Unix timestamps after 03:14:07 UTC 2038-01-19 might cause an overflow
|
|
||||||
// if 32 bit integers are used.
|
|
||||||
$timestamp = mktime((int)$date[4],
|
|
||||||
(int)$date[5],
|
|
||||||
(int)$date[6],
|
|
||||||
(int)$date[2],
|
|
||||||
(int)$date[3],
|
|
||||||
(int)$date[1]);
|
|
||||||
return $timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of arrays with all events. Every event is an associative
|
|
||||||
* array and each property is an element it.
|
|
||||||
*
|
|
||||||
* @return {array}
|
|
||||||
*/
|
|
||||||
public function events()
|
|
||||||
{
|
|
||||||
$array = $this->cal;
|
|
||||||
return $array['VEVENT'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an array of calendar types.
|
* Get a key-value pair of a string.
|
||||||
*
|
*
|
||||||
* @return {array}
|
* @param {string} $text which is like "VCALENDAR:Begin" or "LOCATION:"
|
||||||
*/
|
*
|
||||||
public function calendar()
|
* @return {array} array("VCALENDAR", "Begin")
|
||||||
{
|
*/
|
||||||
$array = $this->cal;
|
public function keyValueFromString($text) {
|
||||||
return $array['VCALENDAR'];
|
preg_match("/(^[^a-z:]+)[:]([\w\W]*)/", $text, $matches);
|
||||||
}
|
if (count($matches) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$matches = array_splice($matches, 1, 2);
|
||||||
|
return $matches;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a boolean value whether thr current calendar has events or not
|
* Return Unix timestamp from ical date time format
|
||||||
*
|
*
|
||||||
* @return {boolean}
|
* @param {string} $icalDate A Date in the format YYYYMMDD[T]HHMMSS[Z] or
|
||||||
*/
|
* YYYYMMDD[T]HHMMSS
|
||||||
public function hasEvents()
|
*
|
||||||
{
|
* @return {int}
|
||||||
return ( count($this->events()) > 0 ? true : false );
|
*/
|
||||||
}
|
public function iCalDateToUnixTimestamp($icalDate) {
|
||||||
|
$icalDate = str_replace('T', '', $icalDate);
|
||||||
|
$icalDate = str_replace('Z', '', $icalDate);
|
||||||
|
|
||||||
/**
|
$pattern = '/([0-9]{4})'; // 1: YYYY
|
||||||
* Returns false when the current calendar has no events in range, else the
|
$pattern .= '([0-9]{2})'; // 2: MM
|
||||||
* events.
|
$pattern .= '([0-9]{2})'; // 3: DD
|
||||||
*
|
$pattern .= '([0-9]{0,2})'; // 4: HH
|
||||||
* Note that this function makes use of a UNIX timestamp. This might be a
|
$pattern .= '([0-9]{0,2})'; // 5: MM
|
||||||
* problem on January the 29th, 2038.
|
$pattern .= '([0-9]{0,2})/'; // 6: SS
|
||||||
* See http://en.wikipedia.org/wiki/Unix_time#Representing_the_number
|
preg_match($pattern, $icalDate, $date);
|
||||||
*
|
|
||||||
* @param {boolean} $rangeStart Either true or false
|
|
||||||
* @param {boolean} $rangeEnd Either true or false
|
|
||||||
*
|
|
||||||
* @return {mixed}
|
|
||||||
*/
|
|
||||||
public function eventsFromRange($rangeStart = false, $rangeEnd = false)
|
|
||||||
{
|
|
||||||
$events = $this->sortEventsWithOrder($this->events(), SORT_ASC);
|
|
||||||
|
|
||||||
if (!$events) {
|
// Unix timestamp can't represent dates before 1970
|
||||||
return false;
|
if ($date[1] <= 1970) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
// Unix timestamps after 03:14:07 UTC 2038-01-19 might cause an overflow
|
||||||
|
// if 32 bit integers are used.
|
||||||
|
$timestamp = mktime((int)$date[4],
|
||||||
|
(int)$date[5],
|
||||||
|
(int)$date[6],
|
||||||
|
(int)$date[2],
|
||||||
|
(int)$date[3],
|
||||||
|
(int)$date[1]);
|
||||||
|
|
||||||
$extendedEvents = array();
|
|
||||||
|
|
||||||
if ($rangeStart !== false) {
|
$utcdate = new DateTime();
|
||||||
$rangeStart = new DateTime();
|
$utcdate->setTimestamp($timestamp);
|
||||||
}
|
$utcdate->setTimezone(new DateTimeZone($this->default_timezone));
|
||||||
|
$utcoffset = $utcdate->getOffset();
|
||||||
|
|
||||||
if ($rangeEnd !== false or $rangeEnd <= 0) {
|
|
||||||
$rangeEnd = new DateTime('2038/01/18');
|
|
||||||
} else {
|
|
||||||
$rangeEnd = new DateTime($rangeEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
$rangeStart = $rangeStart->format('U');
|
return ($timestamp + $utcoffset);
|
||||||
$rangeEnd = $rangeEnd->format('U');
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of arrays with all events. Every event is an associative
|
||||||
|
* array and each property is an element it.
|
||||||
|
*
|
||||||
|
* @return {array}
|
||||||
|
*/
|
||||||
|
public function events() {
|
||||||
|
$array = $this->cal;
|
||||||
|
return $array['VEVENT'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of calendar types.
|
||||||
|
*
|
||||||
|
* @return {array}
|
||||||
|
*/
|
||||||
|
public function calendar() {
|
||||||
|
$array = $this->cal;
|
||||||
|
return $array['VCALENDAR'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a boolean value whether thr current calendar has events or not
|
||||||
|
*
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
public function hasEvents() {
|
||||||
|
return ( count($this->events()) > 0 ? true : false );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns false when the current calendar has no events in range, else the
|
||||||
|
* events.
|
||||||
|
*
|
||||||
|
* Note that this function makes use of a UNIX timestamp. This might be a
|
||||||
|
* problem on January the 29th, 2038.
|
||||||
|
* See http://en.wikipedia.org/wiki/Unix_time#Representing_the_number
|
||||||
|
*
|
||||||
|
* @param {boolean} $rangeStart Either true or false
|
||||||
|
* @param {boolean} $rangeEnd Either true or false
|
||||||
|
*
|
||||||
|
* @return {mixed}
|
||||||
|
*/
|
||||||
|
public function eventsFromRange($rangeStart = false, $rangeEnd = false) {
|
||||||
|
$events = $this->sortEventsWithOrder($this->events(), SORT_ASC);
|
||||||
|
|
||||||
|
if (!$events) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$extendedEvents = array();
|
||||||
|
|
||||||
|
if ($rangeStart !== false) {
|
||||||
|
$rangeStart = new DateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($rangeEnd !== false or $rangeEnd <= 0) {
|
||||||
|
$rangeEnd = new DateTime('2038/01/18');
|
||||||
|
} else {
|
||||||
|
$rangeEnd = new DateTime($rangeEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
$rangeStart = $rangeStart->format('U');
|
||||||
|
$rangeEnd = $rangeEnd->format('U');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// loop through all events by adding two new elements
|
// loop through all events by adding two new elements
|
||||||
foreach ($events as $anEvent) {
|
foreach ($events as $anEvent) {
|
||||||
$timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTSTART']);
|
$timestamp = $this->iCalDateToUnixTimestamp($anEvent['DTSTART']);
|
||||||
if ($timestamp >= $rangeStart && $timestamp <= $rangeEnd) {
|
if ($timestamp >= $rangeStart && $timestamp <= $rangeEnd) {
|
||||||
$extendedEvents[] = $anEvent;
|
$extendedEvents[] = $anEvent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $extendedEvents;
|
return $extendedEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns sorted events
|
* Returns sorted events
|
||||||
*
|
*
|
||||||
* @param {array} $events An array with events.
|
* @param {array} $events An array with events.
|
||||||
* @param {array} $sortOrder Either SORT_ASC, SORT_DESC, SORT_REGULAR,
|
* @param {array} $sortOrder Either SORT_ASC, SORT_DESC, SORT_REGULAR,
|
||||||
* SORT_NUMERIC, SORT_STRING
|
* SORT_NUMERIC, SORT_STRING
|
||||||
*
|
*
|
||||||
* @return {array}
|
* @return {array}
|
||||||
*/
|
*/
|
||||||
public function sortEventsWithOrder($events, $sortOrder = SORT_ASC)
|
public function sortEventsWithOrder($events, $sortOrder = SORT_ASC) {
|
||||||
{
|
$extendedEvents = array();
|
||||||
$extendedEvents = array();
|
|
||||||
|
|
||||||
// loop through all events by adding two new elements
|
// loop through all events by adding two new elements
|
||||||
foreach ($events as $anEvent) {
|
foreach ($events as $anEvent) {
|
||||||
if (!array_key_exists('UNIX_TIMESTAMP', $anEvent)) {
|
if (!array_key_exists('UNIX_TIMESTAMP', $anEvent)) {
|
||||||
$anEvent['UNIX_TIMESTAMP'] =
|
$anEvent['UNIX_TIMESTAMP'] =
|
||||||
$this->iCalDateToUnixTimestamp($anEvent['DTSTART']);
|
$this->iCalDateToUnixTimestamp($anEvent['DTSTART']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!array_key_exists('REAL_DATETIME', $anEvent)) {
|
if (!array_key_exists('REAL_DATETIME', $anEvent)) {
|
||||||
$anEvent['REAL_DATETIME'] =
|
$anEvent['REAL_DATETIME'] =
|
||||||
date("d.m.Y", $anEvent['UNIX_TIMESTAMP']);
|
date("d.m.Y", $anEvent['UNIX_TIMESTAMP']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$extendedEvents[] = $anEvent;
|
$extendedEvents[] = $anEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($extendedEvents as $key => $value) {
|
foreach ($extendedEvents as $key => $value) {
|
||||||
$timestamp[$key] = $value['UNIX_TIMESTAMP'];
|
$timestamp[$key] = $value['UNIX_TIMESTAMP'];
|
||||||
}
|
}
|
||||||
array_multisort($timestamp, $sortOrder, $extendedEvents);
|
array_multisort($timestamp, $sortOrder, $extendedEvents);
|
||||||
|
|
||||||
return $extendedEvents;
|
return $extendedEvents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
@ -47,7 +47,7 @@ class Plugincalendarimporter extends Plugin {
|
|||||||
'plugins' => Array(
|
'plugins' => Array(
|
||||||
'calendarimporter' => Array(
|
'calendarimporter' => Array(
|
||||||
'enable' => PLUGIN_CALENDARIMPORTER_USER_DEFAULT_ENABLE,
|
'enable' => PLUGIN_CALENDARIMPORTER_USER_DEFAULT_ENABLE,
|
||||||
'default_calendar' => PLUGIN_CALENDARIMPORTER_DEFAULT
|
'default_calendar' => PLUGIN_CALENDARIMPORTER_DEFAULT // currently not used, maybe in next release
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user