Version Description
Download this release
Release Info
Developer | murgroland |
Plugin | WP Simple Booking Calendar |
Version | 2.0 |
Comparing to | |
See all releases |
Code changes from version 1.5.5 to 2.0
- assets/css/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- assets/css/images/ui-icons_222222_256x240.png +0 -0
- assets/css/jquery-ui.css +1 -0
- assets/css/style-admin.css +611 -0
- assets/css/style-front-end.css +173 -0
- assets/css/style-front-end.min.css +1 -0
- assets/img/date-icon.svg +1 -0
- assets/img/flags/ad.png +0 -0
- assets/img/flags/ae.png +0 -0
- assets/img/flags/af.png +0 -0
- assets/img/flags/ag.png +0 -0
- assets/img/flags/ai.png +0 -0
- assets/img/flags/al.png +0 -0
- assets/img/flags/am.png +0 -0
- assets/img/flags/an.png +0 -0
- assets/img/flags/ao.png +0 -0
- assets/img/flags/ar.png +0 -0
- assets/img/flags/as.png +0 -0
- assets/img/flags/at.png +0 -0
- assets/img/flags/au.png +0 -0
- assets/img/flags/aw.png +0 -0
- assets/img/flags/ax.png +0 -0
- assets/img/flags/az.png +0 -0
- assets/img/flags/ba.png +0 -0
- assets/img/flags/bb.png +0 -0
- assets/img/flags/bd.png +0 -0
- assets/img/flags/be.png +0 -0
- assets/img/flags/bf.png +0 -0
- assets/img/flags/bg.png +0 -0
- assets/img/flags/bh.png +0 -0
- assets/img/flags/bi.png +0 -0
- assets/img/flags/bj.png +0 -0
- assets/img/flags/bm.png +0 -0
- assets/img/flags/bn.png +0 -0
- assets/img/flags/bo.png +0 -0
- assets/img/flags/br.png +0 -0
- assets/img/flags/bs.png +0 -0
- assets/img/flags/bt.png +0 -0
- assets/img/flags/bv.png +0 -0
- assets/img/flags/bw.png +0 -0
- assets/img/flags/by.png +0 -0
- assets/img/flags/bz.png +0 -0
- assets/img/flags/ca.png +0 -0
- assets/img/flags/cc.png +0 -0
- assets/img/flags/cd.png +0 -0
- assets/img/flags/cf.png +0 -0
- assets/img/flags/cg.png +0 -0
- assets/img/flags/ch.png +0 -0
- assets/img/flags/ci.png +0 -0
- assets/img/flags/ck.png +0 -0
- assets/img/flags/cl.png +0 -0
- assets/img/flags/cm.png +0 -0
- assets/img/flags/cn.png +0 -0
- assets/img/flags/co.png +0 -0
- assets/img/flags/cr.png +0 -0
- assets/img/flags/cs.png +0 -0
- assets/img/flags/cu.png +0 -0
- assets/img/flags/cv.png +0 -0
- assets/img/flags/cx.png +0 -0
- assets/img/flags/cy.png +0 -0
- assets/img/flags/cz.png +0 -0
- assets/img/flags/da.png +0 -0
- assets/img/flags/de.png +0 -0
- assets/img/flags/dj.png +0 -0
- assets/img/flags/dm.png +0 -0
- assets/img/flags/do.png +0 -0
- assets/img/flags/dz.png +0 -0
- assets/img/flags/ec.png +0 -0
- assets/img/flags/ee.png +0 -0
- assets/img/flags/eg.png +0 -0
- assets/img/flags/eh.png +0 -0
- assets/img/flags/el.png +0 -0
- assets/img/flags/en.png +0 -0
- assets/img/flags/england.png +0 -0
- assets/img/flags/er.png +0 -0
- assets/img/flags/es.png +0 -0
- assets/img/flags/et.png +0 -0
- assets/img/flags/eu.png +0 -0
- assets/img/flags/europeanunion.png +0 -0
- assets/img/flags/fam.png +0 -0
- assets/img/flags/fi.png +0 -0
- assets/img/flags/fj.png +0 -0
- assets/img/flags/fk.png +0 -0
- assets/img/flags/fm.png +0 -0
- assets/img/flags/fo.png +0 -0
- assets/img/flags/fr.png +0 -0
- assets/img/flags/ga.png +0 -0
- assets/img/flags/gb.png +0 -0
- assets/img/flags/gd.png +0 -0
- assets/img/flags/ge.png +0 -0
- assets/img/flags/gf.png +0 -0
- assets/img/flags/gh.png +0 -0
- assets/img/flags/gi.png +0 -0
- assets/img/flags/gl.png +0 -0
- assets/img/flags/gm.png +0 -0
- assets/img/flags/gn.png +0 -0
- assets/img/flags/gp.png +0 -0
- assets/img/flags/gq.png +0 -0
- assets/img/flags/gs.png +0 -0
- assets/img/flags/gt.png +0 -0
- assets/img/flags/gu.png +0 -0
- assets/img/flags/gw.png +0 -0
- assets/img/flags/gy.png +0 -0
- assets/img/flags/hk.png +0 -0
- assets/img/flags/hm.png +0 -0
- assets/img/flags/hn.png +0 -0
- assets/img/flags/hr.png +0 -0
- assets/img/flags/ht.png +0 -0
- assets/img/flags/hu.png +0 -0
- assets/img/flags/id.png +0 -0
- assets/img/flags/ie.png +0 -0
- assets/img/flags/il.png +0 -0
- assets/img/flags/in.png +0 -0
- assets/img/flags/io.png +0 -0
- assets/img/flags/iq.png +0 -0
- assets/img/flags/ir.png +0 -0
- assets/img/flags/is.png +0 -0
- assets/img/flags/it.png +0 -0
- assets/img/flags/jm.png +0 -0
- assets/img/flags/jo.png +0 -0
- assets/img/flags/jp.png +0 -0
- assets/img/flags/ke.png +0 -0
- assets/img/flags/kg.png +0 -0
- assets/img/flags/kh.png +0 -0
- assets/img/flags/ki.png +0 -0
- assets/img/flags/km.png +0 -0
- assets/img/flags/kn.png +0 -0
- assets/img/flags/kp.png +0 -0
- assets/img/flags/kr.png +0 -0
- assets/img/flags/kw.png +0 -0
- assets/img/flags/ky.png +0 -0
- assets/img/flags/kz.png +0 -0
- assets/img/flags/la.png +0 -0
- assets/img/flags/lb.png +0 -0
- assets/img/flags/lc.png +0 -0
- assets/img/flags/li.png +0 -0
- assets/img/flags/lk.png +0 -0
- assets/img/flags/lr.png +0 -0
- assets/img/flags/ls.png +0 -0
- assets/img/flags/lt.png +0 -0
- assets/img/flags/lu.png +0 -0
- assets/img/flags/lv.png +0 -0
- assets/img/flags/ly.png +0 -0
- assets/img/flags/ma.png +0 -0
- assets/img/flags/mc.png +0 -0
- assets/img/flags/md.png +0 -0
- assets/img/flags/me.png +0 -0
- assets/img/flags/mg.png +0 -0
- assets/img/flags/mh.png +0 -0
- assets/img/flags/mk.png +0 -0
- assets/img/flags/ml.png +0 -0
- assets/img/flags/mm.png +0 -0
- assets/img/flags/mn.png +0 -0
- assets/img/flags/mo.png +0 -0
- assets/img/flags/mp.png +0 -0
- assets/img/flags/mq.png +0 -0
- assets/img/flags/mr.png +0 -0
- assets/img/flags/ms.png +0 -0
- assets/img/flags/mt.png +0 -0
- assets/img/flags/mu.png +0 -0
- assets/img/flags/mv.png +0 -0
- assets/img/flags/mw.png +0 -0
- assets/img/flags/mx.png +0 -0
- assets/img/flags/my.png +0 -0
- assets/img/flags/mz.png +0 -0
- assets/img/flags/na.png +0 -0
- assets/img/flags/nc.png +0 -0
- assets/img/flags/ne.png +0 -0
- assets/img/flags/nf.png +0 -0
- assets/img/flags/ng.png +0 -0
- assets/img/flags/ni.png +0 -0
- assets/img/flags/nl.png +0 -0
- assets/img/flags/no.png +0 -0
- assets/img/flags/np.png +0 -0
- assets/img/flags/nr.png +0 -0
- assets/img/flags/nu.png +0 -0
- assets/img/flags/nz.png +0 -0
- assets/img/flags/om.png +0 -0
- assets/img/flags/pa.png +0 -0
- assets/img/flags/pe.png +0 -0
- assets/img/flags/pf.png +0 -0
- assets/img/flags/pg.png +0 -0
- assets/img/flags/ph.png +0 -0
- assets/img/flags/pk.png +0 -0
- assets/img/flags/pl.png +0 -0
- assets/img/flags/pm.png +0 -0
- assets/img/flags/pn.png +0 -0
- assets/img/flags/pr.png +0 -0
- assets/img/flags/ps.png +0 -0
- assets/img/flags/pt.png +0 -0
- assets/img/flags/pw.png +0 -0
- assets/img/flags/py.png +0 -0
- assets/img/flags/qa.png +0 -0
- assets/img/flags/re.png +0 -0
- assets/img/flags/ro.png +0 -0
- assets/img/flags/ru.png +0 -0
- assets/img/flags/rw.png +0 -0
- assets/img/flags/sa.png +0 -0
- assets/img/flags/sb.png +0 -0
- assets/img/flags/sc.png +0 -0
- assets/img/flags/scotland.png +0 -0
- assets/img/flags/sd.png +0 -0
- assets/img/flags/se.png +0 -0
- assets/img/flags/sg.png +0 -0
- assets/img/flags/sh.png +0 -0
- assets/img/flags/si.png +0 -0
- assets/img/flags/sj.png +0 -0
- assets/img/flags/sk.png +0 -0
- assets/img/flags/sl.png +0 -0
- assets/img/flags/sm.png +0 -0
- assets/img/flags/sn.png +0 -0
- assets/img/flags/so.png +0 -0
- assets/img/flags/sr.png +0 -0
- assets/img/flags/srn.png +0 -0
- assets/img/flags/st.png +0 -0
- assets/img/flags/sv.png +0 -0
- assets/img/flags/sy.png +0 -0
- assets/img/flags/sz.png +0 -0
- assets/img/flags/tc.png +0 -0
- assets/img/flags/td.png +0 -0
- assets/img/flags/tf.png +0 -0
- assets/img/flags/tg.png +0 -0
- assets/img/flags/th.png +0 -0
- assets/img/flags/tj.png +0 -0
- assets/img/flags/tk.png +0 -0
- assets/img/flags/tl.png +0 -0
- assets/img/flags/tm.png +0 -0
- assets/img/flags/tn.png +0 -0
- assets/img/flags/to.png +0 -0
- assets/img/flags/tr.png +0 -0
- assets/img/flags/tt.png +0 -0
- assets/img/flags/tv.png +0 -0
- assets/img/flags/tw.png +0 -0
- assets/img/flags/tz.png +0 -0
- assets/img/flags/ua.png +0 -0
- assets/img/flags/ug.png +0 -0
- assets/img/flags/um.png +0 -0
- assets/img/flags/us.png +0 -0
- assets/img/flags/uy.png +0 -0
- assets/img/flags/uz.png +0 -0
- assets/img/flags/va.png +0 -0
- assets/img/flags/vc.png +0 -0
- assets/img/flags/ve.png +0 -0
- assets/img/flags/vg.png +0 -0
- assets/img/flags/vi.png +0 -0
- assets/img/flags/vn.png +0 -0
- assets/img/flags/vu.png +0 -0
- assets/img/flags/wales.png +0 -0
- assets/img/flags/wf.png +0 -0
- assets/img/flags/ws.png +0 -0
- assets/img/flags/ye.png +0 -0
- assets/img/flags/yt.png +0 -0
- assets/img/flags/za.png +0 -0
- assets/img/flags/zm.png +0 -0
- assets/img/flags/zw.png +0 -0
- assets/js/script-admin-edit-calendar.js +368 -0
- assets/js/script-admin-uninstaller.js +44 -0
- assets/js/script-admin-upgrader.js +148 -0
- assets/js/script-admin.js +363 -0
- assets/js/script-front-end.js +283 -0
- assets/js/script-front-end.min.js +1 -0
- assets/libs/chosen/chosen-sprite.png +0 -0
- assets/libs/chosen/chosen-sprite@2x.png +0 -0
- assets/libs/chosen/chosen.css +448 -0
- assets/libs/chosen/chosen.jquery.min.js +2 -0
- blocks/sbc/assets/js/script-block-sbc.js +0 -71
- blocks/sbc/functions.php +0 -152
- css/sbc-controller.css +0 -98
- css/sbc-shortcode.css +0 -17
- css/sbc.css +0 -171
- images/button-bg.png +0 -0
- images/checked-icon.jpg +0 -0
- images/checked.png +0 -0
- includes/abstracts/abstract-class-db.php +66 -0
- includes/abstracts/abstract-class-list-table.php +1373 -0
- includes/abstracts/abstract-class-object-db.php +351 -0
- includes/abstracts/abstract-class-object-meta-db.php +95 -0
- includes/abstracts/abstract-class-object.php +58 -0
- includes/abstracts/abstract-class-submenu-page.php +167 -0
- includes/base/admin/backup/class-submenu-page-backup.php +45 -0
- includes/base/admin/backup/functions-actions-backup.php +148 -0
- includes/base/admin/backup/functions.php +50 -0
- includes/base/admin/backup/views/view-backup.php +78 -0
- includes/base/admin/calendar/class-calendar-editor-outputter.php +454 -0
- includes/base/admin/calendar/class-list-table-calendars.php +294 -0
- includes/base/admin/calendar/class-submenu-page-calendar.php +130 -0
- includes/base/admin/calendar/functions-actions-ajax-calendar.php +241 -0
- includes/base/admin/calendar/functions-actions-calendar.php +299 -0
- includes/base/admin/calendar/functions-actions-legend-item.php +396 -0
- includes/base/admin/calendar/functions-shortcode-generator.php +69 -0
- includes/base/admin/calendar/functions.php +105 -0
- includes/base/admin/calendar/views/view-add-calendar.php +51 -0
- includes/base/admin/calendar/views/view-calendars.php +34 -0
- includes/base/admin/calendar/views/view-edit-calendar.php +219 -0
- includes/base/admin/calendar/views/view-shortcode-generator.php +167 -0
- includes/base/admin/class-admin-notices.php +154 -0
- includes/base/admin/functions.php +76 -0
- includes/base/admin/settings/class-submenu-page-settings.php +90 -0
- includes/base/admin/settings/functions.php +46 -0
- includes/base/admin/settings/views/view-settings-tab-languages.php +43 -0
- includes/base/admin/settings/views/view-settings.php +87 -0
- includes/base/admin/upgrade-to-premium.php +93 -0
- includes/base/calendar/class-calendar-outputter.php +820 -0
- includes/base/calendar/class-calendar.php +67 -0
- includes/base/calendar/class-object-db-calendars.php +157 -0
- includes/base/calendar/class-object-meta-db-calendars.php +85 -0
- includes/base/calendar/functions-ajax.php +41 -0
- includes/base/calendar/functions.php +290 -0
- includes/base/class-shortcodes.php +94 -0
- includes/base/class-widget-calendar.php +349 -0
- includes/base/event/class-event.php +85 -0
- includes/base/event/class-object-db-events.php +193 -0
- includes/base/event/class-object-meta-db-events.php +85 -0
- includes/base/event/functions.php +189 -0
- includes/base/functions-languages.php +231 -0
- includes/base/functions-utils.php +72 -0
- includes/base/functions.php +83 -0
- includes/base/legend/class-legend-item.php +106 -0
- includes/base/legend/class-object-db-legend-items.php +156 -0
- includes/base/legend/class-object-meta-db-legend-items.php +85 -0
- includes/base/legend/functions.php +387 -0
- includes/libs/iCal/iCalcreator.php +67 -0
- includes/libs/iCal/lib/calendarComponent.class.php +4661 -0
- includes/libs/iCal/lib/iCal.XML.inc.php +897 -0
- includes/libs/iCal/lib/iCal.tz.inc.php +292 -0
- includes/libs/iCal/lib/iCal.vCard.inc.php +166 -0
- includes/libs/iCal/lib/iCalBase.class.php +427 -0
- includes/libs/iCal/lib/iCalUtilityFunctions.class.php +2510 -0
- includes/libs/iCal/lib/iCaldateTime.class.php +129 -0
- includes/libs/iCal/lib/valarm.class.php +135 -0
- includes/libs/iCal/lib/vcalendar.class.php +2132 -0
- includes/libs/iCal/lib/vevent.class.php +269 -0
- includes/libs/iCal/lib/vfreebusy.class.php +149 -0
- includes/libs/iCal/lib/vjournal.class.php +222 -0
- includes/libs/iCal/lib/vtimezone.class.php +165 -0
- includes/libs/iCal/lib/vtodo.class.php +207 -0
assets/css/images/ui-bg_flat_75_ffffff_40x100.png
ADDED
Binary file
|
assets/css/images/ui-icons_222222_256x240.png
ADDED
Binary file
|
assets/css/jquery-ui.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{position:absolute;left:-99999999px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}.ui-helper-clearfix{display:inline-block}* html .ui-helper-clearfix{height:1%}.ui-helper-clearfix{display:block}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget button,.ui-widget input,.ui-widget select,.ui-widget textarea{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:700}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:400;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-focus,.ui-state-hover,.ui-widget-content .ui-state-focus,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-focus,.ui-widget-header .ui-state-hover{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.ui-state-hover a,.ui-state-hover a:hover{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-widget :active{outline:0}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:700}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:400}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-focus .ui-icon,.ui-state-hover .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-off{background-position:-96px -144px}.ui-icon-radio-on{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px}.ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-corner-top{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px}.ui-corner-bottom{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-corner-right{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.ui-corner-left{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.ui-corner-all{-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;z-index:99999;display:block}.ui-resizable-autohide .ui-resizable-handle,.ui-resizable-disabled .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{border:1px dotted #000}.ui-accordion .ui-accordion-header{cursor:pointer;position:relative;margin-top:1px;zoom:1}.ui-accordion .ui-accordion-li-fix{display:inline}.ui-accordion .ui-accordion-header-active{border-bottom:0!important}.ui-accordion .ui-accordion-header a{display:block;font-size:1em;padding:.5em .5em .5em .7em}.ui-accordion a{zoom:1}.ui-accordion-icons .ui-accordion-header a{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;margin-top:-2px;position:relative;top:1px;margin-bottom:2px;overflow:auto;display:none;zoom:1}.ui-accordion .ui-accordion-content-active{display:block}.ui-autocomplete{position:absolute;cursor:default}.ui-autocomplete-loading{background:#fff url(images/ui-anim_basic_16x16.gif) right center no-repeat}* html .ui-autocomplete{width:1px}.ui-menu{list-style:none;padding:2px;margin:0;display:block}.ui-menu .ui-menu{margin-top:-3px}.ui-menu .ui-menu-item{margin:0;padding:0;zoom:1;float:left;clear:left;width:100%}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:.2em .4em;line-height:1.5;zoom:1}.ui-menu .ui-menu-item a.ui-state-active,.ui-menu .ui-menu-item a.ui-state-hover{font-weight:400;margin:-1px}.ui-button{display:inline-block;position:relative;padding:0;margin-right:.1em;text-decoration:none!important;cursor:pointer;text-align:center;zoom:1;overflow:visible}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:1.4}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-icons-only .ui-icon,.ui-button-text-icon .ui-icon,.ui-button-text-icons .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-icons-only .ui-button-icon-primary,.ui-button-text-icon .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary{left:.5em}.ui-button-icons-only .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-dialog{position:absolute;padding:.2em;width:300px;overflow:hidden}.ui-dialog .ui-dialog-titlebar{padding:.5em 1em .3em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 16px .2em 0}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:19px;margin:-10px 0 0 0;padding:1px;height:18px}.ui-dialog .ui-dialog-titlebar-close span{display:block;margin:1px}.ui-dialog .ui-dialog-titlebar-close:focus,.ui-dialog .ui-dialog-titlebar-close:hover{padding:0}.ui-dialog .ui-dialog-content{border:0;padding:.5em 1em;background:0 0;overflow:auto;zoom:1}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin:.5em 0 0 0;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane button{float:right;margin:.5em .4em .5em 0;cursor:pointer;padding:.2em .6em .3em .6em;line-height:1.4em;width:auto;overflow:visible}.ui-dialog .ui-resizable-se{width:14px;height:14px;right:3px;bottom:3px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-tabs{position:relative;padding:.2em;zoom:1}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:1px;margin:0 .2em 1px 0;border-bottom:0!important;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-selected{margin-bottom:0;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-state-processing a,.ui-tabs .ui-tabs-nav li.ui-tabs-selected a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0 0}.ui-tabs .ui-tabs-hide{display:none!important}.ui-datepicker{width:17em;padding:.2em .2em 0}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-next,.ui-datepicker .ui-datepicker-prev{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-next-hover,.ui-datepicker .ui-datepicker-prev-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-next span,.ui-datepicker .ui-datepicker-prev span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td a,.ui-datepicker td span{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker-cover{display:none;display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}.ui-progressbar{height:2em;text-align:left}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}
|
assets/css/style-admin.css
ADDED
@@ -0,0 +1,611 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/******************************************************************************************/
|
2 |
+
/* General
|
3 |
+
/******************************************************************************************/
|
4 |
+
a.wpsbc-inactive { color: #b1b1b1; }
|
5 |
+
a.wpsbc-inactive:hover { color: #b1b1b1; }
|
6 |
+
|
7 |
+
.wpsbc-float-right { float: right; }
|
8 |
+
|
9 |
+
.wpsbc-clear {display:block; clear:both;}
|
10 |
+
|
11 |
+
.button-primary.wpsbc-button-large { height: 38px; line-height: 36px; padding: 0 30px; }
|
12 |
+
|
13 |
+
.postbox .wpsbc-plugin-card-bottom { padding-left: 12px; padding-right: 12px; overflow: visible; }
|
14 |
+
|
15 |
+
.wrap.wpsbc-wrap .postbox .hndle { cursor: auto; }
|
16 |
+
|
17 |
+
/******************************************************************************************/
|
18 |
+
/* Grid
|
19 |
+
/******************************************************************************************/
|
20 |
+
.wpsbc-row { margin-left: -10px; margin-right: -10px; }
|
21 |
+
.wpsbc-row:after { content: ''; display: block; clear: both; }
|
22 |
+
.wpsbc-row.wpsbc-last { margin-bottom: -20px; }
|
23 |
+
|
24 |
+
[class*="wpsbc-col-"] { display: block; float: left; padding: 0 10px; margin-bottom: 20px; box-sizing: border-box; }
|
25 |
+
|
26 |
+
.wpsbc-col-1-1 { width: 100%; }
|
27 |
+
.wpsbc-col-1-2 { width: 50%; }
|
28 |
+
.wpsbc-col-1-3 { width: 33.3333%; }
|
29 |
+
.wpsbc-col-1-4 { width: 25%; }
|
30 |
+
.wpsbc-col-3-4 { width: 75%; }
|
31 |
+
.wpsbc-col-1-5 { width: 20%; }
|
32 |
+
|
33 |
+
|
34 |
+
/******************************************************************************************/
|
35 |
+
/* Error notices
|
36 |
+
/******************************************************************************************/
|
37 |
+
.wpsbc-notice-error { background: #fff; border-left: 4px solid #dc3232; box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); margin: 5px 0 15px 0; padding: 1px 12px; }
|
38 |
+
|
39 |
+
/******************************************************************************************/
|
40 |
+
/* Page Headings
|
41 |
+
/******************************************************************************************/
|
42 |
+
.wpsbc-heading-button-secondary.button-secondary { position: relative; top: -3px; vertical-align: initial; }
|
43 |
+
|
44 |
+
.wpsbc-heading-actions { display: block; float: right; margin-top: 9px; }
|
45 |
+
|
46 |
+
.wp-header-end {clear: both;}
|
47 |
+
|
48 |
+
.wpsbc-heading-tag { position: relative; top: -2px; font-size: 11px; margin-left: 15px; background: #34495e; color: #fff; padding: 6px 11px; border-radius: 4px; vertical-align: middle; }
|
49 |
+
|
50 |
+
/******************************************************************************************/
|
51 |
+
/* Tab Navigation
|
52 |
+
/******************************************************************************************/
|
53 |
+
.wpsbc-nav-tab:focus { outline: 0; box-shadow: none; }
|
54 |
+
|
55 |
+
.wpsbc-tab { display: none; margin-top: 2em; margin-bottom: 2em; }
|
56 |
+
.wpsbc-tab.wpsbc-active { display: block; }
|
57 |
+
|
58 |
+
/******************************************************************************************/
|
59 |
+
/* Settings Fields
|
60 |
+
/******************************************************************************************/
|
61 |
+
.wpsbc-settings-field-wrapper { position: relative; margin-bottom: 15px; }
|
62 |
+
.wpsbc-settings-field-wrapper.wpsbc-settings-field-inline { padding-left: 200px; }
|
63 |
+
|
64 |
+
.wpsbc-settings-field-wrapper.wpsbc-settings-field-wrapper-left {width:49%; float:left; margin-right:2%;}
|
65 |
+
.wpsbc-settings-field-wrapper.wpsbc-settings-field-wrapper-right {width:49%; float:right;}
|
66 |
+
|
67 |
+
.wpsbc-settings-field-wrapper.wpsbc-last { margin-bottom: 0; }
|
68 |
+
|
69 |
+
.wpsbc-settings-field-wrapper .wpsbc-settings-field-label { display: block; margin-bottom: 5px; }
|
70 |
+
.wpsbc-settings-field-wrapper.wpsbc-settings-field-inline .wpsbc-settings-field-label { position: absolute; top: 5px; left: 0; width: 180px; margin-bottom: 0; }
|
71 |
+
|
72 |
+
.wpsbc-settings-field-inner > input,
|
73 |
+
.wpsbc-settings-field-inner > textarea,
|
74 |
+
.wpsbc-settings-field-inner > select { width: 100%; margin-left: 0; height: 30px; }
|
75 |
+
|
76 |
+
.wpsbc-settings-field-small .wpsbc-settings-field-inner > input,
|
77 |
+
.wpsbc-settings-field-small .wpsbc-settings-field-inner > textarea,
|
78 |
+
.wpsbc-settings-field-small .wpsbc-settings-field-inner > select { max-width: 110px; }
|
79 |
+
|
80 |
+
.wpsbc-settings-field-medium .wpsbc-settings-field-inner > input,
|
81 |
+
.wpsbc-settings-field-medium .wpsbc-settings-field-inner > textarea,
|
82 |
+
.wpsbc-settings-field-medium .wpsbc-settings-field-inner > select { max-width: 225px; }
|
83 |
+
|
84 |
+
.wpsbc-settings-field-large .wpsbc-settings-field-inner > input,
|
85 |
+
.wpsbc-settings-field-large .wpsbc-settings-field-inner > textarea,
|
86 |
+
.wpsbc-settings-field-large .wpsbc-settings-field-inner > select { max-width: 400px; }
|
87 |
+
|
88 |
+
.wpsbc-settings-field-translations {display: none; padding-bottom:20px;}
|
89 |
+
.wpsbc-settings-field-translations .wpsbc-settings-field-wrapper.wpsbc-settings-field-inline.wpsbc-settings-field-large {margin-left:200px; padding-left:100px; }
|
90 |
+
.wpsbc-settings-field-translations .wpsbc-settings-field-wrapper.wpsbc-settings-field-inline.wpsbc-settings-field-large-label {margin-left:300px; }
|
91 |
+
.wpsbc-settings-field-translations .wpsbc-settings-field-wrapper.wpsbc-settings-field-inline.wpsbc-settings-field-large .wpsbc-settings-field-label {width:80px;}
|
92 |
+
|
93 |
+
.wpsbc-settings-field-show-translations {text-decoration:none; margin-top: 3px; display: block; max-width:400px;}
|
94 |
+
.wpsbc-settings-field-show-translations:focus {outline:none; box-shadow:none;}
|
95 |
+
.wpsbc-settings-field-show-translations span {position: relative; top:-1px; left:-7px;}
|
96 |
+
.wpsbc-settings-field-show-translations.open span {transform:rotate(180deg); left:-5px; top:0; }
|
97 |
+
|
98 |
+
/* Chosen */
|
99 |
+
.wpsbc-chosen-wrapper .chosen-container { width: 100% !important; }
|
100 |
+
.wpsbc-chosen-wrapper .chosen-container .chosen-choices { box-shadow: inset 0 1px 2px rgba(0,0,0,.07); background-image: none; border-color: #ddd; min-height: 32px; padding: 0 3px; }
|
101 |
+
.wpsbc-chosen-wrapper .chosen-container .chosen-choices .search-choice { box-shadow: none; background: #34495e; color: #fff; border: 0; padding: 5px 24px 6px 8px; border-radius: 2px; }
|
102 |
+
.wpsbc-chosen-wrapper .chosen-container .chosen-choices li.search-field input[type="text"] { height: 28px; padding-left: 3px; }
|
103 |
+
.wpsbc-chosen-wrapper .chosen-container .chosen-choices li.search-choice .search-choice-close { top: 7px; right: 6px; opacity: 0.7; transition: opacity 0.2s ease-in-out; }
|
104 |
+
.wpsbc-chosen-wrapper .chosen-container .chosen-choices li.search-choice .search-choice-close:hover { background-position: -42px 1px; opacity: 1; }
|
105 |
+
|
106 |
+
.wpsbc-chosen-wrapper .chosen-container.chosen-with-drop .chosen-drop { border: 0; }
|
107 |
+
.wpsbc-chosen-wrapper .chosen-container.chosen-with-drop .chosen-drop .chosen-results li { padding: 8px 10px; }
|
108 |
+
.wpsbc-chosen-wrapper .chosen-container.chosen-with-drop .chosen-drop .chosen-results li.highlighted { background: #34495e; }
|
109 |
+
|
110 |
+
|
111 |
+
|
112 |
+
/******************************************************************************************/
|
113 |
+
/* Legend Item Icon
|
114 |
+
/******************************************************************************************/
|
115 |
+
.wpsbc-legend-item-icon { position: relative; display: inline-block; width: 24px; height: 24px; border-radius: 2px; vertical-align: middle; box-sizing: border-box; overflow: hidden; }
|
116 |
+
|
117 |
+
.wpsbc-legend-item-icon[data-type="single"] div { display: none; }
|
118 |
+
.wpsbc-legend-item-icon[data-type="single"] svg { display:none; }
|
119 |
+
.wpsbc-legend-item-icon[data-type="single"] div:first-of-type { position: absolute; top: 0; left: 0; display: block; width: 100%; height: 100%; }
|
120 |
+
|
121 |
+
.wpsbc-legend-item-icon[data-type="split"] div:first-of-type { position: absolute; top: -115%; left: -115%; width: 200%; height: 200%; transform: rotate(45deg); }
|
122 |
+
.wpsbc-legend-item-icon[data-type="split"] div:nth-of-type(2) { position: absolute; top: 20.75%; left: 20.75%; width: 200%; height: 200%; transform: rotate(45deg); }
|
123 |
+
|
124 |
+
/******************************************************************************************/
|
125 |
+
/* Admin Fields General
|
126 |
+
/******************************************************************************************/
|
127 |
+
.wpsbc-admin-field-wrapper { margin-bottom: 15px; }
|
128 |
+
.wpsbc-admin-field-wrapper label { font-weight: bold; }
|
129 |
+
|
130 |
+
.wpsbc-admin-field-wrapper.wpsbc-field-inline { position: relative; padding-left: 150px; }
|
131 |
+
.wpsbc-admin-field-wrapper.wpsbc-field-inline > label { position: absolute; top: 4px; left: 0; }
|
132 |
+
|
133 |
+
.wpsbc-admin-field-wrapper input.wpsbc-medium,
|
134 |
+
.wpsbc-admin-field-wrapper select.wpsbc-medium { min-width: 300px; }
|
135 |
+
|
136 |
+
/* Color picker */
|
137 |
+
.wpsbc-admin-field-wrapper .wp-picker-container { position: relative; display: inline-block; }
|
138 |
+
.wpsbc-admin-field-wrapper .wp-picker-container button { width: 145px; }
|
139 |
+
.wpsbc-admin-field-wrapper .wp-picker-container .wp-picker-input-wrap { position: absolute; z-index: 1; top: 27px; left: 0; width: 100%; padding: 5px 0; background: #fff; }
|
140 |
+
.wpsbc-admin-field-wrapper .wp-picker-container .wp-picker-input-wrap input[type="text"] { width: 93px; font-weight: normal; }
|
141 |
+
.wpsbc-admin-field-wrapper .wp-picker-container .wp-picker-holder { position: absolute; z-index: 1; top: 55px; left: 0; }
|
142 |
+
|
143 |
+
|
144 |
+
/******************************************************************************************/
|
145 |
+
/* Tooltips
|
146 |
+
/******************************************************************************************/
|
147 |
+
.wpsbc-tooltip-wrapper { position: relative; margin-left: 2px; top:1px; }
|
148 |
+
|
149 |
+
.wpsbc-tooltip-wrapper .wpsbc-tooltip-icon { display: inline-block; width: 16px; height: 16px; line-height: 16px; text-align: center; font-size: 10px; vertical-align: text-top; cursor: pointer; background: #6B8CAD; color: #fff; border-radius: 10px; }
|
150 |
+
|
151 |
+
.wpsbc-tooltip-wrapper .wpsbc-tooltip-message { opacity: 0; visibility: hidden; position: absolute; z-index: 9999; top: 45px; left: 50%; width: 220px; margin-left: -110px; background: #6B8CAD; padding: 10px; line-height: 18px; font-size: 12px; border-radius: 3px; font-weight: normal; color: #fff; box-shadow: 0 2px 5px rgba( 0, 0, 0, 0.1 ), 0 0 56px rgba( 0, 0, 0, 0.075 ); box-sizing: border-box; transition: all 0.2s ease-in-out; }
|
152 |
+
.wpsbc-tooltip-wrapper:hover .wpsbc-tooltip-message { opacity: 1; visibility: visible; top: 28px; }
|
153 |
+
|
154 |
+
.wpsbc-tooltip-wrapper .wpsbc-tooltip-arrow { position: absolute; z-index: 1; top: -7px; left: 50%; margin-left: -10px; width: 0; height: 0; line-height: 0; border: 10px solid #6B8CAD; border-left-style: solid; border-top: none; border-left-color: transparent; border-right-color: transparent; }
|
155 |
+
|
156 |
+
.wpsbc-tooltip-wrapper a { color: #fff; }
|
157 |
+
.wpsbc-tooltip-wrapper hr { border: 0; border-bottom: 1px solid #e1e1e1; margin: 12px 0; }
|
158 |
+
|
159 |
+
/******************************************************************************************/
|
160 |
+
/* List Table General
|
161 |
+
/******************************************************************************************/
|
162 |
+
.wpsbc-list-table-no-items { text-align: center; padding: 35px; }
|
163 |
+
|
164 |
+
.wpsbc-list-table-icon.wpsbc-list-table-icon-star.wpsbc-list-table-icon-active .dashicons { color: #f0932b; }
|
165 |
+
.wpsbc-list-table-icon.wpsbc-list-table-icon-star.wpsbc-list-table-icon-inactive .dashicons { color: #95afc0; opacity: 0.55; }
|
166 |
+
.wpsbc-list-table-icon.wpsbc-list-table-icon-star.wpsbc-list-table-icon-inactive:hover .dashicons { color: #f0932b; }
|
167 |
+
|
168 |
+
.wpsbc-list-table-icon.wpsbc-list-table-icon-yes .dashicons { position: relative; top: 1px; border-radius: 50%; color: #fff; width: 18px; height: 18px; line-height: 18px; font-size: 16px; text-align: center; text-indent: -2px; }
|
169 |
+
.wpsbc-list-table-icon.wpsbc-list-table-icon-yes.wpsbc-list-table-icon-active .dashicons { background: #27ae60; }
|
170 |
+
.wpsbc-list-table-icon.wpsbc-list-table-icon-yes.wpsbc-list-table-icon-inactive .dashicons { background: #95afc0; color: #95afc0; opacity: 0.55; }
|
171 |
+
.wpsbc-list-table-icon.wpsbc-list-table-icon-yes.wpsbc-list-table-icon-inactive:hover .dashicons { background: #27ae60; color: #fff; }
|
172 |
+
|
173 |
+
/******************************************************************************************/
|
174 |
+
/* Calendars List Table
|
175 |
+
/******************************************************************************************/
|
176 |
+
.wp-list-table.wpsbc_calendars .column-id { width: 55px; }
|
177 |
+
.wp-list-table.wpsbc_calendars .column-name { width: 50%; }
|
178 |
+
@media screen and (max-width: 782px) {
|
179 |
+
.wpsbc-wrap-calendars p.search-box {bottom:-40px}
|
180 |
+
}
|
181 |
+
|
182 |
+
/******************************************************************************************/
|
183 |
+
/* Legend Items List Table
|
184 |
+
/******************************************************************************************/
|
185 |
+
.wrap.wpsbc-wrap-legend-items .tablenav.top { display: none; }
|
186 |
+
|
187 |
+
.wpsbc-wp-list-table-wrapper { position: relative; }
|
188 |
+
|
189 |
+
.wp-list-table.wpsbc_legend_items { margin-top: 10px; }
|
190 |
+
.wp-list-table.wpsbc_legend_items .column-sort { width: 40px; text-align: center; }
|
191 |
+
.wp-list-table.wpsbc_legend_items .column-color { width: 40px; text-align: center; }
|
192 |
+
.wp-list-table.wpsbc_legend_items td { vertical-align: middle; }
|
193 |
+
|
194 |
+
.wp-list-table.wpsbc_legend_items .wpsbc-legend-item-icon { margin-top: 5px; }
|
195 |
+
|
196 |
+
.wpsbc-move-legend-item { position: relative; display: block; width: 40px; height: 40px; cursor: move; }
|
197 |
+
.wpsbc-move-legend-item .wpsbc-inner,
|
198 |
+
.wpsbc-move-legend-item .wpsbc-inner:before,
|
199 |
+
.wpsbc-move-legend-item .wpsbc-inner:after { content: ''; display: block; position: absolute; left: 50%; margin-left: -12px; width: 24px; height: 1px; background: #c1c1c1; }
|
200 |
+
.wpsbc-move-legend-item .wpsbc-inner { top: 50%; }
|
201 |
+
.wpsbc-move-legend-item .wpsbc-inner:before { top: -6px; }
|
202 |
+
.wpsbc-move-legend-item .wpsbc-inner:after { top: 6px; }
|
203 |
+
|
204 |
+
.wp-list-table.wpsbc_legend_items .ui-sortable-helper { background: #fff; box-shadow: 0 5px 10px 2px #f1f1f1; }
|
205 |
+
.wp-list-table.wpsbc_legend_items .wpsbc-list-table-sort-placeholder { display: table-row; width: 100%; height: 60px; box-sizing: border-box; box-shadow: inset 0 0 10px #d9d9d9; background: #f9f9f9 !important; }
|
206 |
+
|
207 |
+
.wpsbc-overlay { position: absolute; z-index: 3; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255,255,255,0.65); }
|
208 |
+
.wpsbc-overlay .spinner { float: none; position: absolute; top: 50%; left: 50%; margin: -10px 0 0 -10px; visibility: visible; }
|
209 |
+
|
210 |
+
/******************************************************************************************/
|
211 |
+
/* Add New Calendar Page
|
212 |
+
/******************************************************************************************/
|
213 |
+
|
214 |
+
/* Admin notices */
|
215 |
+
.wrap.wpsbc-wrap-add-calendar div.notice { max-width: 500px; margin-left: auto; margin-right: auto; box-sizing: border-box; }
|
216 |
+
|
217 |
+
/* Icon */
|
218 |
+
#wpsbc-add-new-calendar-icon { text-align: center; }
|
219 |
+
#wpsbc-add-new-calendar-icon .wpsbc-icon-wrap { position: relative; background: #e6e6e6; width: 70px; height: 70px; border-radius: 50%; margin: 50px auto 10px; }
|
220 |
+
|
221 |
+
#wpsbc-add-new-calendar-icon .wpsbc-icon-wrap .dashicons-calendar-alt { font-size: 38px; vertical-align: middle; text-align: center; width: 70px; height: 70px; line-height: 68px; }
|
222 |
+
#wpsbc-add-new-calendar-icon .wpsbc-icon-wrap .dashicons-plus { position: absolute; top: -10px; right: -10px; background: #c1c1c1; border-radius: 50%; width: 30px; height: 30px; text-align: center; line-height: 32px; vertical-align: middle; }
|
223 |
+
|
224 |
+
/* Heading */
|
225 |
+
#wpsbc-add-new-calendar-heading { text-align: center; margin-bottom: 35px; }
|
226 |
+
|
227 |
+
/* Postbox */
|
228 |
+
#wpsbc-add-new-calendar-postbox { max-width: 500px; margin: 0 auto; }
|
229 |
+
#wpsbc-add-new-calendar-postbox .inside { padding: 30px 20px; margin: 0; }
|
230 |
+
|
231 |
+
#wpsbc-add-new-calendar-postbox h1 { text-align: center; margin-bottom: 35px; }
|
232 |
+
|
233 |
+
#wpsbc-add-new-calendar-postbox label { display: block; font-weight: bold; margin-bottom: 5px; }
|
234 |
+
#wpsbc-add-new-calendar-postbox input[type="text"],
|
235 |
+
#wpsbc-add-new-calendar-postbox select { width: 100%; height: 32px; }
|
236 |
+
|
237 |
+
#wpsbc-add-new-calendar-postbox label[for="wpsbc-new-calendar-legend"] { margin-top: 25px; }
|
238 |
+
#wpsbc-add-new-calendar-postbox select { margin-bottom: 5px; }
|
239 |
+
|
240 |
+
#wpsbc-add-new-calendar-postbox input[type=submit] { display: inline-block; margin: 0 auto; }
|
241 |
+
|
242 |
+
#wpsbc-add-new-calendar-postbox #major-publishing-actions { padding: 20px; text-align: right; }
|
243 |
+
#wpsbc-add-new-calendar-postbox #major-publishing-actions:after { content: ''; display: block; clear: both; }
|
244 |
+
#wpsbc-add-new-calendar-postbox #major-publishing-actions a { float: left; color: #777; line-height: 36px; outline: 0; box-shadow: none; }
|
245 |
+
#wpsbc-add-new-calendar-postbox #major-publishing-actions a:hover { color: #444; }
|
246 |
+
|
247 |
+
/******************************************************************************************/
|
248 |
+
/* Edit Calendar Page
|
249 |
+
/******************************************************************************************/
|
250 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv { margin-bottom: 20px; }
|
251 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv #titlewrap:after {content:""; display:block; clear:both;}
|
252 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-toggle {float:right;}
|
253 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-toggle svg {width:8px; margin-left:1px;}
|
254 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-toggle.open svg {transform:rotate(180deg);}
|
255 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-translations {display:none; clear:both; width:100%; float:right; padding-top: 10px;}
|
256 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-translations input {padding: 3px 8px 3px 34px; font-size: 1.7em; line-height: 100%; height: 1.7em; width: 100%; outline: 0; margin: 0 0 3px; background-color: #fff;}
|
257 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-translation {position:relative;}
|
258 |
+
.wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-translation-flag img {position:absolute; left: 10px; top: 14px;}
|
259 |
+
|
260 |
+
|
261 |
+
|
262 |
+
.wrap.wpsbc-wrap-edit-calendar #post-body-content { float: right; margin-right: 0; }
|
263 |
+
.wrap.wpsbc-wrap-edit-calendar #poststuff #post-body.columns-2 { margin-left: 255px; margin-right: 0; }
|
264 |
+
.wrap.wpsbc-wrap-edit-calendar #post-body.columns-2 #postbox-container-1 { float: left; width: 235px; margin-left: -255px; margin-right: 0; }
|
265 |
+
.wrap.wpsbc-wrap-edit-calendar #post-body.columns-2 #postbox-container-1 .postbox { min-width: 225px; }
|
266 |
+
.wrap.wpsbc-wrap-edit-calendar #poststuff .postbox .inside { margin-top: 12px; }
|
267 |
+
.wrap.wpsbc-wrap-edit-calendar #poststuff:after { content: ''; display: block; clear: both; }
|
268 |
+
|
269 |
+
/* Calendar */
|
270 |
+
.wrap.wpsbc-wrap-edit-calendar .wpsbc-container .wpsbc-calendars .wpsbc-calendar { border: 0; margin-top: 10px; margin-bottom: 0; }
|
271 |
+
.wrap.wpsbc-wrap-edit-calendar .wpsbc-container .wpsbc-calendars .wpsbc-calendar-wrapper { padding: 10px 0 0 0; }
|
272 |
+
.wrap.wpsbc-wrap-edit-calendar .wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header { padding: 0 0 10px; background: transparent; border-bottom: 1px solid #f1f1f1; }
|
273 |
+
|
274 |
+
/* Legend */
|
275 |
+
.wpsbc-legend-item { margin-bottom: 10px; }
|
276 |
+
.wpsbc-legend-item .wpsbc-legend-item-icon { margin-right: 5px; }
|
277 |
+
.wpsbc-legend-item .wpsbc-legend-item-name { display: inline-block; vertical-align: middle; }
|
278 |
+
|
279 |
+
/* Calendar Editor */
|
280 |
+
#wpsbc-calendar-events { position: relative; }
|
281 |
+
|
282 |
+
#wpsbc-calendar-editor .wpsbc-calendar-date { padding: 3px 0; }
|
283 |
+
|
284 |
+
.wpsbc-calendar-date-legend-item,
|
285 |
+
.wpsbc-calendar-date-legend-item-header { position: relative; display: inline-block; width: 180px; padding-left: 35px; margin-right: 7px; box-sizing: border-box; }
|
286 |
+
.wpsbc-calendar-date-legend-item-header { padding-left: 0; }
|
287 |
+
.wpsbc-calendar-date-legend-item select { width: 100%; height: 30px; margin: 0; }
|
288 |
+
.wpsbc-calendar-date-legend-item .wpsbc-legend-item-icon-wrapper,
|
289 |
+
.wpsbc-calendar-date-legend-item .wpsbc-legend-item-icon { position: absolute; top: 0; left: 0; width: 30px; height: 30px; }
|
290 |
+
.wpsbc-calendar-date-legend-item .wpsbc-date-inner { position: relative; z-index: 2; line-height: 30px; width: 100%; text-align: center; }
|
291 |
+
|
292 |
+
.wpsbc-calendar-date-description-ical { position: relative; display: inline-block; width: calc( 100% - 200px ); margin-right:7px; }
|
293 |
+
.wpsbc-calendar-date-description,
|
294 |
+
.wpsbc-calendar-date-tooltip,
|
295 |
+
.wpsbc-calendar-date-description-header,
|
296 |
+
.wpsbc-calendar-date-tooltip-header { position: relative; display: inline-block; width: calc( 100% - 200px ); }
|
297 |
+
.wpsbc-calendar-date-description-ical .dashicons,
|
298 |
+
.wpsbc-calendar-date-description .dashicons,
|
299 |
+
.wpsbc-calendar-date-tooltip .dashicons { position: absolute; left: 5px; top: 5px; color: #d6d6d6; }
|
300 |
+
.wpsbc-calendar-date-description-ical input,
|
301 |
+
.wpsbc-calendar-date-description input,
|
302 |
+
.wpsbc-calendar-date-tooltip input { width: 100%; height: 30px; margin: 0; vertical-align: middle; padding-left: 30px; }
|
303 |
+
|
304 |
+
.wpsbc-calendar-date-description,
|
305 |
+
.wpsbc-calendar-date-description-header { margin-right: 7px; }
|
306 |
+
|
307 |
+
.wpsbc-calendar-date-legend-item-header,
|
308 |
+
.wpsbc-calendar-date-description-header,
|
309 |
+
.wpsbc-calendar-date-tooltip-header { margin-bottom: 7px; font-weight: bold; }
|
310 |
+
|
311 |
+
.wpsbc-save-calendar-spinner { float: none; margin-top: 0; }
|
312 |
+
|
313 |
+
|
314 |
+
/* Export CSV */
|
315 |
+
.wrap.wpsbc-wrap-edit-calendar .postbox .button-secondary .dashicons {position: relative; top:2px; left:-2px;}
|
316 |
+
|
317 |
+
.wp-admin .ui-datepicker.wpsbc-datepicker { border: 1px solid #ccc; -webkit-box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4); box-shadow: 0 3px 6px rgba(0, 0, 0, 0.4); }
|
318 |
+
|
319 |
+
|
320 |
+
/******************************************************************************************/
|
321 |
+
/* iCalendar Import/Export Page
|
322 |
+
/******************************************************************************************/
|
323 |
+
.wpsbc-wrap #dashboard-widgets-wrap { overflow: visible; }
|
324 |
+
|
325 |
+
.wpsbc-wrap .wpsbc-settings-field-inner .wpsbc-warning {padding-top:6px; font-weight: bold; display:none;}
|
326 |
+
.wpsbc-wrap .wpsbc-settings-field-inner .wpsbc-warning span.dashicons {color: #ffba00;}
|
327 |
+
|
328 |
+
#wpsbc-settings-field-ical-import,
|
329 |
+
#wpsbc-settings-field-ical-export { font-size: 12px; height: 32px; }
|
330 |
+
|
331 |
+
#wpsbc-ical-url-import .wpsbc-settings-field-conditional {display: none;}
|
332 |
+
#ical_url_import_split_days {position:relative; top:2px;}
|
333 |
+
|
334 |
+
.wpsbc-ical-feed-calendar { position: relative; padding: 15px 80px 15px 40px; border-bottom: 1px solid #eee; box-sizing: border-box; }
|
335 |
+
.wpsbc-ical-feed-calendar:after { clear: both; display: block; }
|
336 |
+
|
337 |
+
.wpsbc-ical-feed-calendar p { margin-top: 5px; margin-bottom: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: #757575; }
|
338 |
+
.wpsbc-ical-feed-calendar small { color: #757575; }
|
339 |
+
|
340 |
+
.wpsbc-ical-feed-calendar .wpsbc-trash { position: absolute; right: 12px; top: 50%; margin-top: -10px; line-height: 20px; vertical-align: middle; color: #a00; }
|
341 |
+
.wpsbc-ical-feed-calendar .wpsbc-trash:hover { color: #dc3232; }
|
342 |
+
|
343 |
+
.wpsbc-ical-feed-calendar .wpsbc-legend-item-icon { position: absolute; left: 12px; top: 15px; width: 16px; height: 16px; }
|
344 |
+
|
345 |
+
|
346 |
+
/******************************************************************************************/
|
347 |
+
/* Modals
|
348 |
+
/******************************************************************************************/
|
349 |
+
.wpsbc-modal { display: none; position: fixed; z-index: 85462256; background-color: #fff; border: 1px solid rgba(0,0,0,.08); margin: 0 auto; max-height: 600px; max-width: 950px; top: 7.5%; bottom: 7.5%; left: calc(45% - 400px ); right: calc(45% - 400px ); box-shadow: 0 1px 3px 0 rgba(0,0,0,.2), 0 1px 1px 0 rgba(0,0,0,.14), 0 2px 1px -1px rgba(0,0,0,.12); overflow: hidden; }
|
350 |
+
.wpsbc-modal.wpsbc-active { display: block; }
|
351 |
+
|
352 |
+
.wpsbc-modal .wpsbc-modal-header { position: relative; padding: 20px 15px; box-shadow: 0 1px 3px 0 rgba(0,0,0,.2), 0 1px 1px 0 rgba(0,0,0,.14), 0 2px 1px -1px rgba(0,0,0,.12); }
|
353 |
+
.wpsbc-modal .wpsbc-modal-header h2 { margin: 0; font-size: 1.6em; font-weight: normal; }
|
354 |
+
.wpsbc-modal .wpsbc-modal-header h2 .dashicons { margin-right: 5px; }
|
355 |
+
.wpsbc-modal .wpsbc-modal-header .wpsbc-modal-close { position: absolute; right: 15px; top: 50%; margin-top: -15px; width: 30px; height: 30px; line-height: 30px; font-size: 30px; cursor: pointer; }
|
356 |
+
|
357 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper { list-style: none; background: rgba( 0, 0, 0, 0.08 ); padding: 0; margin: 0; }
|
358 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper:after { content: ''; display: block; clear: both; }
|
359 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper li { display: block; margin: 0; float: left; }
|
360 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper li a { position: relative; display: block; padding: 14px 16px; color: #444; text-decoration: none; font-weight: bold; outline: 0; box-shadow: none; }
|
361 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper li a:after { content: ''; display: block; position: absolute; bottom: 0; left: 50%; width: 0; height: 2px; background: #66b3ff; transition: all 0.2s ease-in-out; }
|
362 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper li a:hover:after { left: 0%; width: 100%; }
|
363 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper li.wpsbc-active a { background: rgba( 0, 0, 0, 0.15 ); }
|
364 |
+
.wpsbc-modal .wpsbc-modal-nav-tab-wrapper li.wpsbc-active a:after { left: 0%; width: 100%; }
|
365 |
+
|
366 |
+
.wpsbc-modal .wpsbc-modal-body .wpsbc-modal-inner { padding: 15px; overflow-y: scroll; }
|
367 |
+
|
368 |
+
.wpsbc-modal .wpsbc-modal-body .wpsbc-modal-tab { margin: 0; }
|
369 |
+
.wpsbc-modal .wpsbc-modal-body .wpsbc-modal-tab.wpsbc-active { padding-bottom: 5px; }
|
370 |
+
|
371 |
+
.wpsbc-modal-overlay { display: none; position: fixed; z-index: 85462255; top: 0; left: 0; width: 100%; height: 100%; background: rgba( 0, 0, 0, 0.5 ); }
|
372 |
+
.wpsbc-modal-overlay.wpsbc-active { display: block; }
|
373 |
+
|
374 |
+
.wpsbc-modal .wpsbc-tooltip-message { width: 240px; margin-left: -120px; }
|
375 |
+
|
376 |
+
.wpsbc-modal .wpsbc-modal-body .wpsbc-modal-tab .wpsbc-element-disabled { position: relative; }
|
377 |
+
.wpsbc-modal .wpsbc-modal-body .wpsbc-modal-tab .wpsbc-element-disabled:before { content: ''; position: absolute; z-index: 1; top: 0; right: 0; bottom: 0; left: 0; background: #fff; opacity: 0.6; }
|
378 |
+
|
379 |
+
|
380 |
+
/******************************************************************************************/
|
381 |
+
/* Shortcode Generator
|
382 |
+
/******************************************************************************************/
|
383 |
+
#wpsbc-shortcode-generator-button span { position: relative; top: -2px; display: inline-block; width: 18px; height: 18px; vertical-align: text-top; margin: 0 4px 0 0; font-size: 18px; }
|
384 |
+
|
385 |
+
#wpsbc-modal-add-calendar-shortcode .wpsbc-tab { display: block; height: 0; position: relative; top: 50px; visibility: hidden; opacity: 0; transition: all 0.2s ease-in-out; overflow: hidden; }
|
386 |
+
#wpsbc-modal-add-calendar-shortcode .wpsbc-tab.wpsbc-active { height: auto; top: 0; opacity: 1; visibility: visible; overflow: visible; }
|
387 |
+
|
388 |
+
#wpsbc-modal-add-calendar-shortcode h3 { margin-bottom: 0; }
|
389 |
+
#wpsbc-modal-add-calendar-shortcode h4 { font-size: 1.1em; margin-bottom: 0; }
|
390 |
+
#wpsbc-modal-add-calendar-shortcode hr { margin: 1.33em 0; }
|
391 |
+
#wpsbc-modal-add-calendar-shortcode p:first-of-type { margin-top: 0.5em; margin-bottom: 2.2em; }
|
392 |
+
#wpsbc-modal-add-calendar-shortcode label { display: block; margin-bottom: 5px; font-weight: bold; }
|
393 |
+
#wpsbc-modal-add-calendar-shortcode select { width: 100%; }
|
394 |
+
|
395 |
+
|
396 |
+
|
397 |
+
/******************************************************************************************/
|
398 |
+
/* Settings Page
|
399 |
+
/******************************************************************************************/
|
400 |
+
|
401 |
+
/* Languages Tab */
|
402 |
+
.wpsbc-tab.wpsbc-tab-languages .wpsbc-settings-field-inner > div { margin-bottom: 7px; }
|
403 |
+
.wpsbc-tab.wpsbc-tab-languages .wpsbc-settings-field-inner > div img { margin: 0 5px 0 5px; }
|
404 |
+
|
405 |
+
/* Register Website Tab */
|
406 |
+
#wpsbc-wpsbc-settings-field-register-website input { max-width: 300px; margin: 0; }
|
407 |
+
#wpsbc-wpsbc-settings-field-register-website .button-primary,
|
408 |
+
#wpsbc-wpsbc-settings-field-register-website .button-secondary { vertical-align: top; height: 29px; line-height: 27px; }
|
409 |
+
|
410 |
+
/* Uninstaller Tab */
|
411 |
+
#wpsbc-uninstaller-confirmation { display: none; }
|
412 |
+
|
413 |
+
.wpsbc-settings-field-inner.wpsbc-settings-field-inner-inline small {display: inline-block; position: relative; top: 3px; font-style:italic;}
|
414 |
+
|
415 |
+
|
416 |
+
/******************************************************************************************/
|
417 |
+
/* Upgrader Page
|
418 |
+
/******************************************************************************************/
|
419 |
+
#wpsbc-upgrader-content { max-width: 800px; margin: 0 auto; text-align: center; }
|
420 |
+
|
421 |
+
#wpsbc-upgrader-content-inner { min-height: 85px; }
|
422 |
+
|
423 |
+
#wpsbc-upgrader-content-inner :first-child { margin-top: 0; }
|
424 |
+
#wpsbc-upgrader-content-inner :last-child { margin-bottom: 0; }
|
425 |
+
|
426 |
+
#wpsbc-upgrader-button-wrapper { position: relative; display: inline-block; margin-top: 40px; padding: 0 30px; }
|
427 |
+
|
428 |
+
#wpsbc-upgrader-button-wrapper .spinner { position: absolute; margin: 0; right: 0; top: 10px; }
|
429 |
+
|
430 |
+
#wpsbc-upgrader-button-start-upgrade span { display: none; }
|
431 |
+
#wpsbc-upgrader-button-start-upgrade span:nth-of-type(1) { display: block; }
|
432 |
+
|
433 |
+
#wpsbc-upgrader-button-continue { display: none; }
|
434 |
+
|
435 |
+
#wpsbc-upgrader-loading-bar-wrapper { display: none; min-height: 85px; }
|
436 |
+
|
437 |
+
#wpsbc-upgrader-loading-bar { position: relative; top: 42px; background: #d5d5d5; height: 3px; width: 100%; }
|
438 |
+
#wpsbc-upgrader-loading-bar:after { content: ''; display: block; position: absolute; z-index: 1; top: 0; left: 0; width: 0%; height: 3px; background: #27ae60; transition: width 0.4s ease-in-out; }
|
439 |
+
|
440 |
+
.wpsbc-upgrader-loading-bar-step,
|
441 |
+
#wpsbc-upgrader-loading-bar .spinner { visibility: visible; opacity: 1; position: absolute; z-index: 2; top: -9px; margin-left: -10px; width: 20px; height: 20px; background-color: #d5d5d5; border-radius: 50%; }
|
442 |
+
|
443 |
+
#wpsbc-upgrader-loading-bar .spinner { background-color: #f1f1f1; margin: 0; margin-left: -10px; left: 0; }
|
444 |
+
|
445 |
+
#wpsbc-upgrader-loading-bar-step-1,
|
446 |
+
#wpsbc-upgrader-message-doing-step-1,
|
447 |
+
#wpsbc-upgrader-message-step-1 { left: 0; }
|
448 |
+
#wpsbc-upgrader-loading-bar-step-2,
|
449 |
+
#wpsbc-upgrader-message-doing-step-2,
|
450 |
+
#wpsbc-upgrader-message-step-2 { left: 33.3333%; }
|
451 |
+
#wpsbc-upgrader-loading-bar-step-3,
|
452 |
+
#wpsbc-upgrader-message-doing-step-3,
|
453 |
+
#wpsbc-upgrader-message-step-3 { left: 66.6666%; }
|
454 |
+
#wpsbc-upgrader-loading-bar-step-4,
|
455 |
+
#wpsbc-upgrader-message-doing-step-4,
|
456 |
+
#wpsbc-upgrader-message-step-4 { left: 100%; }
|
457 |
+
|
458 |
+
.wpsbc-upgrader-message-step,
|
459 |
+
.wpsbc-upgrader-message-doing-step { position: absolute; top: 20px; width: 250px; margin-left: -125px !important; text-align: center; }
|
460 |
+
|
461 |
+
.wpsbc-upgrader-message-step { opacity: 0.35; }
|
462 |
+
.wpsbc-upgrader-message-doing-step { display: none; }
|
463 |
+
|
464 |
+
/* Upgrader Step 1 */
|
465 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="1"] #wpsbc-upgrader-loading-bar .spinner { left: 0; }
|
466 |
+
|
467 |
+
/* Upgrader Step 2 */
|
468 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="2"] #wpsbc-upgrader-loading-bar .spinner { left: 33.3333%; }
|
469 |
+
|
470 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="2"] #wpsbc-upgrader-message-step-1 { opacity: 1; color: #27ae60; }
|
471 |
+
|
472 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="2"] #wpsbc-upgrader-loading-bar-step-1 { background-color: #27ae60; }
|
473 |
+
|
474 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="2"] #wpsbc-upgrader-loading-bar:after { width: 33.3333%; }
|
475 |
+
|
476 |
+
/* Upgrader Step 3 */
|
477 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="3"] #wpsbc-upgrader-loading-bar .spinner { left: 66.6666%; }
|
478 |
+
|
479 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="3"] #wpsbc-upgrader-message-step-1,
|
480 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="3"] #wpsbc-upgrader-message-step-2 { opacity: 1; color: #27ae60; }
|
481 |
+
|
482 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="3"] #wpsbc-upgrader-loading-bar-step-1,
|
483 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="3"] #wpsbc-upgrader-loading-bar-step-2 { background-color: #27ae60; }
|
484 |
+
|
485 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="3"] #wpsbc-upgrader-loading-bar:after { width: 66.6666%; }
|
486 |
+
|
487 |
+
/* Upgrader Step 4 */
|
488 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-loading-bar .spinner { left: 100%; }
|
489 |
+
|
490 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-message-step-1,
|
491 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-message-step-2,
|
492 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-message-step-3 { opacity: 1; color: #27ae60; }
|
493 |
+
|
494 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-loading-bar-step-1,
|
495 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-loading-bar-step-2,
|
496 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-loading-bar-step-3 { background-color: #27ae60; }
|
497 |
+
|
498 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="4"] #wpsbc-upgrader-loading-bar:after { width: 100%; }
|
499 |
+
|
500 |
+
/* Upgrader Step 5 */
|
501 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-loading-bar .spinner { display: none; }
|
502 |
+
|
503 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-message-step-1,
|
504 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-message-step-2,
|
505 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-message-step-3,
|
506 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-message-step-4 { opacity: 1; color: #27ae60; }
|
507 |
+
|
508 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-loading-bar-step-1,
|
509 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-loading-bar-step-2,
|
510 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-loading-bar-step-3,
|
511 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-loading-bar-step-4 { background-color: #27ae60; }
|
512 |
+
|
513 |
+
#wpsbc-upgrader-loading-bar-wrapper[data-step="5"] #wpsbc-upgrader-loading-bar:after { width: 100%; }
|
514 |
+
|
515 |
+
/* Skip Migration */
|
516 |
+
|
517 |
+
#wpsbc-upgrader-skip-wrapper { margin-top: 20px; }
|
518 |
+
|
519 |
+
/* Print Styles */
|
520 |
+
@media print {
|
521 |
+
#adminmenumain {display: none;}
|
522 |
+
#wpcontent {margin: 0 !important;}
|
523 |
+
}
|
524 |
+
|
525 |
+
|
526 |
+
|
527 |
+
.wpsbc-page-notice { background: #fff; border-left-style: solid; border-left-width: 4px; box-shadow: 0 1px 1px 0 rgba(0,0,0,.1); margin: 5px 0 15px; padding: 1px 12px;}
|
528 |
+
.wpsbc-page-notice p {font-size:13px; line-height:1.5; margin: .5em 0; padding: 2px; }
|
529 |
+
|
530 |
+
/*** Premium CTA ***/
|
531 |
+
.wpsbc-wrap-upgrade-to-premium h3 {margin:30px 0;}
|
532 |
+
.wpsbc-wrap-upgrade-to-premium ul {float:left; width:75%; margin:0;}
|
533 |
+
.wpsbc-wrap-upgrade-to-premium ul:after {display: block; clear: both; content:"";}
|
534 |
+
.wpsbc-wrap-upgrade-to-premium ul li {display:block; float:left; width:24%; margin:0 1% 1% 0; background:#fff; padding:15px; box-sizing:border-box;}
|
535 |
+
.wpsbc-wrap-upgrade-to-premium ul li:nth-child(4n+1) {clear:both;}
|
536 |
+
.wpsbc-wrap-upgrade-to-premium ul li strong {font-size:16px;}
|
537 |
+
.wpsbc-wrap-upgrade-to-premium ul li strong span {color: #3cc33c; font-size: 30px; position: relative; top: -4px; left: -7px;}
|
538 |
+
.wpsbc-wrap-upgrade-to-premium ul li p {margin:0; padding-top:10px;}
|
539 |
+
|
540 |
+
.wpsbc-wrap-upgrade-to-premium .cta {float:right; width:25%; background-color:#9aca41; padding:30px; box-sizing:border-box; color:#fff; margin-bottom:1%;}
|
541 |
+
.wpsbc-wrap-upgrade-to-premium .cta h3 {color:#fff; font-size:22px; line-height:28px; margin:0;}
|
542 |
+
.wpsbc-wrap-upgrade-to-premium .cta a.wpsbc-button {padding: 20px 30px 20px 30px; border-radius: 2px; text-align: center; font-size:20px; font-weight: bold; display:block; background:#1075a0; color:#fff; text-decoration:none; margin-top:20px; }
|
543 |
+
.wpsbc-wrap-upgrade-to-premium .cta a.wpsbc-button:hover {color:#000; background:#fff;}
|
544 |
+
.wpsbc-wrap-upgrade-to-premium .cta p.prices {text-align:center; margin:2px 0; font-size:12px;}
|
545 |
+
|
546 |
+
|
547 |
+
.wpsbc-wrap-upgrade-to-premium .cta-2 {float:right; width:25%; background-color:#fff; padding:30px; box-sizing:border-box; color:#fff; margin-bottom:20px;}
|
548 |
+
.wpsbc-wrap-upgrade-to-premium .cta-2 h4 {color:#000; font-size:18px; line-height:28px; margin:0; text-align: center;}
|
549 |
+
.wpsbc-wrap-upgrade-to-premium .cta-2 p.discount {text-align: center;}
|
550 |
+
.wpsbc-wrap-upgrade-to-premium .cta-2 p.discount strong {display:inline-block; background:#1075a0; color:#fff; padding:4px 10px; font-size:18px; }
|
551 |
+
|
552 |
+
.wpsbc-wrap-upgrade-cta {width:100%; background:#fff; padding:20px; box-sizing: border-box; border-radius:2px; display:block; text-decoration: none;}
|
553 |
+
.wpsbc-modal-inner .wpsbc-wrap-upgrade-cta {background:#f7f7f7;}
|
554 |
+
.wpsbc-wrap-upgrade-cta:hover .wpsbc-wrap-upgrade-cta-button {background:#1075a0;}
|
555 |
+
.wpsbc-wrap-upgrade-cta:after {display: block; content:""; clear: both;}
|
556 |
+
.wpsbc-wrap-upgrade-cta .wpsbc-wrap-upgrade-cta-button {padding: 15px 20px; border-radius: 2px; text-align: center; font-size:16px; font-weight: bold; display:block; float:right; background:#9aca41; color:#fff; text-decoration:none; }
|
557 |
+
.wpsbc-wrap-upgrade-cta .wpsbc-wrap-upgrade-cta-heading {color: #23282d; font-size: 1.3em; line-height:28px; padding:10px 0; display: block;}
|
558 |
+
|
559 |
+
|
560 |
+
/* 5.3 Styles */
|
561 |
+
|
562 |
+
.branch-5-3 .wpsbc-wrap select {max-width:none; border-radius:4px; min-height:28px;}
|
563 |
+
|
564 |
+
.branch-5-3 .wpsbc-ical-feed-calendar {border-bottom:1px solid #ccd0d4;}
|
565 |
+
.branch-5-3 .postbox .wpsbc-plugin-card-bottom {border-top:1px solid #ccd0d4;}
|
566 |
+
|
567 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container .chosen-choices {border-color:#7e8993; border-radius:4px; box-shadow:none; background: #fff url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20width%3D%2220%22%20height%3D%2220%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cpath%20d%3D%22M5%206l5%205%205-5%202%201-7%207-7-7%202-1z%22%20fill%3D%22%23555%22%2F%3E%3C%2Fsvg%3E') no-repeat right 5px top 55%; background-size: 16px 16px; cursor: pointer;}
|
568 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container.chosen-container-active .chosen-choices {border-color: #007cba; box-shadow: 0 0 0 1px #007cba;}
|
569 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container .chosen-choices .search-choice {background: #007cba;}
|
570 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container.chosen-with-drop .chosen-drop .chosen-results li.highlighted {background: #007cba;}
|
571 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container.chosen-with-drop .chosen-drop {top: calc(100% + 1px);}
|
572 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container .chosen-choices li.search-field input[type="text"] {min-height:28px; margin:0;}
|
573 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container .chosen-choices {min-height:30px;}
|
574 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container-multi .chosen-choices li.search-choice,
|
575 |
+
.branch-5-3 .wpsbc-chosen-wrapper .chosen-container-multi .chosen-choices li.search-choice {margin:2px 3px 2px 0;}
|
576 |
+
|
577 |
+
|
578 |
+
|
579 |
+
@media screen and ( max-width : 850px ) {
|
580 |
+
|
581 |
+
/* Hide the headers of the availability table */
|
582 |
+
.wpsbc-calendar-date-legend-item-header,
|
583 |
+
.wpsbc-calendar-date-description-header,
|
584 |
+
.wpsbc-calendar-date-tooltip-header { display: none; }
|
585 |
+
|
586 |
+
/* Make the availability fields 100% in width */
|
587 |
+
.wpsbc-calendar-date-legend-item,
|
588 |
+
.wpsbc-calendar-date-description-ical,
|
589 |
+
.wpsbc-calendar-date-description,
|
590 |
+
.wpsbc-calendar-date-tooltip { width: 100%; margin-top: 10px; }
|
591 |
+
|
592 |
+
/* Match the heights for all availability fields */
|
593 |
+
.wpsbc-calendar-date-legend-item { padding-left: 45px; }
|
594 |
+
|
595 |
+
.wpsbc-calendar-date-description-ical input,
|
596 |
+
.wpsbc-calendar-date-description input,
|
597 |
+
.wpsbc-calendar-date-tooltip input { height: 36px; }
|
598 |
+
|
599 |
+
.wpsbc-calendar-date-description-ical .dashicons,
|
600 |
+
.wpsbc-calendar-date-description .dashicons,
|
601 |
+
.wpsbc-calendar-date-tooltip .dashicons { top: 8px; left: 8px; }
|
602 |
+
|
603 |
+
.wpsbc-calendar-date-legend-item .wpsbc-legend-item-icon-wrapper,
|
604 |
+
.wpsbc-calendar-date-legend-item .wpsbc-legend-item-icon { width: 36px; height: 36px; }
|
605 |
+
.wpsbc-calendar-date-legend-item .wpsbc-date-inner { line-height: 36px; }
|
606 |
+
|
607 |
+
/* Position sidebar */
|
608 |
+
.wrap.wpsbc-wrap-edit-calendar #post-body.columns-2 #postbox-container-1 { margin-left: 0; }
|
609 |
+
|
610 |
+
.branch-5-3 #wpsbc-calendar-editor .wpsbc-wrap select {min-height:36px; line-height:1;}
|
611 |
+
}
|
assets/css/style-front-end.css
ADDED
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/******************************************************************************************/
|
2 |
+
/* Single Calendar Resets
|
3 |
+
/******************************************************************************************/
|
4 |
+
.wpsbc-container { position: relative; visibility: hidden; }
|
5 |
+
.wpsbc-container .wpsbc-calendars-wrapper { position: relative; }
|
6 |
+
|
7 |
+
.wpsbc-container .wpsbc-calendars:after { content: ''; display: block; clear: both; }
|
8 |
+
|
9 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table { table-layout: fixed; width: 100%; border-collapse: collapse; margin: 0 !important; padding: 0 !important; border: 0 !important; }
|
10 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table thead,
|
11 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tbody,
|
12 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr { border: 0 !important; padding: 0 !important; margin: 0 !important; background: transparent; }
|
13 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr th,
|
14 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td { position: relative; border: 0 !important; padding: 0 !important; margin: 0 !important; vertical-align: middle; background: transparent; text-shadow: none; box-shadow: none; box-sizing: border-box; }
|
15 |
+
|
16 |
+
|
17 |
+
|
18 |
+
|
19 |
+
/******************************************************************************************/
|
20 |
+
/* Single Calendar Default Styles
|
21 |
+
/******************************************************************************************/
|
22 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar { position: relative; border: 1px solid #f1f1f1; background: #fff; margin-bottom: 1em; }
|
23 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table thead tr th {padding-bottom: 8px !important; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box;}
|
24 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar-wrapper { padding: 8px 7px 7px 7px; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; }
|
25 |
+
|
26 |
+
/******************************************************************************************/
|
27 |
+
/* Calendar Loading Overlay
|
28 |
+
/******************************************************************************************/
|
29 |
+
.wpsbc-container .wpsbc-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: rgba( 255,255,255,0.6 ); }
|
30 |
+
|
31 |
+
.wpsbc-overlay-spinner { position: absolute; top: 50%; left: 50%; margin-top: -6px; margin-left: -35px; width: 70px; text-align: center; }
|
32 |
+
.wpsbc-overlay-spinner > div { width: 12px; height: 12px; background-color: #333; border-radius: 100%; display: inline-block; -webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both; animation: sk-bouncedelay 1.4s infinite ease-in-out both; }
|
33 |
+
.wpsbc-overlay-spinner .wpsbc-overlay-bounce1 { -webkit-animation-delay: -0.32s; animation-delay: -0.32s; }
|
34 |
+
.wpsbc-overlay-spinner .wpsbc-overlay-bounce2 { -webkit-animation-delay: -0.16s; animation-delay: -0.16s; }
|
35 |
+
@-webkit-keyframes sk-bouncedelay { 0%, 80%, 100% { -webkit-transform: scale(0) } 40% { -webkit-transform: scale(1.0) } }
|
36 |
+
@keyframes sk-bouncedelay { 0%, 80%, 100% { -webkit-transform: scale(0); transform: scale(0); } 40% { -webkit-transform: scale(1.0); transform: scale(1.0); } }
|
37 |
+
|
38 |
+
/******************************************************************************************/
|
39 |
+
/* Single Calendar Header
|
40 |
+
/******************************************************************************************/
|
41 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header { text-align: center; padding: 8px; background: #f5f5f5 }
|
42 |
+
|
43 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation { position: relative; padding: 0 30px; min-height: 26px; font-size: 13px; line-height: 26px; }
|
44 |
+
|
45 |
+
/******************************************************************************************/
|
46 |
+
/* Single Calendar Header Button Navigation
|
47 |
+
/******************************************************************************************/
|
48 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev,
|
49 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next { position: absolute; display: block; top: 50%; height: 26px; width: 26px; line-height: 26px; margin-top: -13px; text-decoration: none; border: 0; box-shadow: none; color: #fff; background: #bdc3c7; border-radius: 2px; }
|
50 |
+
|
51 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev { left: 0; }
|
52 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next { right: 0; }
|
53 |
+
|
54 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next .wpsbc-arrow,
|
55 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev .wpsbc-arrow { position: absolute; top: 50%; margin-top: -5px; display: inline-block; width: 0; height: 0; border-style: solid; }
|
56 |
+
|
57 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next .wpsbc-arrow { right: 50%; margin-right: -5px; border-width: 5px 0 5px 8.7px; border-color: transparent transparent transparent #ffffff; }
|
58 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev .wpsbc-arrow { left: 50%; margin-left: -5px; border-width: 5px 8.7px 5px 0; border-color: transparent #fff transparent transparent; }
|
59 |
+
|
60 |
+
/******************************************************************************************/
|
61 |
+
/* Single Calendar Header Select Navigation
|
62 |
+
/******************************************************************************************/
|
63 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-select-container select { width: 100%; height: 26px; line-height: 26px; margin: 0; padding: 0 10px; vertical-align: top; font-size: 13px; box-sizing: border-box !important; }
|
64 |
+
|
65 |
+
/******************************************************************************************/
|
66 |
+
/* Single Calendar Table Week Numbers
|
67 |
+
/******************************************************************************************/
|
68 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table td .wpsbc-week-number { background: #e8e8e8; height: 32px; }
|
69 |
+
|
70 |
+
/******************************************************************************************/
|
71 |
+
/* Single Calendar Table Dates
|
72 |
+
/******************************************************************************************/
|
73 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr th,
|
74 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td { text-align: center; padding: 1px !important; font-size: 13px; }
|
75 |
+
|
76 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table th { font-weight: bold; color: inherit; }
|
77 |
+
|
78 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date { position: relative; width: 100%; height: 100%; }
|
79 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date-inner { position: relative; width: 100%; height: 32px; }
|
80 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date-inner .wpsbc-date-number { position: absolute; z-index: 0; top: 0; left: 0; width: 100%; height: 100%; font-size: 13px; }
|
81 |
+
|
82 |
+
.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date.wpsbc-gap { background: #f7f7f7; }
|
83 |
+
|
84 |
+
/******************************************************************************************/
|
85 |
+
/* Legend: Legend Item
|
86 |
+
/******************************************************************************************/
|
87 |
+
.wpsbc-legend { text-align: left; margin: 1em 0; padding: 8px 8px 0; border: 1px solid #f1f1f1; }
|
88 |
+
|
89 |
+
.wpsbc-legend .wpsbc-legend-item { display: inline-block; margin-bottom: 8px; margin-right: 8px; }
|
90 |
+
.wpsbc-legend .wpsbc-legend-item-icon { position: relative; display: inline-block; width: 24px; height: 24px; vertical-align: middle; margin-right: 5px; box-sizing: border-box; overflow: hidden; }
|
91 |
+
.wpsbc-legend .wpsbc-legend-item-name { display: inline-block; vertical-align: middle; font-size: 13px; }
|
92 |
+
|
93 |
+
/* Legend position: side */
|
94 |
+
.wpsbc-calendars-wrapper.wpsbc-legend-position-side { padding-right: 165px; box-sizing: content-box !important; }
|
95 |
+
.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend { position: absolute; top: 0; right: 0; width: 155px; margin-top: 0; background: #fff; box-sizing: border-box !important; }
|
96 |
+
.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend .wpsbc-legend-item { display: block; margin-right: 0; line-height: 18px; }
|
97 |
+
|
98 |
+
/******************************************************************************************/
|
99 |
+
/* Calendar: Legend Item Icon
|
100 |
+
/******************************************************************************************/
|
101 |
+
.wpsbc-calendars .wpsbc-legend-item-icon { position: absolute; z-index: 0; top: 0; left: 0; display: inline-block; width: 100%; height: 100%; box-sizing: border-box; overflow: hidden; }
|
102 |
+
|
103 |
+
.wpsbc-legend-item-icon[data-type="single"] div { display: none; }
|
104 |
+
.wpsbc-legend-item-icon[data-type="single"] div:first-of-type { position: absolute; top: 0; left: 0; display: block; width: 100%; height: 100%; }
|
105 |
+
|
106 |
+
|
107 |
+
.wpsbc-legend-item-icon[data-type="split"] div svg {position:absolute; width:100%; height:100%; left: 0;top: 0;}
|
108 |
+
|
109 |
+
.wpsbc-legend-item-icon[data-type="blank"] {background-color: #f3f3f3; height: 100%;}
|
110 |
+
|
111 |
+
|
112 |
+
/******************************************************************************************/
|
113 |
+
/* Calendar Columns
|
114 |
+
/******************************************************************************************/
|
115 |
+
.wpsbc-container[data-columns] .wpsbc-calendars .wpsbc-calendar { float: left; margin-left: 5px; margin-right: 5px; box-sizing: border-box !important; }
|
116 |
+
.wpsbc-container[data-columns] .wpsbc-calendars { margin-left: -5px; margin-right: -5px; }
|
117 |
+
|
118 |
+
.wpsbc-container[data-columns="6"] .wpsbc-calendars .wpsbc-calendar { width: calc( 16.6666% - 10px ); }
|
119 |
+
.wpsbc-container[data-columns="4"] .wpsbc-calendars .wpsbc-calendar { width: calc( 25% - 10px ); }
|
120 |
+
.wpsbc-container[data-columns="3"] .wpsbc-calendars .wpsbc-calendar { width: calc( 33.3333% - 10px ); }
|
121 |
+
.wpsbc-container[data-columns="2"] .wpsbc-calendars .wpsbc-calendar { width: calc( 50% - 10px ); }
|
122 |
+
|
123 |
+
|
124 |
+
/******************************************************************************************/
|
125 |
+
/* Media Queries
|
126 |
+
/******************************************************************************************/
|
127 |
+
@media screen and (max-width: 420px){
|
128 |
+
.wpsbc-calendars-wrapper.wpsbc-legend-position-side {padding-right: 0;}
|
129 |
+
.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend {position: relative; top: auto; right: auto; width: auto;}
|
130 |
+
.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend .wpsbc-legend-item {display: inline-block; margin-right: 8px;}
|
131 |
+
}
|
132 |
+
|
133 |
+
/* Datepicker */
|
134 |
+
.ui-datepicker.wpsbc-datepicker {padding: 0; margin: 0; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0; border: 1px solid #ccc; border-top: none; -webkit-border-bottom-right-radius: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -moz-border-radius-bottomleft: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; -webkit-box-shadow: 0 3px 6px rgba(0, 0, 0, 0.075); box-shadow: 0 3px 6px rgba(0, 0, 0, 0.075); min-width: 17em; width: auto; z-index: 1000 !important; max-width: 360px; overflow: hidden; background:#fff;}
|
135 |
+
.ui-datepicker.wpsbc-datepicker * {padding: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; -webkit-border-radius: 0; -moz-border-radius: 0; border-radius: 0;}
|
136 |
+
.ui-datepicker.wpsbc-datepicker table {font-size: 13px; margin: 0; border: none; border-collapse: collapse; width: 100%;}
|
137 |
+
.ui-datepicker.wpsbc-datepicker .ui-widget-header,
|
138 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-header {background: #fff; border: none; color: #333; font-weight: normal;}
|
139 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-header .ui-state-hover {background: transparent; border-color: transparent; cursor: pointer;}
|
140 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-title {margin: 0; padding: 10px 0; color: #333; font-size: 14px; line-height: 14px; text-align: center;}
|
141 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev,
|
142 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next {position: relative; top: 0; height: 34px; width: 34px;}
|
143 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev.ui-state-disabled,
|
144 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next.ui-state-disabled {opacity:0.3;}
|
145 |
+
.ui-datepicker.wpsbc-datepicker .ui-state-hover.ui-datepicker-prev,
|
146 |
+
.ui-datepicker.wpsbc-datepicker .ui-state-hover.ui-datepicker-next {border: none;}
|
147 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev,
|
148 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev-hover {left: 0;}
|
149 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next,
|
150 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next-hover {right: 0;}
|
151 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next span,
|
152 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev span {display: none;}
|
153 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev {float: left;}
|
154 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next {float: right;}
|
155 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev:before,
|
156 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next:before {font: normal 20px/34px 'dashicons'; padding-left: 7px; color: #333; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; width: 34px; height: 34px; position: relative; top: 8px;}
|
157 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev:before {content: '\f341';}
|
158 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next:before {content: '\f345';}
|
159 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev-hover:before,
|
160 |
+
.ui-datepicker.wpsbc-datepicker .ui-datepicker-next-hover:before {opacity: 0.7;}
|
161 |
+
.ui-datepicker.wpsbc-datepicker select.ui-datepicker-month,
|
162 |
+
.ui-datepicker.wpsbc-datepicker select.ui-datepicker-year {width: 33%; border: 1px solid #ccc; padding: 5px;}
|
163 |
+
.ui-datepicker.wpsbc-datepicker select.ui-datepicker-month {border-right: none;}
|
164 |
+
.ui-datepicker.wpsbc-datepicker thead {color: #333; font-weight: 600;}
|
165 |
+
.ui-datepicker.wpsbc-datepicker th {padding: 12px 13px; border: 1px solid #f7f7f7; background: #f7f7f7;}
|
166 |
+
.ui-datepicker.wpsbc-datepicker td {padding: 0; border: 1px solid #f4f4f4;}
|
167 |
+
.ui-datepicker.wpsbc-datepicker td.ui-datepicker-other-month {background: #f9f9f9; opacity: 1;}
|
168 |
+
.ui-datepicker.wpsbc-datepicker tr:first-of-type td {border-top: 1px solid #f0f0f0;}
|
169 |
+
.ui-datepicker.wpsbc-datepicker td.ui-datepicker-current-day {background: #7f7f7f; }
|
170 |
+
.ui-datepicker.wpsbc-datepicker td.ui-datepicker-current-day a {color:#fff;}
|
171 |
+
.ui-datepicker.wpsbc-datepicker td .ui-state-default {background: transparent; border: none; text-align: center; text-decoration: none; width: auto; display: block; padding: 12px 13px; color: #333;}
|
172 |
+
.ui-datepicker.wpsbc-datepicker td .ui-state-default.ui-state-hover {box-shadow: 0 3px 6px rgba(0, 0, 0, 0.075); background:#aaa; color:#fff;}
|
173 |
+
.ui-datepicker.wpsbc-datepicker td.ui-state-disabled .ui-state-default {opacity: 0.3;}
|
assets/css/style-front-end.min.css
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
.wpsbc-container{position:relative;visibility:hidden}.wpsbc-container .wpsbc-calendars-wrapper{position:relative}.wpsbc-container .wpsbc-calendars:after{content:'';display:block;clear:both}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table{table-layout:fixed;width:100%;border-collapse:collapse;margin:0!important;padding:0!important;border:0!important}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tbody,.wpsbc-container .wpsbc-calendars .wpsbc-calendar table thead,.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr{border:0!important;padding:0!important;margin:0!important;background:0 0}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td,.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr th{position:relative;border:0!important;padding:0!important;margin:0!important;vertical-align:middle;background:0 0;text-shadow:none;box-shadow:none;box-sizing:border-box}.wpsbc-container .wpsbc-calendars .wpsbc-calendar{position:relative;border:1px solid #f1f1f1;background:#fff;margin-bottom:1em}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table thead tr th{padding-bottom:8px!important;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.wpsbc-container .wpsbc-calendars .wpsbc-calendar-wrapper{padding:8px 7px 7px 7px;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.wpsbc-container .wpsbc-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(255,255,255,.6)}.wpsbc-overlay-spinner{position:absolute;top:50%;left:50%;margin-top:-6px;margin-left:-35px;width:70px;text-align:center}.wpsbc-overlay-spinner>div{width:12px;height:12px;background-color:#333;border-radius:100%;display:inline-block;-webkit-animation:sk-bouncedelay 1.4s infinite ease-in-out both;animation:sk-bouncedelay 1.4s infinite ease-in-out both}.wpsbc-overlay-spinner .wpsbc-overlay-bounce1{-webkit-animation-delay:-.32s;animation-delay:-.32s}.wpsbc-overlay-spinner .wpsbc-overlay-bounce2{-webkit-animation-delay:-.16s;animation-delay:-.16s}@-webkit-keyframes sk-bouncedelay{0%,100%,80%{-webkit-transform:scale(0)}40%{-webkit-transform:scale(1)}}@keyframes sk-bouncedelay{0%,100%,80%{-webkit-transform:scale(0);transform:scale(0)}40%{-webkit-transform:scale(1);transform:scale(1)}}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header{text-align:center;padding:8px;background:#f5f5f5}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation{position:relative;padding:0 30px;min-height:26px;font-size:13px;line-height:26px}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next,.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev{position:absolute;display:block;top:50%;height:26px;width:26px;line-height:26px;margin-top:-13px;text-decoration:none;border:0;box-shadow:none;color:#fff;background:#bdc3c7;border-radius:2px}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev{left:0}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next{right:0}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next .wpsbc-arrow,.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev .wpsbc-arrow{position:absolute;top:50%;margin-top:-5px;display:inline-block;width:0;height:0;border-style:solid}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-next .wpsbc-arrow{right:50%;margin-right:-5px;border-width:5px 0 5px 8.7px;border-color:transparent transparent transparent #fff}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-calendar-header-navigation .wpsbc-prev .wpsbc-arrow{left:50%;margin-left:-5px;border-width:5px 8.7px 5px 0;border-color:transparent #fff transparent transparent}.wpsbc-container .wpsbc-calendars .wpsbc-calendar .wpsbc-calendar-header .wpsbc-select-container select{width:100%;height:26px;line-height:26px;margin:0;padding:0 10px;vertical-align:top;font-size:13px;box-sizing:border-box!important}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table td .wpsbc-week-number{background:#e8e8e8;height:32px}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td,.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr th{text-align:center;padding:1px!important;font-size:13px}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table th{font-weight:700;color:inherit}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date{position:relative;width:100%;height:100%}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date-inner{position:relative;width:100%;height:32px}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date-inner .wpsbc-date-number{position:absolute;z-index:0;top:0;left:0;width:100%;height:100%;font-size:13px}.wpsbc-container .wpsbc-calendars .wpsbc-calendar table tr td .wpsbc-date.wpsbc-gap{background:#f7f7f7}.wpsbc-legend{text-align:left;margin:1em 0;padding:8px 8px 0;border:1px solid #f1f1f1}.wpsbc-legend .wpsbc-legend-item{display:inline-block;margin-bottom:8px;margin-right:8px}.wpsbc-legend .wpsbc-legend-item-icon{position:relative;display:inline-block;width:24px;height:24px;vertical-align:middle;margin-right:5px;box-sizing:border-box;overflow:hidden}.wpsbc-legend .wpsbc-legend-item-name{display:inline-block;vertical-align:middle;font-size:13px}.wpsbc-calendars-wrapper.wpsbc-legend-position-side{padding-right:165px;box-sizing:content-box!important}.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend{position:absolute;top:0;right:0;width:155px;margin-top:0;background:#fff;box-sizing:border-box!important}.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend .wpsbc-legend-item{display:block;margin-right:0;line-height:18px}.wpsbc-calendars .wpsbc-legend-item-icon{position:absolute;z-index:0;top:0;left:0;display:inline-block;width:100%;height:100%;box-sizing:border-box;overflow:hidden}.wpsbc-legend-item-icon[data-type=single] div{display:none}.wpsbc-legend-item-icon[data-type=single] div:first-of-type{position:absolute;top:0;left:0;display:block;width:100%;height:100%}.wpsbc-legend-item-icon[data-type=split] div svg{position:absolute;width:100%;height:100%;left:0;top:0}.wpsbc-legend-item-icon[data-type=blank]{background-color:#f3f3f3;height:100%}.wpsbc-container[data-columns] .wpsbc-calendars .wpsbc-calendar{float:left;margin-left:5px;margin-right:5px;box-sizing:border-box!important}.wpsbc-container[data-columns] .wpsbc-calendars{margin-left:-5px;margin-right:-5px}.wpsbc-container[data-columns="6"] .wpsbc-calendars .wpsbc-calendar{width:calc(16.6666% - 10px)}.wpsbc-container[data-columns="4"] .wpsbc-calendars .wpsbc-calendar{width:calc(25% - 10px)}.wpsbc-container[data-columns="3"] .wpsbc-calendars .wpsbc-calendar{width:calc(33.3333% - 10px)}.wpsbc-container[data-columns="2"] .wpsbc-calendars .wpsbc-calendar{width:calc(50% - 10px)}@media screen and (max-width:420px){.wpsbc-calendars-wrapper.wpsbc-legend-position-side{padding-right:0}.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend{position:relative;top:auto;right:auto;width:auto}.wpsbc-calendars-wrapper.wpsbc-legend-position-side .wpsbc-legend .wpsbc-legend-item{display:inline-block;margin-right:8px}}.ui-datepicker.wpsbc-datepicker{padding:0;margin:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;border:1px solid #ccc;border-top:none;-webkit-border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px;border-bottom-right-radius:4px;border-bottom-left-radius:4px;-webkit-box-shadow:0 3px 6px rgba(0,0,0,.075);box-shadow:0 3px 6px rgba(0,0,0,.075);min-width:17em;width:auto;z-index:1000!important;max-width:360px;overflow:hidden;background:#fff}.ui-datepicker.wpsbc-datepicker *{padding:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-datepicker.wpsbc-datepicker table{font-size:13px;margin:0;border:none;border-collapse:collapse;width:100%}.ui-datepicker.wpsbc-datepicker .ui-datepicker-header,.ui-datepicker.wpsbc-datepicker .ui-widget-header{background:#fff;border:none;color:#333;font-weight:400}.ui-datepicker.wpsbc-datepicker .ui-datepicker-header .ui-state-hover{background:0 0;border-color:transparent;cursor:pointer}.ui-datepicker.wpsbc-datepicker .ui-datepicker-title{margin:0;padding:10px 0;color:#333;font-size:14px;line-height:14px;text-align:center}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next,.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev{position:relative;top:0;height:34px;width:34px}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next.ui-state-disabled,.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev.ui-state-disabled{opacity:.3}.ui-datepicker.wpsbc-datepicker .ui-state-hover.ui-datepicker-next,.ui-datepicker.wpsbc-datepicker .ui-state-hover.ui-datepicker-prev{border:none}.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev,.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev-hover{left:0}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next,.ui-datepicker.wpsbc-datepicker .ui-datepicker-next-hover{right:0}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next span,.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev span{display:none}.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev{float:left}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next{float:right}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next:before,.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev:before{font:normal 20px/34px dashicons;padding-left:7px;color:#333;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;width:34px;height:34px;position:relative;top:8px}.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev:before{content:'\f341'}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next:before{content:'\f345'}.ui-datepicker.wpsbc-datepicker .ui-datepicker-next-hover:before,.ui-datepicker.wpsbc-datepicker .ui-datepicker-prev-hover:before{opacity:.7}.ui-datepicker.wpsbc-datepicker select.ui-datepicker-month,.ui-datepicker.wpsbc-datepicker select.ui-datepicker-year{width:33%;border:1px solid #ccc;padding:5px}.ui-datepicker.wpsbc-datepicker select.ui-datepicker-month{border-right:none}.ui-datepicker.wpsbc-datepicker thead{color:#333;font-weight:600}.ui-datepicker.wpsbc-datepicker th{padding:12px 13px;border:1px solid #f7f7f7;background:#f7f7f7}.ui-datepicker.wpsbc-datepicker td{padding:0;border:1px solid #f4f4f4}.ui-datepicker.wpsbc-datepicker td.ui-datepicker-other-month{background:#f9f9f9;opacity:1}.ui-datepicker.wpsbc-datepicker tr:first-of-type td{border-top:1px solid #f0f0f0}.ui-datepicker.wpsbc-datepicker td.ui-datepicker-current-day{background:#7f7f7f}.ui-datepicker.wpsbc-datepicker td.ui-datepicker-current-day a{color:#fff}.ui-datepicker.wpsbc-datepicker td .ui-state-default{background:0 0;border:none;text-align:center;text-decoration:none;width:auto;display:block;padding:12px 13px;color:#333}.ui-datepicker.wpsbc-datepicker td .ui-state-default.ui-state-hover{box-shadow:0 3px 6px rgba(0,0,0,.075);background:#aaa;color:#fff}.ui-datepicker.wpsbc-datepicker td.ui-state-disabled .ui-state-default{opacity:.3}
|
assets/img/date-icon.svg
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20" height="20" preserveAspectRatio="xMidYMid meet" viewBox="0 0 20 20" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);"><path d="M15 4h3v15H2V4h3V3c0-.41.15-.76.44-1.06.29-.29.65-.44 1.06-.44s.77.15 1.06.44c.29.3.44.65.44 1.06v1h4V3c0-.41.15-.76.44-1.06.29-.29.65-.44 1.06-.44s.77.15 1.06.44c.29.3.44.65.44 1.06v1zM6 3v2.5a.491.491 0 0 0 .5.5.491.491 0 0 0 .5-.5V3c0-.14-.05-.26-.15-.35-.09-.1-.21-.15-.35-.15s-.26.05-.35.15c-.1.09-.15.21-.15.35zm7 0v2.5c0 .14.05.26.14.36.1.09.22.14.36.14s.26-.05.36-.14c.09-.1.14-.22.14-.36V3a.491.491 0 0 0-.5-.5.491.491 0 0 0-.5.5zm4 15V8H3v10h14zM7 9v2H5V9h2zm2 0h2v2H9V9zm4 2V9h2v2h-2zm-6 1v2H5v-2h2zm2 0h2v2H9v-2zm4 2v-2h2v2h-2zm-6 1v2H5v-2h2zm4 2H9v-2h2v2zm4 0h-2v-2h2v2z" fill="#7f7f7f"/><rect x="0" y="0" width="20" height="20" fill="rgba(0, 0, 0, 0)" /></svg>
|
assets/img/flags/ad.png
ADDED
Binary file
|
assets/img/flags/ae.png
ADDED
Binary file
|
assets/img/flags/af.png
ADDED
Binary file
|
assets/img/flags/ag.png
ADDED
Binary file
|
assets/img/flags/ai.png
ADDED
Binary file
|
assets/img/flags/al.png
ADDED
Binary file
|
assets/img/flags/am.png
ADDED
Binary file
|
assets/img/flags/an.png
ADDED
Binary file
|
assets/img/flags/ao.png
ADDED
Binary file
|
assets/img/flags/ar.png
ADDED
Binary file
|
assets/img/flags/as.png
ADDED
Binary file
|
assets/img/flags/at.png
ADDED
Binary file
|
assets/img/flags/au.png
ADDED
Binary file
|
assets/img/flags/aw.png
ADDED
Binary file
|
assets/img/flags/ax.png
ADDED
Binary file
|
assets/img/flags/az.png
ADDED
Binary file
|
assets/img/flags/ba.png
ADDED
Binary file
|
assets/img/flags/bb.png
ADDED
Binary file
|
assets/img/flags/bd.png
ADDED
Binary file
|
assets/img/flags/be.png
ADDED
Binary file
|
assets/img/flags/bf.png
ADDED
Binary file
|
assets/img/flags/bg.png
ADDED
Binary file
|
assets/img/flags/bh.png
ADDED
Binary file
|
assets/img/flags/bi.png
ADDED
Binary file
|
assets/img/flags/bj.png
ADDED
Binary file
|
assets/img/flags/bm.png
ADDED
Binary file
|
assets/img/flags/bn.png
ADDED
Binary file
|
assets/img/flags/bo.png
ADDED
Binary file
|
assets/img/flags/br.png
ADDED
Binary file
|
assets/img/flags/bs.png
ADDED
Binary file
|
assets/img/flags/bt.png
ADDED
Binary file
|
assets/img/flags/bv.png
ADDED
Binary file
|
assets/img/flags/bw.png
ADDED
Binary file
|
assets/img/flags/by.png
ADDED
Binary file
|
assets/img/flags/bz.png
ADDED
Binary file
|
assets/img/flags/ca.png
ADDED
Binary file
|
assets/img/flags/cc.png
ADDED
Binary file
|
assets/img/flags/cd.png
ADDED
Binary file
|
assets/img/flags/cf.png
ADDED
Binary file
|
assets/img/flags/cg.png
ADDED
Binary file
|
assets/img/flags/ch.png
ADDED
Binary file
|
assets/img/flags/ci.png
ADDED
Binary file
|
assets/img/flags/ck.png
ADDED
Binary file
|
assets/img/flags/cl.png
ADDED
Binary file
|
assets/img/flags/cm.png
ADDED
Binary file
|
assets/img/flags/cn.png
ADDED
Binary file
|
assets/img/flags/co.png
ADDED
Binary file
|
assets/img/flags/cr.png
ADDED
Binary file
|
assets/img/flags/cs.png
ADDED
Binary file
|
assets/img/flags/cu.png
ADDED
Binary file
|
assets/img/flags/cv.png
ADDED
Binary file
|
assets/img/flags/cx.png
ADDED
Binary file
|
assets/img/flags/cy.png
ADDED
Binary file
|
assets/img/flags/cz.png
ADDED
Binary file
|
assets/img/flags/da.png
ADDED
Binary file
|
assets/img/flags/de.png
ADDED
Binary file
|
assets/img/flags/dj.png
ADDED
Binary file
|
assets/img/flags/dm.png
ADDED
Binary file
|
assets/img/flags/do.png
ADDED
Binary file
|
assets/img/flags/dz.png
ADDED
Binary file
|
assets/img/flags/ec.png
ADDED
Binary file
|
assets/img/flags/ee.png
ADDED
Binary file
|
assets/img/flags/eg.png
ADDED
Binary file
|
assets/img/flags/eh.png
ADDED
Binary file
|
assets/img/flags/el.png
ADDED
Binary file
|
assets/img/flags/en.png
ADDED
Binary file
|
assets/img/flags/england.png
ADDED
Binary file
|
assets/img/flags/er.png
ADDED
Binary file
|
assets/img/flags/es.png
ADDED
Binary file
|
assets/img/flags/et.png
ADDED
Binary file
|
assets/img/flags/eu.png
ADDED
Binary file
|
assets/img/flags/europeanunion.png
ADDED
Binary file
|
assets/img/flags/fam.png
ADDED
Binary file
|
assets/img/flags/fi.png
ADDED
Binary file
|
assets/img/flags/fj.png
ADDED
Binary file
|
assets/img/flags/fk.png
ADDED
Binary file
|
assets/img/flags/fm.png
ADDED
Binary file
|
assets/img/flags/fo.png
ADDED
Binary file
|
assets/img/flags/fr.png
ADDED
Binary file
|
assets/img/flags/ga.png
ADDED
Binary file
|
assets/img/flags/gb.png
ADDED
Binary file
|
assets/img/flags/gd.png
ADDED
Binary file
|
assets/img/flags/ge.png
ADDED
Binary file
|
assets/img/flags/gf.png
ADDED
Binary file
|
assets/img/flags/gh.png
ADDED
Binary file
|
assets/img/flags/gi.png
ADDED
Binary file
|
assets/img/flags/gl.png
ADDED
Binary file
|
assets/img/flags/gm.png
ADDED
Binary file
|
assets/img/flags/gn.png
ADDED
Binary file
|
assets/img/flags/gp.png
ADDED
Binary file
|
assets/img/flags/gq.png
ADDED
Binary file
|
assets/img/flags/gs.png
ADDED
Binary file
|
assets/img/flags/gt.png
ADDED
Binary file
|
assets/img/flags/gu.png
ADDED
Binary file
|
assets/img/flags/gw.png
ADDED
Binary file
|
assets/img/flags/gy.png
ADDED
Binary file
|
assets/img/flags/hk.png
ADDED
Binary file
|
assets/img/flags/hm.png
ADDED
Binary file
|
assets/img/flags/hn.png
ADDED
Binary file
|
assets/img/flags/hr.png
ADDED
Binary file
|
assets/img/flags/ht.png
ADDED
Binary file
|
assets/img/flags/hu.png
ADDED
Binary file
|
assets/img/flags/id.png
ADDED
Binary file
|
assets/img/flags/ie.png
ADDED
Binary file
|
assets/img/flags/il.png
ADDED
Binary file
|
assets/img/flags/in.png
ADDED
Binary file
|
assets/img/flags/io.png
ADDED
Binary file
|
assets/img/flags/iq.png
ADDED
Binary file
|
assets/img/flags/ir.png
ADDED
Binary file
|
assets/img/flags/is.png
ADDED
Binary file
|
assets/img/flags/it.png
ADDED
Binary file
|
assets/img/flags/jm.png
ADDED
Binary file
|
assets/img/flags/jo.png
ADDED
Binary file
|
assets/img/flags/jp.png
ADDED
Binary file
|
assets/img/flags/ke.png
ADDED
Binary file
|
assets/img/flags/kg.png
ADDED
Binary file
|
assets/img/flags/kh.png
ADDED
Binary file
|
assets/img/flags/ki.png
ADDED
Binary file
|
assets/img/flags/km.png
ADDED
Binary file
|
assets/img/flags/kn.png
ADDED
Binary file
|
assets/img/flags/kp.png
ADDED
Binary file
|
assets/img/flags/kr.png
ADDED
Binary file
|
assets/img/flags/kw.png
ADDED
Binary file
|
assets/img/flags/ky.png
ADDED
Binary file
|
assets/img/flags/kz.png
ADDED
Binary file
|
assets/img/flags/la.png
ADDED
Binary file
|
assets/img/flags/lb.png
ADDED
Binary file
|
assets/img/flags/lc.png
ADDED
Binary file
|
assets/img/flags/li.png
ADDED
Binary file
|
assets/img/flags/lk.png
ADDED
Binary file
|
assets/img/flags/lr.png
ADDED
Binary file
|
assets/img/flags/ls.png
ADDED
Binary file
|
assets/img/flags/lt.png
ADDED
Binary file
|
assets/img/flags/lu.png
ADDED
Binary file
|
assets/img/flags/lv.png
ADDED
Binary file
|
assets/img/flags/ly.png
ADDED
Binary file
|
assets/img/flags/ma.png
ADDED
Binary file
|
assets/img/flags/mc.png
ADDED
Binary file
|
assets/img/flags/md.png
ADDED
Binary file
|
assets/img/flags/me.png
ADDED
Binary file
|
assets/img/flags/mg.png
ADDED
Binary file
|
assets/img/flags/mh.png
ADDED
Binary file
|
assets/img/flags/mk.png
ADDED
Binary file
|
assets/img/flags/ml.png
ADDED
Binary file
|
assets/img/flags/mm.png
ADDED
Binary file
|
assets/img/flags/mn.png
ADDED
Binary file
|
assets/img/flags/mo.png
ADDED
Binary file
|
assets/img/flags/mp.png
ADDED
Binary file
|
assets/img/flags/mq.png
ADDED
Binary file
|
assets/img/flags/mr.png
ADDED
Binary file
|
assets/img/flags/ms.png
ADDED
Binary file
|
assets/img/flags/mt.png
ADDED
Binary file
|
assets/img/flags/mu.png
ADDED
Binary file
|
assets/img/flags/mv.png
ADDED
Binary file
|
assets/img/flags/mw.png
ADDED
Binary file
|
assets/img/flags/mx.png
ADDED
Binary file
|
assets/img/flags/my.png
ADDED
Binary file
|
assets/img/flags/mz.png
ADDED
Binary file
|
assets/img/flags/na.png
ADDED
Binary file
|
assets/img/flags/nc.png
ADDED
Binary file
|
assets/img/flags/ne.png
ADDED
Binary file
|
assets/img/flags/nf.png
ADDED
Binary file
|
assets/img/flags/ng.png
ADDED
Binary file
|
assets/img/flags/ni.png
ADDED
Binary file
|
assets/img/flags/nl.png
ADDED
Binary file
|
assets/img/flags/no.png
ADDED
Binary file
|
assets/img/flags/np.png
ADDED
Binary file
|
assets/img/flags/nr.png
ADDED
Binary file
|
assets/img/flags/nu.png
ADDED
Binary file
|
assets/img/flags/nz.png
ADDED
Binary file
|
assets/img/flags/om.png
ADDED
Binary file
|
assets/img/flags/pa.png
ADDED
Binary file
|
assets/img/flags/pe.png
ADDED
Binary file
|
assets/img/flags/pf.png
ADDED
Binary file
|
assets/img/flags/pg.png
ADDED
Binary file
|
assets/img/flags/ph.png
ADDED
Binary file
|
assets/img/flags/pk.png
ADDED
Binary file
|
assets/img/flags/pl.png
ADDED
Binary file
|
assets/img/flags/pm.png
ADDED
Binary file
|
assets/img/flags/pn.png
ADDED
Binary file
|
assets/img/flags/pr.png
ADDED
Binary file
|
assets/img/flags/ps.png
ADDED
Binary file
|
assets/img/flags/pt.png
ADDED
Binary file
|
assets/img/flags/pw.png
ADDED
Binary file
|
assets/img/flags/py.png
ADDED
Binary file
|
assets/img/flags/qa.png
ADDED
Binary file
|
assets/img/flags/re.png
ADDED
Binary file
|
assets/img/flags/ro.png
ADDED
Binary file
|
assets/img/flags/ru.png
ADDED
Binary file
|
assets/img/flags/rw.png
ADDED
Binary file
|
assets/img/flags/sa.png
ADDED
Binary file
|
assets/img/flags/sb.png
ADDED
Binary file
|
assets/img/flags/sc.png
ADDED
Binary file
|
assets/img/flags/scotland.png
ADDED
Binary file
|
assets/img/flags/sd.png
ADDED
Binary file
|
assets/img/flags/se.png
ADDED
Binary file
|
assets/img/flags/sg.png
ADDED
Binary file
|
assets/img/flags/sh.png
ADDED
Binary file
|
assets/img/flags/si.png
ADDED
Binary file
|
assets/img/flags/sj.png
ADDED
Binary file
|
assets/img/flags/sk.png
ADDED
Binary file
|
assets/img/flags/sl.png
ADDED
Binary file
|
assets/img/flags/sm.png
ADDED
Binary file
|
assets/img/flags/sn.png
ADDED
Binary file
|
assets/img/flags/so.png
ADDED
Binary file
|
assets/img/flags/sr.png
ADDED
Binary file
|
assets/img/flags/srn.png
ADDED
Binary file
|
assets/img/flags/st.png
ADDED
Binary file
|
assets/img/flags/sv.png
ADDED
Binary file
|
assets/img/flags/sy.png
ADDED
Binary file
|
assets/img/flags/sz.png
ADDED
Binary file
|
assets/img/flags/tc.png
ADDED
Binary file
|
assets/img/flags/td.png
ADDED
Binary file
|
assets/img/flags/tf.png
ADDED
Binary file
|
assets/img/flags/tg.png
ADDED
Binary file
|
assets/img/flags/th.png
ADDED
Binary file
|
assets/img/flags/tj.png
ADDED
Binary file
|
assets/img/flags/tk.png
ADDED
Binary file
|
assets/img/flags/tl.png
ADDED
Binary file
|
assets/img/flags/tm.png
ADDED
Binary file
|
assets/img/flags/tn.png
ADDED
Binary file
|
assets/img/flags/to.png
ADDED
Binary file
|
assets/img/flags/tr.png
ADDED
Binary file
|
assets/img/flags/tt.png
ADDED
Binary file
|
assets/img/flags/tv.png
ADDED
Binary file
|
assets/img/flags/tw.png
ADDED
Binary file
|
assets/img/flags/tz.png
ADDED
Binary file
|
assets/img/flags/ua.png
ADDED
Binary file
|
assets/img/flags/ug.png
ADDED
Binary file
|
assets/img/flags/um.png
ADDED
Binary file
|
assets/img/flags/us.png
ADDED
Binary file
|
assets/img/flags/uy.png
ADDED
Binary file
|
assets/img/flags/uz.png
ADDED
Binary file
|
assets/img/flags/va.png
ADDED
Binary file
|
assets/img/flags/vc.png
ADDED
Binary file
|
assets/img/flags/ve.png
ADDED
Binary file
|
assets/img/flags/vg.png
ADDED
Binary file
|
assets/img/flags/vi.png
ADDED
Binary file
|
assets/img/flags/vn.png
ADDED
Binary file
|
assets/img/flags/vu.png
ADDED
Binary file
|
assets/img/flags/wales.png
ADDED
Binary file
|
assets/img/flags/wf.png
ADDED
Binary file
|
assets/img/flags/ws.png
ADDED
Binary file
|
assets/img/flags/ye.png
ADDED
Binary file
|
assets/img/flags/yt.png
ADDED
Binary file
|
assets/img/flags/za.png
ADDED
Binary file
|
assets/img/flags/zm.png
ADDED
Binary file
|
assets/img/flags/zw.png
ADDED
Binary file
|
assets/js/script-admin-edit-calendar.js
ADDED
@@ -0,0 +1,368 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* This is the object that stores all calendar data when editing a calendar
|
3 |
+
*
|
4 |
+
* Its structure is by year, month, day basis. Eg: wpsbc_calendar_data[2018][1][21]
|
5 |
+
*
|
6 |
+
*/
|
7 |
+
var wpsbc_calendar_data = {};
|
8 |
+
|
9 |
+
jQuery(function ($) {
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Retrieves an array with the query arguments found in a given string
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
function get_query_args(string) {
|
16 |
+
|
17 |
+
var query_arr = string.replace('?', '').split('&');
|
18 |
+
var query_params = [];
|
19 |
+
|
20 |
+
for (var q = 0, q_query_arr = query_arr.length; q < q_query_arr; q++) {
|
21 |
+
|
22 |
+
var q_arr = query_arr[q].split('=');
|
23 |
+
query_params[q_arr[0]] = q_arr[1];
|
24 |
+
|
25 |
+
}
|
26 |
+
|
27 |
+
return query_params;
|
28 |
+
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Resizes the calendar to always have square dates
|
33 |
+
*
|
34 |
+
*/
|
35 |
+
function resize_calendar($calendars_wrapper) {
|
36 |
+
|
37 |
+
var td_width = $calendars_wrapper.find('td').first().width();
|
38 |
+
|
39 |
+
$calendars_wrapper.find('td .wpsbc-date-inner, td .wpsbc-week-number').css('height', td_width + 'px');
|
40 |
+
$calendars_wrapper.find('td .wpsbc-date-inner, td .wpsbc-week-number').css('line-height', td_width + 'px');
|
41 |
+
|
42 |
+
$calendars_wrapper.css('visibility', 'visible');
|
43 |
+
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Refreshed the output of the calendar with the given data
|
49 |
+
*
|
50 |
+
*/
|
51 |
+
function refresh_calendar($calendar_container, current_year, current_month) {
|
52 |
+
|
53 |
+
var $calendar_container = $calendar_container;
|
54 |
+
var $calendar_editor = $('#wpsbc-calendar-editor');
|
55 |
+
|
56 |
+
if ($calendar_container.hasClass('wpsbc-is-loading'))
|
57 |
+
return false;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Prepare the calendar data
|
61 |
+
*
|
62 |
+
*/
|
63 |
+
var data = $calendar_container.data();
|
64 |
+
|
65 |
+
data['action'] = 'wpsbc_refresh_calendar_editor';
|
66 |
+
data['current_year'] = current_year;
|
67 |
+
data['current_month'] = current_month;
|
68 |
+
data['calendar_data'] = JSON.stringify(wpsbc_calendar_data);
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Add loading animation
|
72 |
+
*
|
73 |
+
*/
|
74 |
+
$calendar_container.find('.wpsbc-calendar').append('<div class="wpsbc-overlay"><div class="wpsbc-overlay-spinner"><div class="wpsbc-overlay-bounce1"></div><div class="wpsbc-overlay-bounce2"></div><div class="wpsbc-overlay-bounce3"></div></div></div>');
|
75 |
+
$calendar_container.addClass('wpsbc-is-loading');
|
76 |
+
$calendar_container.find('select').attr('disabled', true);
|
77 |
+
|
78 |
+
$('#wpsbc-calendar-editor').append('<div class="wpsbc-overlay"><div class="wpsbc-overlay-spinner"><div class="wpsbc-overlay-bounce1"></div><div class="wpsbc-overlay-bounce2"></div><div class="wpsbc-overlay-bounce3"></div></div></div>');
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Make the request
|
82 |
+
*
|
83 |
+
*/
|
84 |
+
$.post(ajaxurl, data, function (response) {
|
85 |
+
|
86 |
+
response = JSON.parse(response);
|
87 |
+
|
88 |
+
$calendar_container.replaceWith(response.calendar);
|
89 |
+
$calendar_editor.replaceWith(response.calendar_editor);
|
90 |
+
|
91 |
+
resize_calendar($('.wpsbc-container[data-id="' + data['id'] + '"]'));
|
92 |
+
refresh_calendar_dates();
|
93 |
+
|
94 |
+
});
|
95 |
+
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Updates the calendar legend items icons of each date from the
|
101 |
+
* data found in wpsbc_calendar_data for the legend items
|
102 |
+
*
|
103 |
+
*/
|
104 |
+
function refresh_calendar_dates() {
|
105 |
+
|
106 |
+
var $calendar_container = $('.wpsbc-container');
|
107 |
+
|
108 |
+
var year = $calendar_container.data('current_year');
|
109 |
+
var month = $calendar_container.data('current_month');
|
110 |
+
|
111 |
+
if (typeof wpsbc_calendar_data[year] == 'undefined')
|
112 |
+
return false;
|
113 |
+
|
114 |
+
if (typeof wpsbc_calendar_data[year][month] == 'undefined')
|
115 |
+
return false;
|
116 |
+
|
117 |
+
for (day in wpsbc_calendar_data[year][month]) {
|
118 |
+
|
119 |
+
if (typeof wpsbc_calendar_data[year][month][day] == 'undefined')
|
120 |
+
continue;
|
121 |
+
|
122 |
+
if (typeof wpsbc_calendar_data[year][month][day]['legend_item_id'] == 'undefined')
|
123 |
+
continue;
|
124 |
+
|
125 |
+
var $legend_item_selector = $('.wpsbc-calendar-date-legend-item select[data-year="' + year + '"][data-month="' + month + '"][data-day="' + day + '"]');
|
126 |
+
|
127 |
+
$calendar_container.find('[data-year="' + year + '"][data-month="' + month + '"][data-day="' + day + '"] .wpsbc-legend-item-icon')
|
128 |
+
.attr('class', 'wpsbc-legend-item-icon wpsbc-legend-item-icon-' + $legend_item_selector.val())
|
129 |
+
.attr('data-type', $legend_item_selector.find('option:selected').data('type'));
|
130 |
+
|
131 |
+
}
|
132 |
+
|
133 |
+
}
|
134 |
+
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Callback function that is triggered on changes made to input, textarea, select, etc.
|
138 |
+
* fields from the calendar editor
|
139 |
+
*
|
140 |
+
*/
|
141 |
+
function calendar_editor_field_change($input) {
|
142 |
+
|
143 |
+
/**
|
144 |
+
* Exit if the input does not have the needed data values
|
145 |
+
*
|
146 |
+
*/
|
147 |
+
if (typeof $input.data('year') == 'undefined')
|
148 |
+
return false;
|
149 |
+
|
150 |
+
if (typeof $input.data('month') == 'undefined')
|
151 |
+
return false;
|
152 |
+
|
153 |
+
if (typeof $input.data('day') == 'undefined')
|
154 |
+
return false;
|
155 |
+
|
156 |
+
if (typeof $input.data('name') == 'undefined')
|
157 |
+
return false;
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Sanitize the data values and set them as variables
|
161 |
+
*
|
162 |
+
*/
|
163 |
+
var year = parseInt($input.data('year'));
|
164 |
+
var month = parseInt($input.data('month'));
|
165 |
+
var day = parseInt($input.data('day'));
|
166 |
+
var name = $input.data('name');
|
167 |
+
|
168 |
+
// Update data
|
169 |
+
update_calendar_data(year, month, day, name, $input.val());
|
170 |
+
|
171 |
+
}
|
172 |
+
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Updates the calendar data object with new data from the provided field
|
176 |
+
*
|
177 |
+
*/
|
178 |
+
function update_calendar_data(year, month, day, field_name, field_value) {
|
179 |
+
|
180 |
+
if (typeof field_name == 'undefined')
|
181 |
+
return false;
|
182 |
+
|
183 |
+
if (typeof field_value == 'undefined')
|
184 |
+
return false;
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Create the object for each date layer if needed
|
188 |
+
*
|
189 |
+
*/
|
190 |
+
if (typeof wpsbc_calendar_data[year] == 'undefined')
|
191 |
+
wpsbc_calendar_data[year] = {};
|
192 |
+
|
193 |
+
if (typeof wpsbc_calendar_data[year][month] == 'undefined')
|
194 |
+
wpsbc_calendar_data[year][month] = {};
|
195 |
+
|
196 |
+
if (typeof wpsbc_calendar_data[year][month][day] == 'undefined')
|
197 |
+
wpsbc_calendar_data[year][month][day] = {};
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Set the value for the current date
|
201 |
+
*
|
202 |
+
*/
|
203 |
+
wpsbc_calendar_data[year][month][day][field_name] = field_value;
|
204 |
+
|
205 |
+
}
|
206 |
+
|
207 |
+
|
208 |
+
/**
|
209 |
+
* Resize the calendars on page load
|
210 |
+
*
|
211 |
+
*/
|
212 |
+
$('.wpsbc-container').each(function () {
|
213 |
+
resize_calendar($(this));
|
214 |
+
});
|
215 |
+
|
216 |
+
/**
|
217 |
+
* Resize the calendars on page resize
|
218 |
+
*
|
219 |
+
*/
|
220 |
+
$(window).on('resize', function () {
|
221 |
+
$('.wpsbc-container').each(function () {
|
222 |
+
resize_calendar($(this));
|
223 |
+
});
|
224 |
+
});
|
225 |
+
|
226 |
+
|
227 |
+
/**
|
228 |
+
* Handles the navigation of the Previous button
|
229 |
+
*
|
230 |
+
*/
|
231 |
+
$(document).on('click', '.wpsbc-container .wpsbc-prev', function (e) {
|
232 |
+
|
233 |
+
e.preventDefault();
|
234 |
+
|
235 |
+
// Set container
|
236 |
+
var $container = $(this).closest('.wpsbc-container');
|
237 |
+
|
238 |
+
// Set the current year and month that are displayed in the calendar
|
239 |
+
var current_month = $container.data('current_month');
|
240 |
+
var current_year = $container.data('current_year');
|
241 |
+
|
242 |
+
|
243 |
+
current_month -= 1;
|
244 |
+
|
245 |
+
if (current_month < 1) {
|
246 |
+
current_month = 12;
|
247 |
+
current_year -= 1;
|
248 |
+
}
|
249 |
+
|
250 |
+
refresh_calendar($container, current_year, current_month);
|
251 |
+
|
252 |
+
});
|
253 |
+
|
254 |
+
/**
|
255 |
+
* Handles the navigation of the Next button
|
256 |
+
*
|
257 |
+
*/
|
258 |
+
$(document).on('click', '.wpsbc-container .wpsbc-next', function (e) {
|
259 |
+
|
260 |
+
e.preventDefault();
|
261 |
+
|
262 |
+
// Set container
|
263 |
+
var $container = $(this).closest('.wpsbc-container');
|
264 |
+
|
265 |
+
// Set the current year and month that are displayed in the calendar
|
266 |
+
var current_month = $container.data('current_month');
|
267 |
+
var current_year = $container.data('current_year');
|
268 |
+
|
269 |
+
current_month += 1;
|
270 |
+
|
271 |
+
if (current_month > 12) {
|
272 |
+
current_month = 1;
|
273 |
+
current_year += 1;
|
274 |
+
}
|
275 |
+
|
276 |
+
refresh_calendar($container, current_year, current_month);
|
277 |
+
|
278 |
+
});
|
279 |
+
|
280 |
+
/**
|
281 |
+
* Handles the navigation of the Month Selector
|
282 |
+
*
|
283 |
+
*/
|
284 |
+
$(document).on('change', '.wpsbc-container .wpsbc-select-container select', function () {
|
285 |
+
|
286 |
+
// Set container
|
287 |
+
var $container = $(this).closest('.wpsbc-container');
|
288 |
+
|
289 |
+
var date = new Date($(this).val() * 1000);
|
290 |
+
|
291 |
+
var year = date.getFullYear();
|
292 |
+
var month = date.getMonth() + 1;
|
293 |
+
|
294 |
+
refresh_calendar($container, year, month);
|
295 |
+
|
296 |
+
});
|
297 |
+
|
298 |
+
|
299 |
+
/**
|
300 |
+
* Updates the calendar wpsbc_calendar_data object when doing changes in the
|
301 |
+
* calendar editor
|
302 |
+
*
|
303 |
+
*/
|
304 |
+
$(document).on('change', '#wpsbc-calendar-editor select', function () {
|
305 |
+
|
306 |
+
calendar_editor_field_change($(this));
|
307 |
+
|
308 |
+
});
|
309 |
+
|
310 |
+
$(document).on('keyup', '#wpsbc-calendar-editor input, #wpsbc-calendar-editor textarea', function () {
|
311 |
+
|
312 |
+
calendar_editor_field_change($(this));
|
313 |
+
|
314 |
+
});
|
315 |
+
|
316 |
+
|
317 |
+
/**
|
318 |
+
* Handle legend item select change in edit caledndar screen
|
319 |
+
*
|
320 |
+
*/
|
321 |
+
$(document).on('change', '.wpsbc-calendar-date-legend-item select', function () {
|
322 |
+
|
323 |
+
$(this).siblings('div').find('.wpsbc-legend-item-icon')
|
324 |
+
.attr('class', 'wpsbc-legend-item-icon wpsbc-legend-item-icon-' + $(this).val())
|
325 |
+
.attr('data-type', $(this).find('option:selected').data('type'));
|
326 |
+
|
327 |
+
$(this).closest('.wpsbc-calendar-date-legend-item')
|
328 |
+
.attr('class', 'wpsbc-calendar-date-legend-item wpsbc-calendar-date-legend-item-' + $(this).val());
|
329 |
+
|
330 |
+
refresh_calendar_dates();
|
331 |
+
|
332 |
+
});
|
333 |
+
|
334 |
+
/**
|
335 |
+
* Handles the saving of the calendar by making an AJAX call to the server
|
336 |
+
* with the wpsbc_calendar_data.
|
337 |
+
*
|
338 |
+
* Upon success refreshes the page and adds a success message
|
339 |
+
*
|
340 |
+
*/
|
341 |
+
$(document).on('click', '.wpsbc-save-calendar', function (e) {
|
342 |
+
|
343 |
+
e.preventDefault();
|
344 |
+
|
345 |
+
var form_data = $(this).closest('form').serialize();
|
346 |
+
|
347 |
+
var data = {
|
348 |
+
action: 'wpsbc_save_calendar_data',
|
349 |
+
form_data: form_data,
|
350 |
+
calendar_data: JSON.stringify(wpsbc_calendar_data),
|
351 |
+
current_year: $('.wpsbc-container').data('current_year'),
|
352 |
+
current_month: $('.wpsbc-container').data('current_month')
|
353 |
+
}
|
354 |
+
|
355 |
+
// Disable all buttons and show loading spinner
|
356 |
+
$('.wpsbc-wrap-edit-calendar input, .wpsbc-wrap-edit-calendar select, .wpsbc-wrap-edit-calendar textarea').attr('disabled', true);
|
357 |
+
$(this).siblings('.wpsbc-save-calendar-spinner').css('visibility', 'visible');
|
358 |
+
|
359 |
+
$.post(ajaxurl, data, function (response) {
|
360 |
+
|
361 |
+
if (typeof response != 'undefined')
|
362 |
+
window.location.replace(response);
|
363 |
+
|
364 |
+
});
|
365 |
+
|
366 |
+
});
|
367 |
+
|
368 |
+
});
|
assets/js/script-admin-uninstaller.js
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery( function($) {
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Handle the Uninstall Plugin button
|
5 |
+
*
|
6 |
+
*/
|
7 |
+
$(document).on( 'click', '#wpsbc-uninstaller-button', function(e) {
|
8 |
+
|
9 |
+
if( ! $('#wpsbc-uninstaller-confirmation').is(':visible') ) {
|
10 |
+
|
11 |
+
e.preventDefault();
|
12 |
+
|
13 |
+
$('#wpsbc-uninstaller-confirmation').fadeIn( 300 );
|
14 |
+
$(this).attr( 'disabled', true );
|
15 |
+
|
16 |
+
return false;
|
17 |
+
|
18 |
+
} else {
|
19 |
+
|
20 |
+
if( ! confirm( 'Are you sure you wish to remove all WP Simple Booking Calendar related data?' ) )
|
21 |
+
return false;
|
22 |
+
|
23 |
+
}
|
24 |
+
|
25 |
+
});
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Track the value of the confirmation field to match the word REMOVE
|
29 |
+
* before letting the user click the Uninstall button
|
30 |
+
*
|
31 |
+
*/
|
32 |
+
$(document).on( 'keyup', function() {
|
33 |
+
|
34 |
+
if( ! $('#wpsbc-uninstaller-confirmation').is(':visible') )
|
35 |
+
return false;
|
36 |
+
|
37 |
+
if( $('#wpsbc-uninstaller-confirmation-field').val() == 'REMOVE' )
|
38 |
+
$('#wpsbc-uninstaller-button').attr( 'disabled', false );
|
39 |
+
else
|
40 |
+
$('#wpsbc-uninstaller-button').attr( 'disabled', true );
|
41 |
+
|
42 |
+
});
|
43 |
+
|
44 |
+
});
|
assets/js/script-admin-upgrader.js
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery( function($) {
|
2 |
+
|
3 |
+
var loading_step = 0;
|
4 |
+
var total_steps = 4;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Handles the incrementation of the loading step and
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
function increment_loading_step() {
|
11 |
+
|
12 |
+
loading_step++;
|
13 |
+
|
14 |
+
// Increment the data-step
|
15 |
+
$('#wpsbc-upgrader-loading-bar-wrapper').attr( 'data-step', loading_step );
|
16 |
+
|
17 |
+
$('#wpsbc-upgrader-message-step-' + loading_step ).fadeOut( 200, function() {
|
18 |
+
$('#wpsbc-upgrader-message-doing-step-' + loading_step ).fadeIn( 200 );
|
19 |
+
} );
|
20 |
+
|
21 |
+
|
22 |
+
$('#wpsbc-upgrader-message-doing-step-' + ( loading_step - 1 ) ).fadeOut( 200, function() {
|
23 |
+
$('#wpsbc-upgrader-message-step-' + ( loading_step - 1 ) ).fadeIn( 200 );
|
24 |
+
} );
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Makes consecutive AJAX calls to migrate the old plugin data into the new format
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
function migrate_data( token ) {
|
34 |
+
|
35 |
+
if( typeof token == 'undefined' )
|
36 |
+
return false;
|
37 |
+
|
38 |
+
increment_loading_step();
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Finish migration if loading steps have been done
|
42 |
+
*
|
43 |
+
*/
|
44 |
+
if( loading_step - 1 == total_steps ) {
|
45 |
+
|
46 |
+
$('#wpsbc-upgrader-button-start-upgrade').remove();
|
47 |
+
$('#wpsbc-upgrader-button-continue').css( 'display', 'block' );
|
48 |
+
|
49 |
+
return false;
|
50 |
+
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Process migration step
|
55 |
+
*
|
56 |
+
*/
|
57 |
+
var action = '';
|
58 |
+
|
59 |
+
if( loading_step == 1 )
|
60 |
+
action = 'wpsbc_action_ajax_migrate_calendars';
|
61 |
+
|
62 |
+
if( loading_step == 2 )
|
63 |
+
action = 'wpsbc_action_ajax_migrate_bookings';
|
64 |
+
|
65 |
+
if( loading_step == 3 )
|
66 |
+
action = 'wpsbc_action_ajax_migrate_general_settings';
|
67 |
+
|
68 |
+
if( loading_step == 4 )
|
69 |
+
action = 'wpsbc_action_ajax_migrate_finishing_up';
|
70 |
+
|
71 |
+
if( action == '' )
|
72 |
+
return false;
|
73 |
+
|
74 |
+
var data = {
|
75 |
+
action : action,
|
76 |
+
token : token
|
77 |
+
}
|
78 |
+
|
79 |
+
$.post( ajaxurl, data, function( response ) {
|
80 |
+
|
81 |
+
response = JSON.parse( response );
|
82 |
+
|
83 |
+
if( response.success ) {
|
84 |
+
|
85 |
+
setTimeout( function() {
|
86 |
+
|
87 |
+
migrate_data( token );
|
88 |
+
|
89 |
+
}, 1000 );
|
90 |
+
|
91 |
+
}
|
92 |
+
|
93 |
+
});
|
94 |
+
|
95 |
+
}
|
96 |
+
|
97 |
+
|
98 |
+
/**
|
99 |
+
* Starts the upgrade procedure
|
100 |
+
*
|
101 |
+
*/
|
102 |
+
$(document).on( 'click', '#wpsbc-upgrader-button-start-upgrade', function(e) {
|
103 |
+
|
104 |
+
e.preventDefault();
|
105 |
+
|
106 |
+
$this = $(this);
|
107 |
+
|
108 |
+
if( $this.hasClass('disabled') )
|
109 |
+
return false;
|
110 |
+
|
111 |
+
// Disable the button
|
112 |
+
$this.addClass('disabled');
|
113 |
+
|
114 |
+
// Change the text of the button
|
115 |
+
$this.find('span:first-of-type').hide();
|
116 |
+
$this.find('span:nth-of-type(2)').show();
|
117 |
+
|
118 |
+
// Add and remove the spinner next to the button
|
119 |
+
$this.siblings( '.spinner' ).css( 'visibility', 'visible' );
|
120 |
+
|
121 |
+
setTimeout( function() {
|
122 |
+
$this.siblings( '.spinner' ).css( 'visibility', 'hidden' );
|
123 |
+
}, 1200 );
|
124 |
+
|
125 |
+
|
126 |
+
// Remove the copy text and show the loading bar
|
127 |
+
$('#wpsbc-upgrader-content-inner').delay( 1200 ).fadeOut( 300, function() {
|
128 |
+
|
129 |
+
$('#wpsbc-upgrader-loading-bar-wrapper').fadeIn( 300 );
|
130 |
+
|
131 |
+
});
|
132 |
+
|
133 |
+
// Remove the skip upgrader message
|
134 |
+
$('#wpsbc-upgrader-skip-wrapper').fadeOut( 300 );
|
135 |
+
|
136 |
+
// Get the token
|
137 |
+
var token = $('#wpsbc_token').val();
|
138 |
+
|
139 |
+
// Run the data migrator
|
140 |
+
setTimeout( function() {
|
141 |
+
|
142 |
+
migrate_data( token );
|
143 |
+
|
144 |
+
}, 1200 );
|
145 |
+
|
146 |
+
});
|
147 |
+
|
148 |
+
});
|
assets/js/script-admin.js
ADDED
@@ -0,0 +1,363 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
/*
|
4 |
+
* Strips one query argument from a given URL string
|
5 |
+
*
|
6 |
+
*/
|
7 |
+
function remove_query_arg(key, sourceURL) {
|
8 |
+
|
9 |
+
var rtn = sourceURL.split("?")[0],
|
10 |
+
param,
|
11 |
+
params_arr = [],
|
12 |
+
queryString = (sourceURL.indexOf("?") !== -1) ? sourceURL.split("?")[1] : "";
|
13 |
+
|
14 |
+
if (queryString !== "") {
|
15 |
+
params_arr = queryString.split("&");
|
16 |
+
for (var i = params_arr.length - 1; i >= 0; i -= 1) {
|
17 |
+
param = params_arr[i].split("=")[0];
|
18 |
+
if (param === key) {
|
19 |
+
params_arr.splice(i, 1);
|
20 |
+
}
|
21 |
+
}
|
22 |
+
|
23 |
+
rtn = rtn + "?" + params_arr.join("&");
|
24 |
+
|
25 |
+
}
|
26 |
+
|
27 |
+
if (rtn.split("?")[1] == "") {
|
28 |
+
rtn = rtn.split("?")[0];
|
29 |
+
}
|
30 |
+
|
31 |
+
return rtn;
|
32 |
+
}
|
33 |
+
|
34 |
+
|
35 |
+
/*
|
36 |
+
* Adds an argument name, value pair to a given URL string
|
37 |
+
*
|
38 |
+
*/
|
39 |
+
function add_query_arg(key, value, sourceURL) {
|
40 |
+
|
41 |
+
return sourceURL + '&' + key + '=' + value;
|
42 |
+
|
43 |
+
}
|
44 |
+
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Initialize colorpicker
|
48 |
+
*
|
49 |
+
*/
|
50 |
+
$('.wpsbc-colorpicker').wpColorPicker();
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Initialize Chosen
|
54 |
+
*
|
55 |
+
*/
|
56 |
+
if (typeof $.fn.chosen != 'undefined') {
|
57 |
+
|
58 |
+
$('.wpsbc-chosen').chosen();
|
59 |
+
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Links that have the inactive class should do nothing
|
64 |
+
*
|
65 |
+
*/
|
66 |
+
$(document).on('click', 'a.wpsbc-inactive, input[type=submit].wpsbc-inactive', function () {
|
67 |
+
|
68 |
+
return false;
|
69 |
+
|
70 |
+
});
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Initialize the sortable function on the Calendar Legend List Table
|
74 |
+
*
|
75 |
+
*/
|
76 |
+
$('table.wpsbc_legend_items tbody').sortable({
|
77 |
+
handle: '.wpsbc-move-legend-item',
|
78 |
+
containment: '#wpcontent',
|
79 |
+
placeholder: 'wpsbc-list-table-sort-placeholder',
|
80 |
+
helper: function (e, tr) {
|
81 |
+
var $originals = tr.children();
|
82 |
+
var $helper = tr.clone();
|
83 |
+
|
84 |
+
$helper.children().each(function (index) {
|
85 |
+
// Set helper cell sizes to match the original sizes
|
86 |
+
$(this).width($originals.eq(index).width());
|
87 |
+
});
|
88 |
+
|
89 |
+
return $helper;
|
90 |
+
},
|
91 |
+
update: function (e, ui) {
|
92 |
+
|
93 |
+
var legend_item_ids = [];
|
94 |
+
|
95 |
+
$('table.wpsbc_legend_items tbody tr .wpsbc-move-legend-item').each(function () {
|
96 |
+
legend_item_ids.push($(this).data('id'));
|
97 |
+
})
|
98 |
+
|
99 |
+
var data = {
|
100 |
+
action: 'wpsbc_sort_legend_items',
|
101 |
+
token: $('[name="wpsbc_token"]').val(),
|
102 |
+
calendar_id: $('[name="calendar_id"]').val(),
|
103 |
+
legend_item_ids: legend_item_ids
|
104 |
+
}
|
105 |
+
|
106 |
+
// Add table wrapper and overlay
|
107 |
+
$('table.wpsbc_legend_items').wrap('<div class="wpsbc-wp-list-table-wrapper"></div>');
|
108 |
+
$('table.wpsbc_legend_items').closest('.wpsbc-wp-list-table-wrapper').append('<div class="wpsbc-overlay"><div class="spinner"></div></div>');
|
109 |
+
|
110 |
+
// Make sort ajax call
|
111 |
+
$.post(ajaxurl, data, function (response) {
|
112 |
+
|
113 |
+
response = JSON.parse(response);
|
114 |
+
|
115 |
+
if (!response.success) {
|
116 |
+
|
117 |
+
window.location.replace(response.redirect_url_error);
|
118 |
+
|
119 |
+
} else {
|
120 |
+
|
121 |
+
// Remove table wrapper and overlay
|
122 |
+
$('table.wpsbc_legend_items').siblings('.wpsbc-overlay').remove();
|
123 |
+
$('table.wpsbc_legend_items').unwrap('.wpsbc-wp-list-table-wrapper');
|
124 |
+
|
125 |
+
}
|
126 |
+
|
127 |
+
|
128 |
+
});
|
129 |
+
|
130 |
+
}
|
131 |
+
});
|
132 |
+
|
133 |
+
$('table.wpsbc_legend_items tbody').disableSelection();
|
134 |
+
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Handle show/hide of the second color option for Legend Item add/edit screen
|
138 |
+
*
|
139 |
+
*/
|
140 |
+
$(document).on('change', 'select[name="legend_item_type"]', function () {
|
141 |
+
|
142 |
+
if ($(this).val() == 'single')
|
143 |
+
$('#wpsbc-legend-item-color-2').closest('.wp-picker-container').hide();
|
144 |
+
else
|
145 |
+
$('#wpsbc-legend-item-color-2').closest('.wp-picker-container').show();
|
146 |
+
|
147 |
+
});
|
148 |
+
|
149 |
+
$(document).ready(function () {
|
150 |
+
|
151 |
+
if ($('select[name="legend_item_type"]').length > 0)
|
152 |
+
$('select[name="legend_item_type"]').trigger('change');
|
153 |
+
|
154 |
+
});
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Tab Navigation
|
158 |
+
*
|
159 |
+
*/
|
160 |
+
$('.wpsbc-nav-tab').on('click', function (e) {
|
161 |
+
e.preventDefault();
|
162 |
+
|
163 |
+
// Nav Tab activation
|
164 |
+
$('.wpsbc-nav-tab').removeClass('wpsbc-active').removeClass('nav-tab-active');
|
165 |
+
$(this).addClass('wpsbc-active').addClass('nav-tab-active');
|
166 |
+
|
167 |
+
// Show tab
|
168 |
+
$('.wpsbc-tab').removeClass('wpsbc-active');
|
169 |
+
|
170 |
+
var nav_tab = $(this).attr('data-tab');
|
171 |
+
$('.wpsbc-tab[data-tab="' + nav_tab + '"]').addClass('wpsbc-active');
|
172 |
+
$('input[name=active_tab]').val(nav_tab);
|
173 |
+
|
174 |
+
// Change http referrer
|
175 |
+
$_wp_http_referer = $('input[name=_wp_http_referer]');
|
176 |
+
|
177 |
+
var _wp_http_referer = $_wp_http_referer.val();
|
178 |
+
_wp_http_referer = remove_query_arg('tab', _wp_http_referer);
|
179 |
+
$_wp_http_referer.val(add_query_arg('tab', $(this).attr('data-tab'), _wp_http_referer));
|
180 |
+
|
181 |
+
});
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Calendar Title Translations Toggle
|
185 |
+
*/
|
186 |
+
$(".wrap.wpsbc-wrap-edit-calendar #titlediv .titlewrap-toggle").click(function (e) {
|
187 |
+
e.preventDefault();
|
188 |
+
$(this).toggleClass('open');
|
189 |
+
$(".titlewrap-translations").slideToggle();
|
190 |
+
|
191 |
+
});
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Toggle settings translations
|
195 |
+
*
|
196 |
+
*/
|
197 |
+
$(".wpsbc-wrap").on('click', '.wpsbc-settings-field-show-translations', function (e) {
|
198 |
+
e.preventDefault();
|
199 |
+
$(this).parents('.wpsbc-settings-field-translation-wrapper').find(".wpsbc-settings-field-translations").slideToggle();
|
200 |
+
$(this).toggleClass('open');
|
201 |
+
})
|
202 |
+
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Modifies the modal inner height to permit the scrollbar to function properly
|
206 |
+
*
|
207 |
+
*/
|
208 |
+
$(window).resize(function () {
|
209 |
+
|
210 |
+
$('.wpsbc-modal-inner').outerHeight($('.wpsbc-modal.wpsbc-active').outerHeight() - $('.wpsbc-modal.wpsbc-active .wpsbc-modal-header').outerHeight() - $('.wpsbc-modal.wpsbc-active .wpsbc-modal-nav-tab-wrapper').outerHeight());
|
211 |
+
|
212 |
+
});
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Close modal window
|
216 |
+
*
|
217 |
+
*/
|
218 |
+
$(document).on('click', '.wpsbc-modal-close', function (e) {
|
219 |
+
|
220 |
+
e.preventDefault();
|
221 |
+
|
222 |
+
$(this).closest('.wpsbc-modal').find('.wpsbc-modal-inner').scrollTop(0);
|
223 |
+
|
224 |
+
$(this).closest('.wpsbc-modal').removeClass('wpsbc-active');
|
225 |
+
$(this).closest('.wpsbc-modal').siblings('.wpsbc-modal-overlay').removeClass('wpsbc-active');
|
226 |
+
|
227 |
+
$(window).resize();
|
228 |
+
|
229 |
+
});
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Close modal on clicking the modal overlay
|
233 |
+
*
|
234 |
+
*/
|
235 |
+
$(document).on('click', '.wpsbc-modal-overlay.wpsbc-active', function (e) {
|
236 |
+
|
237 |
+
$('.wpsbc-modal.wpsbc-active').find('.wpsbc-modal-close').click();
|
238 |
+
|
239 |
+
});
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Open Shortcode Generator modal
|
243 |
+
*
|
244 |
+
*/
|
245 |
+
$(document).on('click', '#wpsbc-shortcode-generator-button', function (e) {
|
246 |
+
|
247 |
+
e.preventDefault();
|
248 |
+
|
249 |
+
$('#wpsbc-modal-add-calendar-shortcode, #wpsbc-modal-add-calendar-shortcode-overlay').addClass('wpsbc-active');
|
250 |
+
|
251 |
+
$(window).resize();
|
252 |
+
|
253 |
+
$('.wpsbc-modal.wpsbc-active').click();
|
254 |
+
|
255 |
+
});
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Builds the shortcode for the Single Calendar and inserts it in the WordPress text editor
|
259 |
+
*
|
260 |
+
*/
|
261 |
+
$(document).on('click', '#wpsbc-insert-shortcode-single-calendar', function (e) {
|
262 |
+
|
263 |
+
e.preventDefault();
|
264 |
+
|
265 |
+
// Begin shortcode
|
266 |
+
var shortcode = '[wpsbc ';
|
267 |
+
|
268 |
+
$('#wpsbc-modal-add-calendar-shortcode.wpsbc-active .wpsbc-shortcode-generator-field-calendar').each(function () {
|
269 |
+
|
270 |
+
shortcode += $(this).data('attribute') + '="' + $(this).val() + '" ';
|
271 |
+
|
272 |
+
});
|
273 |
+
|
274 |
+
// End shortcode
|
275 |
+
shortcode = shortcode.trim();
|
276 |
+
shortcode += ']';
|
277 |
+
|
278 |
+
window.send_to_editor(shortcode);
|
279 |
+
|
280 |
+
$(this).closest('.wpsbc-modal').find('.wpsbc-modal-close').first().trigger('click');
|
281 |
+
|
282 |
+
});
|
283 |
+
|
284 |
+
|
285 |
+
/**
|
286 |
+
* Register and deregister website functionality
|
287 |
+
*
|
288 |
+
*/
|
289 |
+
$(document).on('click', '#wpsbc-register-website-button, #wpsbc-deregister-website-button', function (e) {
|
290 |
+
|
291 |
+
e.preventDefault();
|
292 |
+
|
293 |
+
window.location = add_query_arg('serial_key', $('[name="serial_key"]').val(), $(this).attr('href'));
|
294 |
+
|
295 |
+
});
|
296 |
+
|
297 |
+
$(document).on('click', '#wpsbc-check-for-updates-button', function (e) {
|
298 |
+
|
299 |
+
if ($(this).attr('disabled') == 'disabled')
|
300 |
+
e.preventDefault();
|
301 |
+
|
302 |
+
});
|
303 |
+
|
304 |
+
/**
|
305 |
+
* Move the calendar from the sidebar to the main content and back in the calendar edit screen
|
306 |
+
* when resizing the window
|
307 |
+
*
|
308 |
+
*/
|
309 |
+
$(window).on('resize', function () {
|
310 |
+
|
311 |
+
// Move the calendar from the sidebar to the main content
|
312 |
+
if ($(window).innerWidth() < 850) {
|
313 |
+
|
314 |
+
$('.wpsbc-container').closest('.postbox').detach().prependTo('#post-body-content');
|
315 |
+
|
316 |
+
} else {
|
317 |
+
|
318 |
+
$('.wpsbc-container').closest('.postbox').detach().prependTo('#postbox-container-1');
|
319 |
+
|
320 |
+
}
|
321 |
+
|
322 |
+
});
|
323 |
+
|
324 |
+
$(window).trigger('resize');
|
325 |
+
|
326 |
+
|
327 |
+
/**
|
328 |
+
* iCalendar Export warning message
|
329 |
+
*
|
330 |
+
*/
|
331 |
+
$("#ical-export-legend-items").change(function () {
|
332 |
+
if ($(this).find('option:selected').length > 1) {
|
333 |
+
$(this).siblings('.wpsbc-warning').show();
|
334 |
+
} else {
|
335 |
+
$(this).siblings('.wpsbc-warning').hide();
|
336 |
+
}
|
337 |
+
}).trigger('change');
|
338 |
+
|
339 |
+
jQuery(window).on('load resize', function () {
|
340 |
+
jQuery(".wpsbc-wrap-upgrade-to-premium ul li").wpsbc_adjust_height();
|
341 |
+
})
|
342 |
+
|
343 |
+
});
|
344 |
+
|
345 |
+
/***** Adjust Height Function *****/
|
346 |
+
jQuery.fn.wpsbc_adjust_height = function () {
|
347 |
+
var maxHeightFound = 0;
|
348 |
+
this.css('min-height', '1px');
|
349 |
+
|
350 |
+
if (this.is('a')) {
|
351 |
+
this.removeClass('loaded');
|
352 |
+
};
|
353 |
+
|
354 |
+
this.each(function () {
|
355 |
+
if (jQuery(this).outerHeight() > maxHeightFound) {
|
356 |
+
maxHeightFound = jQuery(this).outerHeight();
|
357 |
+
}
|
358 |
+
});
|
359 |
+
this.css('min-height', maxHeightFound);
|
360 |
+
if (this.is('a')) {
|
361 |
+
this.addClass('loaded');
|
362 |
+
};
|
363 |
+
};
|
assets/js/script-front-end.js
ADDED
@@ -0,0 +1,283 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Resizes the calendar to always have square dates
|
5 |
+
*
|
6 |
+
*/
|
7 |
+
function resize_calendar($calendars_wrapper) {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Set variables
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
var $months_wrapper = $calendars_wrapper.find('.wpsbc-calendars-wrapper');
|
14 |
+
var $months_wrapper_width = $calendars_wrapper.find('.wpsbc-calendars');
|
15 |
+
var calendar_min_width = $calendars_wrapper.data('min_width');
|
16 |
+
var calendar_max_width = $calendars_wrapper.data('max_width');
|
17 |
+
|
18 |
+
var $month_inner = $calendars_wrapper.find('.wpsbc-calendar-wrapper');
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Set the calendar months min and max width from the data attributes
|
22 |
+
*
|
23 |
+
*/
|
24 |
+
if ($calendars_wrapper.data('min_width') > 0)
|
25 |
+
$calendars_wrapper.find('.wpsbc-calendar').css('min-width', calendar_min_width);
|
26 |
+
|
27 |
+
if ($calendars_wrapper.data('max_width') > 0)
|
28 |
+
$calendars_wrapper.find('.wpsbc-calendar').css('max-width', calendar_max_width)
|
29 |
+
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Set the column count
|
33 |
+
*
|
34 |
+
*/
|
35 |
+
var column_count = 0;
|
36 |
+
|
37 |
+
if ($months_wrapper_width.width() < calendar_min_width * 2)
|
38 |
+
column_count = 1;
|
39 |
+
|
40 |
+
else if ($months_wrapper_width.width() < calendar_min_width * 3)
|
41 |
+
column_count = 2;
|
42 |
+
|
43 |
+
else if ($months_wrapper_width.width() < calendar_min_width * 4)
|
44 |
+
column_count = 3;
|
45 |
+
|
46 |
+
else if ($months_wrapper_width.width() < calendar_min_width * 6)
|
47 |
+
column_count = 4;
|
48 |
+
|
49 |
+
else
|
50 |
+
column_count = 6;
|
51 |
+
|
52 |
+
|
53 |
+
// Adjust for when there are fewer months in a calendar than columns
|
54 |
+
if ($calendars_wrapper.find('.wpsbc-calendar').length <= column_count)
|
55 |
+
column_count = $calendars_wrapper.find('.wpsbc-calendar').length;
|
56 |
+
|
57 |
+
// Set column count
|
58 |
+
$calendars_wrapper.attr('data-columns', column_count);
|
59 |
+
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Set the max-width of the calendars container that has a side legend
|
63 |
+
*
|
64 |
+
*/
|
65 |
+
if ($months_wrapper.hasClass('wpsbc-legend-position-side')) {
|
66 |
+
|
67 |
+
$months_wrapper.css('max-width', 'none');
|
68 |
+
$months_wrapper.css('max-width', $calendars_wrapper.find('.wpsbc-calendar').first().outerWidth(true) * column_count);
|
69 |
+
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Handle the height of each date
|
75 |
+
*
|
76 |
+
*/
|
77 |
+
var td_width = $calendars_wrapper.find('td').first().width();
|
78 |
+
|
79 |
+
$calendars_wrapper.find('td .wpsbc-date-inner, td .wpsbc-week-number').css('height', Math.ceil(td_width) + 1 + 'px');
|
80 |
+
$calendars_wrapper.find('td .wpsbc-date-inner, td .wpsbc-week-number').css('line-height', Math.ceil(td_width) + 1 + 'px');
|
81 |
+
|
82 |
+
var th_height = $calendars_wrapper.find('th').css('height', 'auto').first().height();
|
83 |
+
$calendars_wrapper.find('th').css('height', Math.ceil(th_height) + 1 + 'px');
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Set calendar month height
|
87 |
+
*
|
88 |
+
*/
|
89 |
+
var calendar_month_height = 0;
|
90 |
+
|
91 |
+
$month_inner.css('min-height', '1px');
|
92 |
+
|
93 |
+
$month_inner.each(function () {
|
94 |
+
|
95 |
+
if ($(this).height() >= calendar_month_height)
|
96 |
+
calendar_month_height = $(this).height();
|
97 |
+
|
98 |
+
});
|
99 |
+
|
100 |
+
$month_inner.css('min-height', Math.ceil(calendar_month_height) + 'px');
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Show the calendars
|
104 |
+
*
|
105 |
+
*/
|
106 |
+
$calendars_wrapper.css('visibility', 'visible');
|
107 |
+
|
108 |
+
}
|
109 |
+
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Refreshed the output of the calendar with the given data
|
113 |
+
*
|
114 |
+
*/
|
115 |
+
function refresh_calendar($calendar_container, current_year, current_month) {
|
116 |
+
|
117 |
+
var $calendar_container = $calendar_container;
|
118 |
+
|
119 |
+
if ($calendar_container.hasClass('wpsbc-is-loading'))
|
120 |
+
return false;
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Prepare the calendar data
|
124 |
+
*
|
125 |
+
*/
|
126 |
+
var data = $calendar_container.data();
|
127 |
+
|
128 |
+
data['action'] = 'wpsbc_refresh_calendar';
|
129 |
+
data['current_year'] = current_year;
|
130 |
+
data['current_month'] = current_month;
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Add loading animation
|
134 |
+
*
|
135 |
+
*/
|
136 |
+
$calendar_container.find('.wpsbc-calendar').append('<div class="wpsbc-overlay"><div class="wpsbc-overlay-spinner"><div class="wpsbc-overlay-bounce1"></div><div class="wpsbc-overlay-bounce2"></div><div class="wpsbc-overlay-bounce3"></div></div></div>');
|
137 |
+
$calendar_container.addClass('wpsbc-is-loading');
|
138 |
+
$calendar_container.find('select').attr('disabled', true);
|
139 |
+
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Make the request
|
143 |
+
*
|
144 |
+
*/
|
145 |
+
$.post(wpsbc.ajax_url, data, function (response) {
|
146 |
+
|
147 |
+
$calendar_container.replaceWith(response);
|
148 |
+
|
149 |
+
$('.wpsbc-container').each(function () {
|
150 |
+
resize_calendar($(this));
|
151 |
+
});
|
152 |
+
|
153 |
+
});
|
154 |
+
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* Resize the calendars on page load
|
159 |
+
*
|
160 |
+
*/
|
161 |
+
$('.wpsbc-container').each(function () {
|
162 |
+
resize_calendar($(this));
|
163 |
+
});
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Resize the calendars on page resize
|
167 |
+
*
|
168 |
+
*/
|
169 |
+
$(window).on('resize', function () {
|
170 |
+
|
171 |
+
$('.wpsbc-container').each(function () {
|
172 |
+
resize_calendar($(this));
|
173 |
+
});
|
174 |
+
|
175 |
+
});
|
176 |
+
|
177 |
+
|
178 |
+
/**
|
179 |
+
* Handles the navigation of the Previous button
|
180 |
+
*
|
181 |
+
*/
|
182 |
+
$(document).on('click', '.wpsbc-container .wpsbc-prev', function (e) {
|
183 |
+
|
184 |
+
e.preventDefault();
|
185 |
+
|
186 |
+
// Set container
|
187 |
+
var $container = $(this).closest('.wpsbc-container');
|
188 |
+
|
189 |
+
// Set the current year and month that are displayed in the calendar
|
190 |
+
var current_month = $container.data('current_month');
|
191 |
+
var current_year = $container.data('current_year');
|
192 |
+
|
193 |
+
current_month -= 1;
|
194 |
+
|
195 |
+
if (current_month < 1) {
|
196 |
+
current_month = 12;
|
197 |
+
current_year -= 1;
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
refresh_calendar($container, current_year, current_month);
|
202 |
+
|
203 |
+
});
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Handles the navigation of the Next button
|
207 |
+
*
|
208 |
+
*/
|
209 |
+
$(document).on('click', '.wpsbc-container .wpsbc-next', function (e) {
|
210 |
+
|
211 |
+
e.preventDefault();
|
212 |
+
|
213 |
+
// Set container
|
214 |
+
var $container = $(this).closest('.wpsbc-container');
|
215 |
+
|
216 |
+
// Set the current year and month that are displayed in the calendar
|
217 |
+
var current_month = $container.data('current_month');
|
218 |
+
var current_year = $container.data('current_year');
|
219 |
+
|
220 |
+
current_month += 1;
|
221 |
+
|
222 |
+
if (current_month > 12) {
|
223 |
+
current_month = 1;
|
224 |
+
current_year += 1;
|
225 |
+
}
|
226 |
+
|
227 |
+
refresh_calendar($container, current_year, current_month);
|
228 |
+
|
229 |
+
});
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Handles the navigation of the Month Selector for the Single Calendar
|
233 |
+
*
|
234 |
+
*/
|
235 |
+
$(document).on('change', '.wpsbc-container .wpsbc-select-container select', function () {
|
236 |
+
|
237 |
+
// Set container
|
238 |
+
var $container = $(this).closest('.wpsbc-container');
|
239 |
+
|
240 |
+
var date = new Date($(this).val() * 1000);
|
241 |
+
|
242 |
+
var year = date.getFullYear();
|
243 |
+
var month = date.getMonth() + 1;
|
244 |
+
|
245 |
+
refresh_calendar($container, year, month);
|
246 |
+
|
247 |
+
});
|
248 |
+
|
249 |
+
|
250 |
+
|
251 |
+
/**
|
252 |
+
* Check if a calendar is hidden and wait for it to become visible.
|
253 |
+
* When it does, trigger a window resize to properly display the calendar.
|
254 |
+
*
|
255 |
+
*/
|
256 |
+
var wpsbc_frontend_visible_calendars = $('.wpsbc-container:visible').length;
|
257 |
+
function wpsbc_check_if_calendar_is_visible() {
|
258 |
+
|
259 |
+
// If no calendars are embedded, exit
|
260 |
+
if (!$('.wpsbc-container').length)
|
261 |
+
return false;
|
262 |
+
|
263 |
+
// If a calendar just became visible, trigger a resize
|
264 |
+
if (wpsbc_frontend_visible_calendars != $('.wpsbc-container:visible').length) {
|
265 |
+
$(window).trigger('resize');
|
266 |
+
wpsbc_frontend_visible_calendars = $('.wpsbc-container:visible').length;
|
267 |
+
}
|
268 |
+
|
269 |
+
// If all calendars are visible, exit
|
270 |
+
if ($('.wpsbc-container:visible').length == $('.wpsbc-container').length) {
|
271 |
+
return false;
|
272 |
+
}
|
273 |
+
|
274 |
+
// Keep checking every 250ms
|
275 |
+
setTimeout(wpsbc_check_if_calendar_is_visible, 250);
|
276 |
+
|
277 |
+
}
|
278 |
+
// Manually start the first check
|
279 |
+
wpsbc_check_if_calendar_is_visible();
|
280 |
+
|
281 |
+
});
|
282 |
+
|
283 |
+
|
assets/js/script-front-end.min.js
ADDED
@@ -0,0 +1 @@
|
|
|
1 |
+
jQuery((function($){function resize_calendar($calendars_wrapper){var $months_wrapper=$calendars_wrapper.find(".wpsbc-calendars-wrapper"),$months_wrapper_width=$calendars_wrapper.find(".wpsbc-calendars"),calendar_min_width=$calendars_wrapper.data("min_width"),calendar_max_width=$calendars_wrapper.data("max_width"),$month_inner=$calendars_wrapper.find(".wpsbc-calendar-wrapper");$calendars_wrapper.data("min_width")>0&&$calendars_wrapper.find(".wpsbc-calendar").css("min-width",calendar_min_width),$calendars_wrapper.data("max_width")>0&&$calendars_wrapper.find(".wpsbc-calendar").css("max-width",calendar_max_width);var column_count=0;column_count=$months_wrapper_width.width()<2*calendar_min_width?1:$months_wrapper_width.width()<3*calendar_min_width?2:$months_wrapper_width.width()<4*calendar_min_width?3:$months_wrapper_width.width()<6*calendar_min_width?4:6,$calendars_wrapper.find(".wpsbc-calendar").length<=column_count&&(column_count=$calendars_wrapper.find(".wpsbc-calendar").length),$calendars_wrapper.attr("data-columns",column_count),$months_wrapper.hasClass("wpsbc-legend-position-side")&&($months_wrapper.css("max-width","none"),$months_wrapper.css("max-width",$calendars_wrapper.find(".wpsbc-calendar").first().outerWidth(!0)*column_count));var td_width=$calendars_wrapper.find("td").first().width();$calendars_wrapper.find("td .wpsbc-date-inner, td .wpsbc-week-number").css("height",Math.ceil(td_width)+1+"px"),$calendars_wrapper.find("td .wpsbc-date-inner, td .wpsbc-week-number").css("line-height",Math.ceil(td_width)+1+"px");var th_height=$calendars_wrapper.find("th").css("height","auto").first().height();$calendars_wrapper.find("th").css("height",Math.ceil(th_height)+1+"px");var calendar_month_height=0;$month_inner.css("min-height","1px"),$month_inner.each((function(){$(this).height()>=calendar_month_height&&(calendar_month_height=$(this).height())})),$month_inner.css("min-height",Math.ceil(calendar_month_height)+"px"),$calendars_wrapper.css("visibility","visible")}function refresh_calendar($calendar_container,current_year,current_month){var $calendar_container;if(($calendar_container=$calendar_container).hasClass("wpsbc-is-loading"))return!1;var data=$calendar_container.data();data.action="wpsbc_refresh_calendar",data.current_year=current_year,data.current_month=current_month,$calendar_container.find(".wpsbc-calendar").append('<div class="wpsbc-overlay"><div class="wpsbc-overlay-spinner"><div class="wpsbc-overlay-bounce1"></div><div class="wpsbc-overlay-bounce2"></div><div class="wpsbc-overlay-bounce3"></div></div></div>'),$calendar_container.addClass("wpsbc-is-loading"),$calendar_container.find("select").attr("disabled",!0),$.post(wpsbc.ajax_url,data,(function(response){$calendar_container.replaceWith(response),$(".wpsbc-container").each((function(){resize_calendar($(this))}))}))}$(".wpsbc-container").each((function(){resize_calendar($(this))})),$(window).on("resize",(function(){$(".wpsbc-container").each((function(){resize_calendar($(this))}))})),$(document).on("click",".wpsbc-container .wpsbc-prev",(function(e){e.preventDefault();var $container=$(this).closest(".wpsbc-container"),current_month=$container.data("current_month"),current_year=$container.data("current_year");(current_month-=1)<1&&(current_month=12,current_year-=1),refresh_calendar($container,current_year,current_month)})),$(document).on("click",".wpsbc-container .wpsbc-next",(function(e){e.preventDefault();var $container=$(this).closest(".wpsbc-container"),current_month=$container.data("current_month"),current_year=$container.data("current_year");(current_month+=1)>12&&(current_month=1,current_year+=1),refresh_calendar($container,current_year,current_month)})),$(document).on("change",".wpsbc-container .wpsbc-select-container select",(function(){var $container=$(this).closest(".wpsbc-container"),date=new Date(1e3*$(this).val()),year,month;refresh_calendar($container,date.getFullYear(),date.getMonth()+1)}));var wpsbc_frontend_visible_calendars=$(".wpsbc-container:visible").length;function wpsbc_check_if_calendar_is_visible(){return!!$(".wpsbc-container").length&&(wpsbc_frontend_visible_calendars!=$(".wpsbc-container:visible").length&&($(window).trigger("resize"),wpsbc_frontend_visible_calendars=$(".wpsbc-container:visible").length),$(".wpsbc-container:visible").length!=$(".wpsbc-container").length&&void setTimeout(wpsbc_check_if_calendar_is_visible,250))}wpsbc_check_if_calendar_is_visible()}));
|
assets/libs/chosen/chosen-sprite.png
ADDED
Binary file
|
assets/libs/chosen/chosen-sprite@2x.png
ADDED
Binary file
|
assets/libs/chosen/chosen.css
ADDED
@@ -0,0 +1,448 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/*!
|
2 |
+
Chosen, a Select Box Enhancer for jQuery and Prototype
|
3 |
+
by Patrick Filler for Harvest, http://getharvest.com
|
4 |
+
|
5 |
+
Version 1.5.1
|
6 |
+
Full source at https://github.com/harvesthq/chosen
|
7 |
+
Copyright (c) 2011-2016 Harvest http://getharvest.com
|
8 |
+
|
9 |
+
MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
|
10 |
+
This file is generated by `grunt build`, do not edit it by hand.
|
11 |
+
*/
|
12 |
+
|
13 |
+
/* @group Base */
|
14 |
+
.chosen-container {
|
15 |
+
position: relative;
|
16 |
+
display: inline-block;
|
17 |
+
vertical-align: middle;
|
18 |
+
font-size: 13px;
|
19 |
+
-webkit-user-select: none;
|
20 |
+
-moz-user-select: none;
|
21 |
+
user-select: none;
|
22 |
+
}
|
23 |
+
.chosen-container * {
|
24 |
+
-webkit-box-sizing: border-box;
|
25 |
+
-moz-box-sizing: border-box;
|
26 |
+
box-sizing: border-box;
|
27 |
+
}
|
28 |
+
.chosen-container .chosen-drop {
|
29 |
+
position: absolute;
|
30 |
+
top: 100%;
|
31 |
+
left: -9999px;
|
32 |
+
z-index: 1010;
|
33 |
+
width: 100%;
|
34 |
+
border: 1px solid #aaa;
|
35 |
+
border-top: 0;
|
36 |
+
background: #fff;
|
37 |
+
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
|
38 |
+
}
|
39 |
+
.chosen-container.chosen-with-drop .chosen-drop {
|
40 |
+
left: 0;
|
41 |
+
}
|
42 |
+
.chosen-container a {
|
43 |
+
cursor: pointer;
|
44 |
+
}
|
45 |
+
.chosen-container .search-choice .group-name, .chosen-container .chosen-single .group-name {
|
46 |
+
margin-right: 4px;
|
47 |
+
overflow: hidden;
|
48 |
+
white-space: nowrap;
|
49 |
+
text-overflow: ellipsis;
|
50 |
+
font-weight: normal;
|
51 |
+
color: #999999;
|
52 |
+
}
|
53 |
+
.chosen-container .search-choice .group-name:after, .chosen-container .chosen-single .group-name:after {
|
54 |
+
content: ":";
|
55 |
+
padding-left: 2px;
|
56 |
+
vertical-align: top;
|
57 |
+
}
|
58 |
+
|
59 |
+
/* @end */
|
60 |
+
/* @group Single Chosen */
|
61 |
+
.chosen-container-single .chosen-single {
|
62 |
+
position: relative;
|
63 |
+
display: block;
|
64 |
+
overflow: hidden;
|
65 |
+
padding: 0 0 0 8px;
|
66 |
+
height: 25px;
|
67 |
+
border: 1px solid #aaa;
|
68 |
+
border-radius: 5px;
|
69 |
+
background-color: #fff;
|
70 |
+
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
|
71 |
+
background: -webkit-linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
72 |
+
background: -moz-linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
73 |
+
background: -o-linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
74 |
+
background: linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
|
75 |
+
background-clip: padding-box;
|
76 |
+
box-shadow: 0 0 3px white inset, 0 1px 1px rgba(0, 0, 0, 0.1);
|
77 |
+
color: #444;
|
78 |
+
text-decoration: none;
|
79 |
+
white-space: nowrap;
|
80 |
+
line-height: 24px;
|
81 |
+
}
|
82 |
+
.chosen-container-single .chosen-default {
|
83 |
+
color: #999;
|
84 |
+
}
|
85 |
+
.chosen-container-single .chosen-single span {
|
86 |
+
display: block;
|
87 |
+
overflow: hidden;
|
88 |
+
margin-right: 26px;
|
89 |
+
text-overflow: ellipsis;
|
90 |
+
white-space: nowrap;
|
91 |
+
}
|
92 |
+
.chosen-container-single .chosen-single-with-deselect span {
|
93 |
+
margin-right: 38px;
|
94 |
+
}
|
95 |
+
.chosen-container-single .chosen-single abbr {
|
96 |
+
position: absolute;
|
97 |
+
top: 6px;
|
98 |
+
right: 26px;
|
99 |
+
display: block;
|
100 |
+
width: 12px;
|
101 |
+
height: 12px;
|
102 |
+
background: url('chosen-sprite.png') -42px 1px no-repeat;
|
103 |
+
font-size: 1px;
|
104 |
+
}
|
105 |
+
.chosen-container-single .chosen-single abbr:hover {
|
106 |
+
background-position: -42px -10px;
|
107 |
+
}
|
108 |
+
.chosen-container-single.chosen-disabled .chosen-single abbr:hover {
|
109 |
+
background-position: -42px -10px;
|
110 |
+
}
|
111 |
+
.chosen-container-single .chosen-single div {
|
112 |
+
position: absolute;
|
113 |
+
top: 0;
|
114 |
+
right: 0;
|
115 |
+
display: block;
|
116 |
+
width: 18px;
|
117 |
+
height: 100%;
|
118 |
+
}
|
119 |
+
.chosen-container-single .chosen-single div b {
|
120 |
+
display: block;
|
121 |
+
width: 100%;
|
122 |
+
height: 100%;
|
123 |
+
background: url('chosen-sprite.png') no-repeat 0px 2px;
|
124 |
+
}
|
125 |
+
.chosen-container-single .chosen-search {
|
126 |
+
position: relative;
|
127 |
+
z-index: 1010;
|
128 |
+
margin: 0;
|
129 |
+
padding: 3px 4px;
|
130 |
+
white-space: nowrap;
|
131 |
+
}
|
132 |
+
.chosen-container-single .chosen-search input[type="text"] {
|
133 |
+
margin: 1px 0;
|
134 |
+
padding: 4px 20px 4px 5px;
|
135 |
+
width: 100%;
|
136 |
+
height: auto;
|
137 |
+
outline: 0;
|
138 |
+
border: 1px solid #aaa;
|
139 |
+
background: white url('chosen-sprite.png') no-repeat 100% -20px;
|
140 |
+
background: url('chosen-sprite.png') no-repeat 100% -20px;
|
141 |
+
font-size: 1em;
|
142 |
+
font-family: sans-serif;
|
143 |
+
line-height: normal;
|
144 |
+
border-radius: 0;
|
145 |
+
}
|
146 |
+
.chosen-container-single .chosen-drop {
|
147 |
+
margin-top: -1px;
|
148 |
+
border-radius: 0 0 4px 4px;
|
149 |
+
background-clip: padding-box;
|
150 |
+
}
|
151 |
+
.chosen-container-single.chosen-container-single-nosearch .chosen-search {
|
152 |
+
position: absolute;
|
153 |
+
left: -9999px;
|
154 |
+
}
|
155 |
+
|
156 |
+
/* @end */
|
157 |
+
/* @group Results */
|
158 |
+
.chosen-container .chosen-results {
|
159 |
+
color: #444;
|
160 |
+
position: relative;
|
161 |
+
overflow-x: hidden;
|
162 |
+
overflow-y: auto;
|
163 |
+
margin: 0 4px 4px 0;
|
164 |
+
padding: 0 0 0 4px;
|
165 |
+
max-height: 240px;
|
166 |
+
-webkit-overflow-scrolling: touch;
|
167 |
+
}
|
168 |
+
.chosen-container .chosen-results li {
|
169 |
+
display: none;
|
170 |
+
margin: 0;
|
171 |
+
padding: 5px 6px;
|
172 |
+
list-style: none;
|
173 |
+
line-height: 15px;
|
174 |
+
word-wrap: break-word;
|
175 |
+
-webkit-touch-callout: none;
|
176 |
+
}
|
177 |
+
.chosen-container .chosen-results li.active-result {
|
178 |
+
display: list-item;
|
179 |
+
cursor: pointer;
|
180 |
+
}
|
181 |
+
.chosen-container .chosen-results li.disabled-result {
|
182 |
+
display: list-item;
|
183 |
+
color: #ccc;
|
184 |
+
cursor: default;
|
185 |
+
}
|
186 |
+
.chosen-container .chosen-results li.highlighted {
|
187 |
+
background-color: #3875d7;
|
188 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
|
189 |
+
background-image: -webkit-linear-gradient(#3875d7 20%, #2a62bc 90%);
|
190 |
+
background-image: -moz-linear-gradient(#3875d7 20%, #2a62bc 90%);
|
191 |
+
background-image: -o-linear-gradient(#3875d7 20%, #2a62bc 90%);
|
192 |
+
background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
|
193 |
+
color: #fff;
|
194 |
+
}
|
195 |
+
.chosen-container .chosen-results li.no-results {
|
196 |
+
color: #777;
|
197 |
+
display: list-item;
|
198 |
+
background: #f4f4f4;
|
199 |
+
}
|
200 |
+
.chosen-container .chosen-results li.group-result {
|
201 |
+
display: list-item;
|
202 |
+
font-weight: bold;
|
203 |
+
cursor: default;
|
204 |
+
}
|
205 |
+
.chosen-container .chosen-results li.group-option {
|
206 |
+
padding-left: 15px;
|
207 |
+
}
|
208 |
+
.chosen-container .chosen-results li em {
|
209 |
+
font-style: normal;
|
210 |
+
text-decoration: underline;
|
211 |
+
}
|
212 |
+
|
213 |
+
/* @end */
|
214 |
+
/* @group Multi Chosen */
|
215 |
+
.chosen-container-multi .chosen-choices {
|
216 |
+
position: relative;
|
217 |
+
overflow: hidden;
|
218 |
+
margin: 0;
|
219 |
+
padding: 0 5px;
|
220 |
+
width: 100%;
|
221 |
+
height: auto !important;
|
222 |
+
height: 1%;
|
223 |
+
border: 1px solid #aaa;
|
224 |
+
background-color: #fff;
|
225 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
|
226 |
+
background-image: -webkit-linear-gradient(#eeeeee 1%, #ffffff 15%);
|
227 |
+
background-image: -moz-linear-gradient(#eeeeee 1%, #ffffff 15%);
|
228 |
+
background-image: -o-linear-gradient(#eeeeee 1%, #ffffff 15%);
|
229 |
+
background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
|
230 |
+
cursor: text;
|
231 |
+
}
|
232 |
+
.chosen-container-multi .chosen-choices li {
|
233 |
+
float: left;
|
234 |
+
list-style: none;
|
235 |
+
}
|
236 |
+
.chosen-container-multi .chosen-choices li.search-field {
|
237 |
+
margin: 0;
|
238 |
+
padding: 0;
|
239 |
+
white-space: nowrap;
|
240 |
+
}
|
241 |
+
.chosen-container-multi .chosen-choices li.search-field input[type="text"] {
|
242 |
+
margin: 1px 0;
|
243 |
+
padding: 0;
|
244 |
+
height: 25px;
|
245 |
+
outline: 0;
|
246 |
+
border: 0 !important;
|
247 |
+
background: transparent !important;
|
248 |
+
box-shadow: none;
|
249 |
+
color: #999;
|
250 |
+
font-size: 100%;
|
251 |
+
font-family: sans-serif;
|
252 |
+
line-height: normal;
|
253 |
+
border-radius: 0;
|
254 |
+
}
|
255 |
+
.chosen-container-multi .chosen-choices li.search-choice {
|
256 |
+
position: relative;
|
257 |
+
margin: 3px 5px 3px 0;
|
258 |
+
padding: 3px 20px 3px 5px;
|
259 |
+
border: 1px solid #aaa;
|
260 |
+
max-width: 100%;
|
261 |
+
border-radius: 3px;
|
262 |
+
background-color: #eeeeee;
|
263 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
|
264 |
+
background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
265 |
+
background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
266 |
+
background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
267 |
+
background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
268 |
+
background-size: 100% 19px;
|
269 |
+
background-repeat: repeat-x;
|
270 |
+
background-clip: padding-box;
|
271 |
+
box-shadow: 0 0 2px white inset, 0 1px 0 rgba(0, 0, 0, 0.05);
|
272 |
+
color: #333;
|
273 |
+
line-height: 13px;
|
274 |
+
cursor: default;
|
275 |
+
}
|
276 |
+
.chosen-container-multi .chosen-choices li.search-choice span {
|
277 |
+
word-wrap: break-word;
|
278 |
+
}
|
279 |
+
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close {
|
280 |
+
position: absolute;
|
281 |
+
top: 4px;
|
282 |
+
right: 3px;
|
283 |
+
display: block;
|
284 |
+
width: 12px;
|
285 |
+
height: 12px;
|
286 |
+
background: url('chosen-sprite.png') -42px 1px no-repeat;
|
287 |
+
font-size: 1px;
|
288 |
+
}
|
289 |
+
.chosen-container-multi .chosen-choices li.search-choice .search-choice-close:hover {
|
290 |
+
background-position: -42px -10px;
|
291 |
+
}
|
292 |
+
.chosen-container-multi .chosen-choices li.search-choice-disabled {
|
293 |
+
padding-right: 5px;
|
294 |
+
border: 1px solid #ccc;
|
295 |
+
background-color: #e4e4e4;
|
296 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
|
297 |
+
background-image: -webkit-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
298 |
+
background-image: -moz-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
299 |
+
background-image: -o-linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
300 |
+
background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
|
301 |
+
color: #666;
|
302 |
+
}
|
303 |
+
.chosen-container-multi .chosen-choices li.search-choice-focus {
|
304 |
+
background: #d4d4d4;
|
305 |
+
}
|
306 |
+
.chosen-container-multi .chosen-choices li.search-choice-focus .search-choice-close {
|
307 |
+
background-position: -42px -10px;
|
308 |
+
}
|
309 |
+
.chosen-container-multi .chosen-results {
|
310 |
+
margin: 0;
|
311 |
+
padding: 0;
|
312 |
+
}
|
313 |
+
.chosen-container-multi .chosen-drop .result-selected {
|
314 |
+
display: list-item;
|
315 |
+
color: #ccc;
|
316 |
+
cursor: default;
|
317 |
+
}
|
318 |
+
|
319 |
+
/* @end */
|
320 |
+
/* @group Active */
|
321 |
+
.chosen-container-active .chosen-single {
|
322 |
+
border: 1px solid #5897fb;
|
323 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
324 |
+
}
|
325 |
+
.chosen-container-active.chosen-with-drop .chosen-single {
|
326 |
+
border: 1px solid #aaa;
|
327 |
+
-moz-border-radius-bottomright: 0;
|
328 |
+
border-bottom-right-radius: 0;
|
329 |
+
-moz-border-radius-bottomleft: 0;
|
330 |
+
border-bottom-left-radius: 0;
|
331 |
+
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
|
332 |
+
background-image: -webkit-linear-gradient(#eeeeee 20%, #ffffff 80%);
|
333 |
+
background-image: -moz-linear-gradient(#eeeeee 20%, #ffffff 80%);
|
334 |
+
background-image: -o-linear-gradient(#eeeeee 20%, #ffffff 80%);
|
335 |
+
background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
|
336 |
+
box-shadow: 0 1px 0 #fff inset;
|
337 |
+
}
|
338 |
+
.chosen-container-active.chosen-with-drop .chosen-single div {
|
339 |
+
border-left: none;
|
340 |
+
background: transparent;
|
341 |
+
}
|
342 |
+
.chosen-container-active.chosen-with-drop .chosen-single div b {
|
343 |
+
background-position: -18px 2px;
|
344 |
+
}
|
345 |
+
.chosen-container-active .chosen-choices {
|
346 |
+
border: 1px solid #5897fb;
|
347 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
348 |
+
}
|
349 |
+
.chosen-container-active .chosen-choices li.search-field input[type="text"] {
|
350 |
+
color: #222 !important;
|
351 |
+
}
|
352 |
+
|
353 |
+
/* @end */
|
354 |
+
/* @group Disabled Support */
|
355 |
+
.chosen-disabled {
|
356 |
+
opacity: 0.5 !important;
|
357 |
+
cursor: default;
|
358 |
+
}
|
359 |
+
.chosen-disabled .chosen-single {
|
360 |
+
cursor: default;
|
361 |
+
}
|
362 |
+
.chosen-disabled .chosen-choices .search-choice .search-choice-close {
|
363 |
+
cursor: default;
|
364 |
+
}
|
365 |
+
|
366 |
+
/* @end */
|
367 |
+
/* @group Right to Left */
|
368 |
+
.chosen-rtl {
|
369 |
+
text-align: right;
|
370 |
+
}
|
371 |
+
.chosen-rtl .chosen-single {
|
372 |
+
overflow: visible;
|
373 |
+
padding: 0 8px 0 0;
|
374 |
+
}
|
375 |
+
.chosen-rtl .chosen-single span {
|
376 |
+
margin-right: 0;
|
377 |
+
margin-left: 26px;
|
378 |
+
direction: rtl;
|
379 |
+
}
|
380 |
+
.chosen-rtl .chosen-single-with-deselect span {
|
381 |
+
margin-left: 38px;
|
382 |
+
}
|
383 |
+
.chosen-rtl .chosen-single div {
|
384 |
+
right: auto;
|
385 |
+
left: 3px;
|
386 |
+
}
|
387 |
+
.chosen-rtl .chosen-single abbr {
|
388 |
+
right: auto;
|
389 |
+
left: 26px;
|
390 |
+
}
|
391 |
+
.chosen-rtl .chosen-choices li {
|
392 |
+
float: right;
|
393 |
+
}
|
394 |
+
.chosen-rtl .chosen-choices li.search-field input[type="text"] {
|
395 |
+
direction: rtl;
|
396 |
+
}
|
397 |
+
.chosen-rtl .chosen-choices li.search-choice {
|
398 |
+
margin: 3px 5px 3px 0;
|
399 |
+
padding: 3px 5px 3px 19px;
|
400 |
+
}
|
401 |
+
.chosen-rtl .chosen-choices li.search-choice .search-choice-close {
|
402 |
+
right: auto;
|
403 |
+
left: 4px;
|
404 |
+
}
|
405 |
+
.chosen-rtl.chosen-container-single-nosearch .chosen-search,
|
406 |
+
.chosen-rtl .chosen-drop {
|
407 |
+
left: 9999px;
|
408 |
+
}
|
409 |
+
.chosen-rtl.chosen-container-single .chosen-results {
|
410 |
+
margin: 0 0 4px 4px;
|
411 |
+
padding: 0 4px 0 0;
|
412 |
+
}
|
413 |
+
.chosen-rtl .chosen-results li.group-option {
|
414 |
+
padding-right: 15px;
|
415 |
+
padding-left: 0;
|
416 |
+
}
|
417 |
+
.chosen-rtl.chosen-container-active.chosen-with-drop .chosen-single div {
|
418 |
+
border-right: none;
|
419 |
+
}
|
420 |
+
.chosen-rtl .chosen-search input[type="text"] {
|
421 |
+
padding: 4px 5px 4px 20px;
|
422 |
+
background: white url('chosen-sprite.png') no-repeat -30px -20px;
|
423 |
+
background: url('chosen-sprite.png') no-repeat -30px -20px;
|
424 |
+
direction: rtl;
|
425 |
+
}
|
426 |
+
.chosen-rtl.chosen-container-single .chosen-single div b {
|
427 |
+
background-position: 6px 2px;
|
428 |
+
}
|
429 |
+
.chosen-rtl.chosen-container-single.chosen-with-drop .chosen-single div b {
|
430 |
+
background-position: -12px 2px;
|
431 |
+
}
|
432 |
+
|
433 |
+
/* @end */
|
434 |
+
/* @group Retina compatibility */
|
435 |
+
@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi), only screen and (min-resolution: 1.5dppx) {
|
436 |
+
.chosen-rtl .chosen-search input[type="text"],
|
437 |
+
.chosen-container-single .chosen-single abbr,
|
438 |
+
.chosen-container-single .chosen-single div b,
|
439 |
+
.chosen-container-single .chosen-search input[type="text"],
|
440 |
+
.chosen-container-multi .chosen-choices .search-choice .search-choice-close,
|
441 |
+
.chosen-container .chosen-results-scroll-down span,
|
442 |
+
.chosen-container .chosen-results-scroll-up span {
|
443 |
+
background-image: url('chosen-sprite@2x.png') !important;
|
444 |
+
background-size: 52px 37px !important;
|
445 |
+
background-repeat: no-repeat !important;
|
446 |
+
}
|
447 |
+
}
|
448 |
+
/* @end */
|
assets/libs/chosen/chosen.jquery.min.js
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
1 |
+
/* Chosen v1.5.1 | (c) 2011-2016 by Harvest | MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md */
|
2 |
+
(function(){var a,AbstractChosen,Chosen,SelectParser,b,c={}.hasOwnProperty,d=function(a,b){function d(){this.constructor=a}for(var e in b)c.call(b,e)&&(a[e]=b[e]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a};SelectParser=function(){function SelectParser(){this.options_index=0,this.parsed=[]}return SelectParser.prototype.add_node=function(a){return"OPTGROUP"===a.nodeName.toUpperCase()?this.add_group(a):this.add_option(a)},SelectParser.prototype.add_group=function(a){var b,c,d,e,f,g;for(b=this.parsed.length,this.parsed.push({array_index:b,group:!0,label:this.escapeExpression(a.label),title:a.title?a.title:void 0,children:0,disabled:a.disabled,classes:a.className}),f=a.childNodes,g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(this.add_option(c,b,a.disabled));return g},SelectParser.prototype.add_option=function(a,b,c){return"OPTION"===a.nodeName.toUpperCase()?(""!==a.text?(null!=b&&(this.parsed[b].children+=1),this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,value:a.value,text:a.text,html:a.innerHTML,title:a.title?a.title:void 0,selected:a.selected,disabled:c===!0?c:a.disabled,group_array_index:b,group_label:null!=b?this.parsed[b].label:null,classes:a.className,style:a.style.cssText})):this.parsed.push({array_index:this.parsed.length,options_index:this.options_index,empty:!0}),this.options_index+=1):void 0},SelectParser.prototype.escapeExpression=function(a){var b,c;return null==a||a===!1?"":/[\&\<\>\"\'\`]/.test(a)?(b={"<":"<",">":">",'"':""","'":"'","`":"`"},c=/&(?!\w+;)|[\<\>\"\'\`]/g,a.replace(c,function(a){return b[a]||"&"})):a},SelectParser}(),SelectParser.select_to_array=function(a){var b,c,d,e,f;for(c=new SelectParser,f=a.childNodes,d=0,e=f.length;e>d;d++)b=f[d],c.add_node(b);return c.parsed},AbstractChosen=function(){function AbstractChosen(a,b){this.form_field=a,this.options=null!=b?b:{},AbstractChosen.browser_is_supported()&&(this.is_multiple=this.form_field.multiple,this.set_default_text(),this.set_default_values(),this.setup(),this.set_up_html(),this.register_observers(),this.on_ready())}return AbstractChosen.prototype.set_default_values=function(){var a=this;return this.click_test_action=function(b){return a.test_active_click(b)},this.activate_action=function(b){return a.activate_field(b)},this.active_field=!1,this.mouse_on_container=!1,this.results_showing=!1,this.result_highlighted=null,this.allow_single_deselect=null!=this.options.allow_single_deselect&&null!=this.form_field.options[0]&&""===this.form_field.options[0].text?this.options.allow_single_deselect:!1,this.disable_search_threshold=this.options.disable_search_threshold||0,this.disable_search=this.options.disable_search||!1,this.enable_split_word_search=null!=this.options.enable_split_word_search?this.options.enable_split_word_search:!0,this.group_search=null!=this.options.group_search?this.options.group_search:!0,this.search_contains=this.options.search_contains||!1,this.single_backstroke_delete=null!=this.options.single_backstroke_delete?this.options.single_backstroke_delete:!0,this.max_selected_options=this.options.max_selected_options||1/0,this.inherit_select_classes=this.options.inherit_select_classes||!1,this.display_selected_options=null!=this.options.display_selected_options?this.options.display_selected_options:!0,this.display_disabled_options=null!=this.options.display_disabled_options?this.options.display_disabled_options:!0,this.include_group_label_in_selected=this.options.include_group_label_in_selected||!1,this.max_shown_results=this.options.max_shown_results||Number.POSITIVE_INFINITY},AbstractChosen.prototype.set_default_text=function(){return this.form_field.getAttribute("data-placeholder")?this.default_text=this.form_field.getAttribute("data-placeholder"):this.is_multiple?this.default_text=this.options.placeholder_text_multiple||this.options.placeholder_text||AbstractChosen.default_multiple_text:this.default_text=this.options.placeholder_text_single||this.options.placeholder_text||AbstractChosen.default_single_text,this.results_none_found=this.form_field.getAttribute("data-no_results_text")||this.options.no_results_text||AbstractChosen.default_no_result_text},AbstractChosen.prototype.choice_label=function(a){return this.include_group_label_in_selected&&null!=a.group_label?"<b class='group-name'>"+a.group_label+"</b>"+a.html:a.html},AbstractChosen.prototype.mouse_enter=function(){return this.mouse_on_container=!0},AbstractChosen.prototype.mouse_leave=function(){return this.mouse_on_container=!1},AbstractChosen.prototype.input_focus=function(a){var b=this;if(this.is_multiple){if(!this.active_field)return setTimeout(function(){return b.container_mousedown()},50)}else if(!this.active_field)return this.activate_field()},AbstractChosen.prototype.input_blur=function(a){var b=this;return this.mouse_on_container?void 0:(this.active_field=!1,setTimeout(function(){return b.blur_test()},100))},AbstractChosen.prototype.results_option_build=function(a){var b,c,d,e,f,g,h;for(b="",e=0,h=this.results_data,f=0,g=h.length;g>f&&(c=h[f],d="",d=c.group?this.result_add_group(c):this.result_add_option(c),""!==d&&(e++,b+=d),(null!=a?a.first:void 0)&&(c.selected&&this.is_multiple?this.choice_build(c):c.selected&&!this.is_multiple&&this.single_set_selected_text(this.choice_label(c))),!(e>=this.max_shown_results));f++);return b},AbstractChosen.prototype.result_add_option=function(a){var b,c;return a.search_match&&this.include_option_in_results(a)?(b=[],a.disabled||a.selected&&this.is_multiple||b.push("active-result"),!a.disabled||a.selected&&this.is_multiple||b.push("disabled-result"),a.selected&&b.push("result-selected"),null!=a.group_array_index&&b.push("group-option"),""!==a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.style.cssText=a.style,c.setAttribute("data-option-array-index",a.array_index),c.innerHTML=a.search_text,a.title&&(c.title=a.title),this.outerHTML(c)):""},AbstractChosen.prototype.result_add_group=function(a){var b,c;return(a.search_match||a.group_match)&&a.active_options>0?(b=[],b.push("group-result"),a.classes&&b.push(a.classes),c=document.createElement("li"),c.className=b.join(" "),c.innerHTML=a.search_text,a.title&&(c.title=a.title),this.outerHTML(c)):""},AbstractChosen.prototype.results_update_field=function(){return this.set_default_text(),this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.results_build(),this.results_showing?this.winnow_results():void 0},AbstractChosen.prototype.reset_single_select_options=function(){var a,b,c,d,e;for(d=this.results_data,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.selected?e.push(a.selected=!1):e.push(void 0);return e},AbstractChosen.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},AbstractChosen.prototype.results_search=function(a){return this.results_showing?this.winnow_results():this.results_show()},AbstractChosen.prototype.winnow_results=function(){var a,b,c,d,e,f,g,h,i,j,k,l;for(this.no_results_clear(),d=0,f=this.get_search_text(),a=f.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&"),i=new RegExp(a,"i"),c=this.get_search_regex(a),l=this.results_data,j=0,k=l.length;k>j;j++)b=l[j],b.search_match=!1,e=null,this.include_option_in_results(b)&&(b.group&&(b.group_match=!1,b.active_options=0),null!=b.group_array_index&&this.results_data[b.group_array_index]&&(e=this.results_data[b.group_array_index],0===e.active_options&&e.search_match&&(d+=1),e.active_options+=1),b.search_text=b.group?b.label:b.html,(!b.group||this.group_search)&&(b.search_match=this.search_string_match(b.search_text,c),b.search_match&&!b.group&&(d+=1),b.search_match?(f.length&&(g=b.search_text.search(i),h=b.search_text.substr(0,g+f.length)+"</em>"+b.search_text.substr(g+f.length),b.search_text=h.substr(0,g)+"<em>"+h.substr(g)),null!=e&&(e.group_match=!0)):null!=b.group_array_index&&this.results_data[b.group_array_index].search_match&&(b.search_match=!0)));return this.result_clear_highlight(),1>d&&f.length?(this.update_results_content(""),this.no_results(f)):(this.update_results_content(this.results_option_build()),this.winnow_results_set_highlight())},AbstractChosen.prototype.get_search_regex=function(a){var b;return b=this.search_contains?"":"^",new RegExp(b+a,"i")},AbstractChosen.prototype.search_string_match=function(a,b){var c,d,e,f;if(b.test(a))return!0;if(this.enable_split_word_search&&(a.indexOf(" ")>=0||0===a.indexOf("["))&&(d=a.replace(/\[|\]/g,"").split(" "),d.length))for(e=0,f=d.length;f>e;e++)if(c=d[e],b.test(c))return!0},AbstractChosen.prototype.choices_count=function(){var a,b,c,d;if(null!=this.selected_option_count)return this.selected_option_count;for(this.selected_option_count=0,d=this.form_field.options,b=0,c=d.length;c>b;b++)a=d[b],a.selected&&(this.selected_option_count+=1);return this.selected_option_count},AbstractChosen.prototype.choices_click=function(a){return a.preventDefault(),this.results_showing||this.is_disabled?void 0:this.results_show()},AbstractChosen.prototype.keyup_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),b){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices_count()>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:if(a.preventDefault(),this.results_showing)return this.result_select(a);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:case 18:break;default:return this.results_search()}},AbstractChosen.prototype.clipboard_event_checker=function(a){var b=this;return setTimeout(function(){return b.results_search()},50)},AbstractChosen.prototype.container_width=function(){return null!=this.options.width?this.options.width:""+this.form_field.offsetWidth+"px"},AbstractChosen.prototype.include_option_in_results=function(a){return this.is_multiple&&!this.display_selected_options&&a.selected?!1:!this.display_disabled_options&&a.disabled?!1:a.empty?!1:!0},AbstractChosen.prototype.search_results_touchstart=function(a){return this.touch_started=!0,this.search_results_mouseover(a)},AbstractChosen.prototype.search_results_touchmove=function(a){return this.touch_started=!1,this.search_results_mouseout(a)},AbstractChosen.prototype.search_results_touchend=function(a){return this.touch_started?this.search_results_mouseup(a):void 0},AbstractChosen.prototype.outerHTML=function(a){var b;return a.outerHTML?a.outerHTML:(b=document.createElement("div"),b.appendChild(a),b.innerHTML)},AbstractChosen.browser_is_supported=function(){return/iP(od|hone)/i.test(window.navigator.userAgent)?!1:/Android/i.test(window.navigator.userAgent)&&/Mobile/i.test(window.navigator.userAgent)?!1:/IEMobile/i.test(window.navigator.userAgent)?!1:/Windows Phone/i.test(window.navigator.userAgent)?!1:/BlackBerry/i.test(window.navigator.userAgent)?!1:/BB10/i.test(window.navigator.userAgent)?!1:"Microsoft Internet Explorer"===window.navigator.appName?document.documentMode>=8:!0},AbstractChosen.default_multiple_text="Select Some Options",AbstractChosen.default_single_text="Select an Option",AbstractChosen.default_no_result_text="No results match",AbstractChosen}(),a=jQuery,a.fn.extend({chosen:function(b){return AbstractChosen.browser_is_supported()?this.each(function(c){var d,e;return d=a(this),e=d.data("chosen"),"destroy"===b?void(e instanceof Chosen&&e.destroy()):void(e instanceof Chosen||d.data("chosen",new Chosen(this,b)))}):this}}),Chosen=function(c){function Chosen(){return b=Chosen.__super__.constructor.apply(this,arguments)}return d(Chosen,c),Chosen.prototype.setup=function(){return this.form_field_jq=a(this.form_field),this.current_selectedIndex=this.form_field.selectedIndex,this.is_rtl=this.form_field_jq.hasClass("chosen-rtl")},Chosen.prototype.set_up_html=function(){var b,c;return b=["chosen-container"],b.push("chosen-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&b.push(this.form_field.className),this.is_rtl&&b.push("chosen-rtl"),c={"class":b.join(" "),style:"width: "+this.container_width()+";",title:this.form_field.title},this.form_field.id.length&&(c.id=this.form_field.id.replace(/[^\w]/g,"_")+"_chosen"),this.container=a("<div />",c),this.is_multiple?this.container.html('<ul class="chosen-choices"><li class="search-field"><input type="text" value="'+this.default_text+'" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chosen-drop"><ul class="chosen-results"></ul></div>'):this.container.html('<a class="chosen-single chosen-default"><span>'+this.default_text+'</span><div><b></b></div></a><div class="chosen-drop"><div class="chosen-search"><input type="text" autocomplete="off" /></div><ul class="chosen-results"></ul></div>'),this.form_field_jq.hide().after(this.container),this.dropdown=this.container.find("div.chosen-drop").first(),this.search_field=this.container.find("input").first(),this.search_results=this.container.find("ul.chosen-results").first(),this.search_field_scale(),this.search_no_results=this.container.find("li.no-results").first(),this.is_multiple?(this.search_choices=this.container.find("ul.chosen-choices").first(),this.search_container=this.container.find("li.search-field").first()):(this.search_container=this.container.find("div.chosen-search").first(),this.selected_item=this.container.find(".chosen-single").first()),this.results_build(),this.set_tab_index(),this.set_label_behavior()},Chosen.prototype.on_ready=function(){return this.form_field_jq.trigger("chosen:ready",{chosen:this})},Chosen.prototype.register_observers=function(){var a=this;return this.container.bind("touchstart.chosen",function(b){return a.container_mousedown(b),b.preventDefault()}),this.container.bind("touchend.chosen",function(b){return a.container_mouseup(b),b.preventDefault()}),this.container.bind("mousedown.chosen",function(b){a.container_mousedown(b)}),this.container.bind("mouseup.chosen",function(b){a.container_mouseup(b)}),this.container.bind("mouseenter.chosen",function(b){a.mouse_enter(b)}),this.container.bind("mouseleave.chosen",function(b){a.mouse_leave(b)}),this.search_results.bind("mouseup.chosen",function(b){a.search_results_mouseup(b)}),this.search_results.bind("mouseover.chosen",function(b){a.search_results_mouseover(b)}),this.search_results.bind("mouseout.chosen",function(b){a.search_results_mouseout(b)}),this.search_results.bind("mousewheel.chosen DOMMouseScroll.chosen",function(b){a.search_results_mousewheel(b)}),this.search_results.bind("touchstart.chosen",function(b){a.search_results_touchstart(b)}),this.search_results.bind("touchmove.chosen",function(b){a.search_results_touchmove(b)}),this.search_results.bind("touchend.chosen",function(b){a.search_results_touchend(b)}),this.form_field_jq.bind("chosen:updated.chosen",function(b){a.results_update_field(b)}),this.form_field_jq.bind("chosen:activate.chosen",function(b){a.activate_field(b)}),this.form_field_jq.bind("chosen:open.chosen",function(b){a.container_mousedown(b)}),this.form_field_jq.bind("chosen:close.chosen",function(b){a.input_blur(b)}),this.search_field.bind("blur.chosen",function(b){a.input_blur(b)}),this.search_field.bind("keyup.chosen",function(b){a.keyup_checker(b)}),this.search_field.bind("keydown.chosen",function(b){a.keydown_checker(b)}),this.search_field.bind("focus.chosen",function(b){a.input_focus(b)}),this.search_field.bind("cut.chosen",function(b){a.clipboard_event_checker(b)}),this.search_field.bind("paste.chosen",function(b){a.clipboard_event_checker(b)}),this.is_multiple?this.search_choices.bind("click.chosen",function(b){a.choices_click(b)}):this.container.bind("click.chosen",function(a){a.preventDefault()})},Chosen.prototype.destroy=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.search_field[0].tabIndex&&(this.form_field_jq[0].tabIndex=this.search_field[0].tabIndex),this.container.remove(),this.form_field_jq.removeData("chosen"),this.form_field_jq.show()},Chosen.prototype.search_field_disabled=function(){return this.is_disabled=this.form_field_jq[0].disabled,this.is_disabled?(this.container.addClass("chosen-disabled"),this.search_field[0].disabled=!0,this.is_multiple||this.selected_item.unbind("focus.chosen",this.activate_action),this.close_field()):(this.container.removeClass("chosen-disabled"),this.search_field[0].disabled=!1,this.is_multiple?void 0:this.selected_item.bind("focus.chosen",this.activate_action))},Chosen.prototype.container_mousedown=function(b){return this.is_disabled||(b&&"mousedown"===b.type&&!this.results_showing&&b.preventDefault(),null!=b&&a(b.target).hasClass("search-choice-close"))?void 0:(this.active_field?this.is_multiple||!b||a(b.target)[0]!==this.selected_item[0]&&!a(b.target).parents("a.chosen-single").length||(b.preventDefault(),this.results_toggle()):(this.is_multiple&&this.search_field.val(""),a(this.container[0].ownerDocument).bind("click.chosen",this.click_test_action),this.results_show()),this.activate_field())},Chosen.prototype.container_mouseup=function(a){return"ABBR"!==a.target.nodeName||this.is_disabled?void 0:this.results_reset(a)},Chosen.prototype.search_results_mousewheel=function(a){var b;return a.originalEvent&&(b=a.originalEvent.deltaY||-a.originalEvent.wheelDelta||a.originalEvent.detail),null!=b?(a.preventDefault(),"DOMMouseScroll"===a.type&&(b=40*b),this.search_results.scrollTop(b+this.search_results.scrollTop())):void 0},Chosen.prototype.blur_test=function(a){return!this.active_field&&this.container.hasClass("chosen-container-active")?this.close_field():void 0},Chosen.prototype.close_field=function(){return a(this.container[0].ownerDocument).unbind("click.chosen",this.click_test_action),this.active_field=!1,this.results_hide(),this.container.removeClass("chosen-container-active"),this.clear_backstroke(),this.show_search_field_default(),this.search_field_scale()},Chosen.prototype.activate_field=function(){return this.container.addClass("chosen-container-active"),this.active_field=!0,this.search_field.val(this.search_field.val()),this.search_field.focus()},Chosen.prototype.test_active_click=function(b){var c;return c=a(b.target).closest(".chosen-container"),c.length&&this.container[0]===c[0]?this.active_field=!0:this.close_field()},Chosen.prototype.results_build=function(){return this.parsing=!0,this.selected_option_count=null,this.results_data=SelectParser.select_to_array(this.form_field),this.is_multiple?this.search_choices.find("li.search-choice").remove():this.is_multiple||(this.single_set_selected_text(),this.disable_search||this.form_field.options.length<=this.disable_search_threshold?(this.search_field[0].readOnly=!0,this.container.addClass("chosen-container-single-nosearch")):(this.search_field[0].readOnly=!1,this.container.removeClass("chosen-container-single-nosearch"))),this.update_results_content(this.results_option_build({first:!0})),this.search_field_disabled(),this.show_search_field_default(),this.search_field_scale(),this.parsing=!1},Chosen.prototype.result_do_highlight=function(a){var b,c,d,e,f;if(a.length){if(this.result_clear_highlight(),this.result_highlight=a,this.result_highlight.addClass("highlighted"),d=parseInt(this.search_results.css("maxHeight"),10),f=this.search_results.scrollTop(),e=d+f,c=this.result_highlight.position().top+this.search_results.scrollTop(),b=c+this.result_highlight.outerHeight(),b>=e)return this.search_results.scrollTop(b-d>0?b-d:0);if(f>c)return this.search_results.scrollTop(c)}},Chosen.prototype.result_clear_highlight=function(){return this.result_highlight&&this.result_highlight.removeClass("highlighted"),this.result_highlight=null},Chosen.prototype.results_show=function(){return this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.container.addClass("chosen-with-drop"),this.results_showing=!0,this.search_field.focus(),this.search_field.val(this.search_field.val()),this.winnow_results(),this.form_field_jq.trigger("chosen:showing_dropdown",{chosen:this}))},Chosen.prototype.update_results_content=function(a){return this.search_results.html(a)},Chosen.prototype.results_hide=function(){return this.results_showing&&(this.result_clear_highlight(),this.container.removeClass("chosen-with-drop"),this.form_field_jq.trigger("chosen:hiding_dropdown",{chosen:this})),this.results_showing=!1},Chosen.prototype.set_tab_index=function(a){var b;return this.form_field.tabIndex?(b=this.form_field.tabIndex,this.form_field.tabIndex=-1,this.search_field[0].tabIndex=b):void 0},Chosen.prototype.set_label_behavior=function(){var b=this;return this.form_field_label=this.form_field_jq.parents("label"),!this.form_field_label.length&&this.form_field.id.length&&(this.form_field_label=a("label[for='"+this.form_field.id+"']")),this.form_field_label.length>0?this.form_field_label.bind("click.chosen",function(a){return b.is_multiple?b.container_mousedown(a):b.activate_field()}):void 0},Chosen.prototype.show_search_field_default=function(){return this.is_multiple&&this.choices_count()<1&&!this.active_field?(this.search_field.val(this.default_text),this.search_field.addClass("default")):(this.search_field.val(""),this.search_field.removeClass("default"))},Chosen.prototype.search_results_mouseup=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c.length?(this.result_highlight=c,this.result_select(b),this.search_field.focus()):void 0},Chosen.prototype.search_results_mouseover=function(b){var c;return c=a(b.target).hasClass("active-result")?a(b.target):a(b.target).parents(".active-result").first(),c?this.result_do_highlight(c):void 0},Chosen.prototype.search_results_mouseout=function(b){return a(b.target).hasClass("active-result")?this.result_clear_highlight():void 0},Chosen.prototype.choice_build=function(b){var c,d,e=this;return c=a("<li />",{"class":"search-choice"}).html("<span>"+this.choice_label(b)+"</span>"),b.disabled?c.addClass("search-choice-disabled"):(d=a("<a />",{"class":"search-choice-close","data-option-array-index":b.array_index}),d.bind("click.chosen",function(a){return e.choice_destroy_link_click(a)}),c.append(d)),this.search_container.before(c)},Chosen.prototype.choice_destroy_link_click=function(b){return b.preventDefault(),b.stopPropagation(),this.is_disabled?void 0:this.choice_destroy(a(b.target))},Chosen.prototype.choice_destroy=function(a){return this.result_deselect(a[0].getAttribute("data-option-array-index"))?(this.show_search_field_default(),this.is_multiple&&this.choices_count()>0&&this.search_field.val().length<1&&this.results_hide(),a.parents("li").first().remove(),this.search_field_scale()):void 0},Chosen.prototype.results_reset=function(){return this.reset_single_select_options(),this.form_field.options[0].selected=!0,this.single_set_selected_text(),this.show_search_field_default(),this.results_reset_cleanup(),this.form_field_jq.trigger("change"),this.active_field?this.results_hide():void 0},Chosen.prototype.results_reset_cleanup=function(){return this.current_selectedIndex=this.form_field.selectedIndex,this.selected_item.find("abbr").remove()},Chosen.prototype.result_select=function(a){var b,c;return this.result_highlight?(b=this.result_highlight,this.result_clear_highlight(),this.is_multiple&&this.max_selected_options<=this.choices_count()?(this.form_field_jq.trigger("chosen:maxselected",{chosen:this}),!1):(this.is_multiple?b.removeClass("active-result"):this.reset_single_select_options(),b.addClass("result-selected"),c=this.results_data[b[0].getAttribute("data-option-array-index")],c.selected=!0,this.form_field.options[c.options_index].selected=!0,this.selected_option_count=null,this.is_multiple?this.choice_build(c):this.single_set_selected_text(this.choice_label(c)),(a.metaKey||a.ctrlKey)&&this.is_multiple||this.results_hide(),this.show_search_field_default(),(this.is_multiple||this.form_field.selectedIndex!==this.current_selectedIndex)&&this.form_field_jq.trigger("change",{selected:this.form_field.options[c.options_index].value}),this.current_selectedIndex=this.form_field.selectedIndex,a.preventDefault(),this.search_field_scale())):void 0},Chosen.prototype.single_set_selected_text=function(a){return null==a&&(a=this.default_text),a===this.default_text?this.selected_item.addClass("chosen-default"):(this.single_deselect_control_build(),this.selected_item.removeClass("chosen-default")),this.selected_item.find("span").html(a)},Chosen.prototype.result_deselect=function(a){var b;return b=this.results_data[a],this.form_field.options[b.options_index].disabled?!1:(b.selected=!1,this.form_field.options[b.options_index].selected=!1,this.selected_option_count=null,this.result_clear_highlight(),this.results_showing&&this.winnow_results(),this.form_field_jq.trigger("change",{deselected:this.form_field.options[b.options_index].value}),this.search_field_scale(),!0)},Chosen.prototype.single_deselect_control_build=function(){return this.allow_single_deselect?(this.selected_item.find("abbr").length||this.selected_item.find("span").first().after('<abbr class="search-choice-close"></abbr>'),this.selected_item.addClass("chosen-single-with-deselect")):void 0},Chosen.prototype.get_search_text=function(){return a("<div/>").text(a.trim(this.search_field.val())).html()},Chosen.prototype.winnow_results_set_highlight=function(){var a,b;return b=this.is_multiple?[]:this.search_results.find(".result-selected.active-result"),a=b.length?b.first():this.search_results.find(".active-result").first(),null!=a?this.result_do_highlight(a):void 0},Chosen.prototype.no_results=function(b){var c;return c=a('<li class="no-results">'+this.results_none_found+' "<span></span>"</li>'),c.find("span").first().html(b),this.search_results.append(c),this.form_field_jq.trigger("chosen:no_results",{chosen:this})},Chosen.prototype.no_results_clear=function(){return this.search_results.find(".no-results").remove()},Chosen.prototype.keydown_arrow=function(){var a;return this.results_showing&&this.result_highlight?(a=this.result_highlight.nextAll("li.active-result").first())?this.result_do_highlight(a):void 0:this.results_show()},Chosen.prototype.keyup_arrow=function(){var a;return this.results_showing||this.is_multiple?this.result_highlight?(a=this.result_highlight.prevAll("li.active-result"),a.length?this.result_do_highlight(a.first()):(this.choices_count()>0&&this.results_hide(),this.result_clear_highlight())):void 0:this.results_show()},Chosen.prototype.keydown_backstroke=function(){var a;return this.pending_backstroke?(this.choice_destroy(this.pending_backstroke.find("a").first()),this.clear_backstroke()):(a=this.search_container.siblings("li.search-choice").last(),a.length&&!a.hasClass("search-choice-disabled")?(this.pending_backstroke=a,this.single_backstroke_delete?this.keydown_backstroke():this.pending_backstroke.addClass("search-choice-focus")):void 0)},Chosen.prototype.clear_backstroke=function(){return this.pending_backstroke&&this.pending_backstroke.removeClass("search-choice-focus"),this.pending_backstroke=null},Chosen.prototype.keydown_checker=function(a){var b,c;switch(b=null!=(c=a.which)?c:a.keyCode,this.search_field_scale(),8!==b&&this.pending_backstroke&&this.clear_backstroke(),b){case 8:this.backstroke_length=this.search_field.val().length;break;case 9:this.results_showing&&!this.is_multiple&&this.result_select(a),this.mouse_on_container=!1;break;case 13:this.results_showing&&a.preventDefault();break;case 32:this.disable_search&&a.preventDefault();break;case 38:a.preventDefault(),this.keyup_arrow();break;case 40:a.preventDefault(),this.keydown_arrow()}},Chosen.prototype.search_field_scale=function(){var b,c,d,e,f,g,h,i,j;if(this.is_multiple){for(d=0,h=0,f="position:absolute; left: -1000px; top: -1000px; display:none;",g=["font-size","font-style","font-weight","font-family","line-height","text-transform","letter-spacing"],i=0,j=g.length;j>i;i++)e=g[i],f+=e+":"+this.search_field.css(e)+";";return b=a("<div />",{style:f}),b.text(this.search_field.val()),a("body").append(b),h=b.width()+25,b.remove(),c=this.container.outerWidth(),h>c-10&&(h=c-10),this.search_field.css({width:h+"px"})}},Chosen}(AbstractChosen)}).call(this);
|
blocks/sbc/assets/js/script-block-sbc.js
DELETED
@@ -1,71 +0,0 @@
|
|
1 |
-
var el = wp.element.createElement;
|
2 |
-
var ServerSideRender = wp.components.ServerSideRender;
|
3 |
-
var PanelBody = wp.components.PanelBody;
|
4 |
-
var SelectControl = wp.components.SelectControl;
|
5 |
-
var registerBlockType = wp.blocks.registerBlockType;
|
6 |
-
var InspectorControls = wp.editor.InspectorControls;
|
7 |
-
var __ = wp.i18n.__;
|
8 |
-
|
9 |
-
// Register the block
|
10 |
-
registerBlockType( 'wp-simple-booking-calendar/sbc', {
|
11 |
-
|
12 |
-
// The block's title
|
13 |
-
title : 'Single Calendar',
|
14 |
-
|
15 |
-
// The block's icon
|
16 |
-
icon : 'calendar-alt',
|
17 |
-
|
18 |
-
// The block category the block should be added to
|
19 |
-
category : 'wp-simple-booking-calendar',
|
20 |
-
|
21 |
-
// The block's attributes, needed to save the data
|
22 |
-
attributes : {
|
23 |
-
|
24 |
-
title : {
|
25 |
-
type : 'string'
|
26 |
-
}
|
27 |
-
|
28 |
-
},
|
29 |
-
|
30 |
-
edit : function( props ) {
|
31 |
-
|
32 |
-
return [
|
33 |
-
|
34 |
-
el( ServerSideRender, {
|
35 |
-
block : 'wp-simple-booking-calendar/sbc',
|
36 |
-
attributes : props.attributes
|
37 |
-
}),
|
38 |
-
|
39 |
-
el( InspectorControls, { key : 'inspector' },
|
40 |
-
|
41 |
-
el( PanelBody, {
|
42 |
-
title : __( 'Calendar Options', 'wp-simple-booking-calendar' ),
|
43 |
-
initialOpen : true
|
44 |
-
},
|
45 |
-
|
46 |
-
el( SelectControl, {
|
47 |
-
|
48 |
-
label : __( 'Display Calendar Title', 'wp-simple-booking-calendar' ),
|
49 |
-
value : props.attributes.title,
|
50 |
-
options : [
|
51 |
-
{ value : 'yes', label : __( 'Yes', 'wp-simple-booking-calendar' ) },
|
52 |
-
{ value : 'no', label : __( 'No', 'wp-simple-booking-calendar' ) }
|
53 |
-
],
|
54 |
-
onChange : function( new_value ) {
|
55 |
-
props.setAttributes( { title : new_value } );
|
56 |
-
}
|
57 |
-
})
|
58 |
-
|
59 |
-
)
|
60 |
-
|
61 |
-
)
|
62 |
-
|
63 |
-
];
|
64 |
-
|
65 |
-
},
|
66 |
-
|
67 |
-
save : function() {
|
68 |
-
return null;
|
69 |
-
}
|
70 |
-
|
71 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
blocks/sbc/functions.php
DELETED
@@ -1,152 +0,0 @@
|
|
1 |
-
<?php
|
2 |
-
|
3 |
-
// Exit if accessed directly
|
4 |
-
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Function that register the needed categories for the different block
|
8 |
-
* available in the plugin
|
9 |
-
*
|
10 |
-
*/
|
11 |
-
if( ! function_exists( 'wpsbc_register_block_categories' ) ) {
|
12 |
-
|
13 |
-
function wpsbc_register_block_categories( $categories, $post ) {
|
14 |
-
|
15 |
-
/**
|
16 |
-
* Filter the post types where the blocks are available
|
17 |
-
*
|
18 |
-
* @param array
|
19 |
-
*
|
20 |
-
*/
|
21 |
-
$post_types = apply_filters( 'wpsbc_register_block_categories_post_types', array( 'post', 'page' ) );
|
22 |
-
|
23 |
-
if( ! in_array( $post->post_type, $post_types ) )
|
24 |
-
return $categories;
|
25 |
-
|
26 |
-
$categories[] = array(
|
27 |
-
'slug' => 'wp-simple-booking-calendar',
|
28 |
-
'title' => 'WP Simple Booking Calendar',
|
29 |
-
'icon' => ''
|
30 |
-
);
|
31 |
-
|
32 |
-
return $categories;
|
33 |
-
|
34 |
-
}
|
35 |
-
add_filter( 'block_categories', 'wpsbc_register_block_categories', 10, 2 );
|
36 |
-
|
37 |
-
}
|
38 |
-
|
39 |
-
|
40 |
-
/**
|
41 |
-
* Adds the front-end files to the admin editor screen
|
42 |
-
*
|
43 |
-
*/
|
44 |
-
function wpsbc_add_front_end_scripts() {
|
45 |
-
|
46 |
-
if( ! function_exists( 'get_current_screen' ) )
|
47 |
-
return;
|
48 |
-
|
49 |
-
$screen = get_current_screen();
|
50 |
-
|
51 |
-
if( is_null( $screen ) )
|
52 |
-
return;
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Filter the post types where the calendar media button should appear
|
56 |
-
*
|
57 |
-
* @param array
|
58 |
-
*
|
59 |
-
*/
|
60 |
-
$post_types = apply_filters( 'wpsbc_register_block_categories_post_types', array( 'post', 'page' ) );
|
61 |
-
|
62 |
-
if( ! in_array( $screen->post_type, $post_types ) )
|
63 |
-
return;
|
64 |
-
|
65 |
-
|
66 |
-
// Enqueue front-end scripts on the admin part
|
67 |
-
wp_register_script( 'sbc-front-end-script', SBC_DIR_URL . 'js/sbc.js', array( 'jquery' ), SBC_VERSION, true );
|
68 |
-
wp_enqueue_script( 'sbc-front-end-script' );
|
69 |
-
|
70 |
-
// Enqueue front-end styles on the admin part
|
71 |
-
wp_register_style( 'sbc-front-end-style', SBC_DIR_URL . 'css/sbc.css', array(), SBC_VERSION );
|
72 |
-
wp_enqueue_style( 'sbc-front-end-style' );
|
73 |
-
|
74 |
-
}
|
75 |
-
add_action( 'admin_enqueue_scripts', 'wpsbc_add_front_end_scripts', 10 );
|
76 |
-
|
77 |
-
|
78 |
-
/**
|
79 |
-
* Registers the Single Calendar block
|
80 |
-
*
|
81 |
-
*/
|
82 |
-
if( function_exists( 'register_block_type' ) ) {
|
83 |
-
|
84 |
-
function wpsbc_register_block_type_sbc() {
|
85 |
-
|
86 |
-
wp_register_script( 'sbc-script-block-sbc', SBC_DIR_URL . 'blocks/sbc/assets/js/script-block-sbc.js', array( 'wp-blocks', 'wp-element', 'wp-editor', 'wp-i18n' ) );
|
87 |
-
|
88 |
-
register_block_type(
|
89 |
-
'wp-simple-booking-calendar/sbc',
|
90 |
-
array(
|
91 |
-
'attributes' => array(
|
92 |
-
'title' => array(
|
93 |
-
'type' => 'string'
|
94 |
-
)
|
95 |
-
),
|
96 |
-
'editor_script' => 'sbc-script-block-sbc',
|
97 |
-
'render_callback' => 'wpsbc_block_to_shortcode_sbc'
|
98 |
-
)
|
99 |
-
);
|
100 |
-
|
101 |
-
}
|
102 |
-
add_action( 'init', 'wpsbc_register_block_type_sbc' );
|
103 |
-
|
104 |
-
}
|
105 |
-
|
106 |
-
|
107 |
-
/**
|
108 |
-
* Render callback for the server render block
|
109 |
-
* Transforms the attributes from the blocks into the needed shortcode arguments
|
110 |
-
*
|
111 |
-
* @param array $args
|
112 |
-
*
|
113 |
-
* @return string
|
114 |
-
*
|
115 |
-
*/
|
116 |
-
function wpsbc_block_to_shortcode_sbc( $args ) {
|
117 |
-
|
118 |
-
$atts = (array) $args;
|
119 |
-
|
120 |
-
// Validate booleans
|
121 |
-
$booleans = array('title');
|
122 |
-
foreach ($booleans as $key)
|
123 |
-
{
|
124 |
-
if (isset($atts[$key]))
|
125 |
-
{
|
126 |
-
// Replace string values: Yes = true, No = false
|
127 |
-
if (is_bool($atts[$key]) !== true)
|
128 |
-
{
|
129 |
-
$value = (strcasecmp($atts[$key], 'yes') == 0 || $atts[$key] == '1');
|
130 |
-
}
|
131 |
-
else
|
132 |
-
{
|
133 |
-
$value = $atts[$key];
|
134 |
-
}
|
135 |
-
|
136 |
-
$atts[$key] = $value;
|
137 |
-
}
|
138 |
-
}
|
139 |
-
|
140 |
-
// Process attributes
|
141 |
-
$defaults = array('id' => null, 'title' => true);
|
142 |
-
$values = shortcode_atts($defaults, $atts);
|
143 |
-
|
144 |
-
$model = new WpSimpleBookingCalendar_Model();
|
145 |
-
$view = new WpSimpleBookingCalendar_View();
|
146 |
-
|
147 |
-
return $view->setTemplate('shortcode/sbc')
|
148 |
-
->assign('showTitle', $values['title'])
|
149 |
-
->assign('calendar', $model->getCalendar())
|
150 |
-
->fetch();
|
151 |
-
|
152 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
css/sbc-controller.css
DELETED
@@ -1,98 +0,0 @@
|
|
1 |
-
@CHARSET "UTF-8";
|
2 |
-
|
3 |
-
#sbc-wrapper div.postbox-container {
|
4 |
-
float: none;
|
5 |
-
padding: 0;
|
6 |
-
|
7 |
-
/*width: 440px;*/
|
8 |
-
position:relative;
|
9 |
-
}
|
10 |
-
|
11 |
-
#sbc-calendar {
|
12 |
-
float: left;
|
13 |
-
margin: 0 3px 30px 0;
|
14 |
-
}
|
15 |
-
|
16 |
-
#sbc-wrapper div.postbox div.inside {
|
17 |
-
margin: 14px 10px;
|
18 |
-
position: relative;
|
19 |
-
}
|
20 |
-
|
21 |
-
#sbc-wrapper .wpsbc-buttons-container {
|
22 |
-
position: absolute; top: -30px; right: 0;
|
23 |
-
}
|
24 |
-
|
25 |
-
#sbc-wrapper div.postbox-container p {
|
26 |
-
margin: 20px 0;
|
27 |
-
padding-top:0px;
|
28 |
-
}
|
29 |
-
|
30 |
-
#sbc-wrapper div.postbox-container label {
|
31 |
-
display: block;
|
32 |
-
/*font-size: 12px;*/
|
33 |
-
font-weight: bold;
|
34 |
-
margin: 0 0 3px;
|
35 |
-
}
|
36 |
-
|
37 |
-
#sbc-wrapper div.postbox-container label em {
|
38 |
-
color: #62625A;
|
39 |
-
font-weight: normal;
|
40 |
-
}
|
41 |
-
|
42 |
-
#sbc-wrapper div.postbox div.inside textarea {
|
43 |
-
width: 100%;
|
44 |
-
}
|
45 |
-
|
46 |
-
#sbc-wrapper div.postbox div.inside input, #sbc-wrapper div.postbox div.inside textarea {
|
47 |
-
margin: 1px;
|
48 |
-
padding: 3px;
|
49 |
-
}
|
50 |
-
|
51 |
-
#sbc-wrapper div.postbox div.inside input.error, #sbc-wrapper div.postbox div.inside textarea.error {
|
52 |
-
margin: 1px 1px 3px 1px;
|
53 |
-
padding: 3px;
|
54 |
-
}
|
55 |
-
|
56 |
-
#sbc-wrapper .tablenav {
|
57 |
-
line-height: 30px;
|
58 |
-
}
|
59 |
-
|
60 |
-
#sbc-wrapper p.search-box {
|
61 |
-
height: 30px;
|
62 |
-
line-height: 30px;
|
63 |
-
margin: 0;
|
64 |
-
}
|
65 |
-
|
66 |
-
#sbc-wrapper div.loader {
|
67 |
-
display: none;
|
68 |
-
height: 55px;
|
69 |
-
}
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
div.buy-full h1 {font-weight:bold; font-size:20px; line-height:30px; margin-top:30px;}
|
74 |
-
div.buy-full .box {float:left; padding:15px 15px 7px 15px; width:255px; border:1px solid #cccccc; margin-right:15px; background-color:#fff;}
|
75 |
-
div.buy-full .box h1 {padding:0px; margin:0px; border-bottom:1px solid #cccccc; color:#0084ff; font-weight:normal; font-size:26px; display:block; text-align:center; padding:11px 0 26px 0;}
|
76 |
-
div.buy-full .box ul {list-style:none; padding-top:9px; display:block; height:523px;}
|
77 |
-
|
78 |
-
div.buy-full .box ul li {background: transparent url(../images/checked-icon.jpg) no-repeat left 6px; color:#666666; font-size:14px; padding:6px 0 5px 21px;}
|
79 |
-
div.buy-full .box h2 {font-weight:normal; display:block; text-align:center; color:#0084ff; font-size:30px; float:left; margin:0 0 0 25px; padding:19px 0 0 0;}
|
80 |
-
div.buy-full .box small {color:#0084ff; font-size:14px; display:block; margin:8px 0 0 6px; float:left; padding-top: 10px; }
|
81 |
-
div.buy-full .box span {display:block; height:50px; line-height:50px; text-align:center;}
|
82 |
-
div.buy-full .box p {font-size:14px; color:#666666; padding:13px 20px 6px 20px;}
|
83 |
-
div.buy-full .box strong {font-weight:normal; color:#0084ff;}
|
84 |
-
div.buy-full .box a.button {-webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px;font-size:18px; color:#ffffff; text-shadow:0px 2px 2px rgba(0, 0, 0, 0.4); display:block; height:45px; line-height:45px; text-align:center; background: transparent url(../images/button-bg.png) repeat-x left top; border:none; text-decoration:none; clear:both;}
|
85 |
-
div.buy-full .box a.button:hover {background-position:left bottom;}
|
86 |
-
div.buy-full .box div.bottom {background-color:#ececec; padding:15px; width:255px; margin:19px 0 0 -15px;}
|
87 |
-
|
88 |
-
div.buy-full .box.first div.bottom {height:75px; line-height:75px; text-align:center; padding-top:0px; padding-bottom:0px;}
|
89 |
-
div.buy-full .box.first div.bottom p {line-height:75px; text-align:center; padding:0px; margin:0px;}
|
90 |
-
div.buy-full .box small.bottom {color:#666666; font-size:12px; display:block; text-align:center; float:none;}
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
97 |
-
div.buy-full .box p {padding:13px 20px 10px 20px;}
|
98 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
css/sbc-shortcode.css
DELETED
@@ -1,17 +0,0 @@
|
|
1 |
-
@CHARSET "UTF-8";
|
2 |
-
|
3 |
-
/* ----- Token Metabox ----- */
|
4 |
-
#sbc-metabox h4 {
|
5 |
-
border-bottom: 1px dashed #dfdfdf;
|
6 |
-
font-size: 14px;
|
7 |
-
margin: 0;
|
8 |
-
padding: 10px 0;
|
9 |
-
}
|
10 |
-
|
11 |
-
#sbc-metabox .form-table th {
|
12 |
-
vertical-align: middle;
|
13 |
-
}
|
14 |
-
|
15 |
-
#sbc-metabox .form-table th.top {
|
16 |
-
vertical-align: top;
|
17 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
css/sbc.css
DELETED
@@ -1,171 +0,0 @@
|
|
1 |
-
@CHARSET "UTF-8";
|
2 |
-
|
3 |
-
#sbc-calendar-wrapper {
|
4 |
-
font-family: Arial, Helvetica, sans-serif;
|
5 |
-
font-size: 12px;
|
6 |
-
clear: both;
|
7 |
-
overflow: hidden;
|
8 |
-
}
|
9 |
-
|
10 |
-
#sbc-calendar-wrapper, #sbc-calendar-wrapper * {
|
11 |
-
-webkit-box-sizing: content-box; /* Safari/Chrome, other WebKit */
|
12 |
-
-moz-box-sizing: content-box; /* Firefox, other Gecko */
|
13 |
-
box-sizing: content-box;
|
14 |
-
}
|
15 |
-
|
16 |
-
#sbc-calendar-wrapper .sbc-status-free {
|
17 |
-
background-color: #dfc;
|
18 |
-
}
|
19 |
-
|
20 |
-
#sbc-calendar-wrapper .sbc-status-booked {
|
21 |
-
background-color: #ffc0bd;
|
22 |
-
}
|
23 |
-
|
24 |
-
#sbc-calendar-wrapper .sbc-status-changeover {
|
25 |
-
background-color: #fee2a0;
|
26 |
-
}
|
27 |
-
|
28 |
-
#sbc-calendar-wrapper table {
|
29 |
-
border: 0;
|
30 |
-
border-collapse: separate;
|
31 |
-
border-spacing: 2px;
|
32 |
-
table-layout: fixed;
|
33 |
-
margin: 0;
|
34 |
-
-webkit-border-radius: 0px;
|
35 |
-
-moz-border-radius: 0px;
|
36 |
-
border-radius: 0px;
|
37 |
-
padding: 0;
|
38 |
-
}
|
39 |
-
#sbc-calendar-wrapper table tr, #sbc-calendar-wrapper table th {
|
40 |
-
background: none !important;
|
41 |
-
}
|
42 |
-
|
43 |
-
#sbc-calendar-wrapper table tr td {
|
44 |
-
border: 0;
|
45 |
-
padding: 0;
|
46 |
-
line-height: 12px;
|
47 |
-
vertical-align: middle;
|
48 |
-
}
|
49 |
-
|
50 |
-
#sbc-calendar {
|
51 |
-
float: left;
|
52 |
-
margin: 0 5px 30px 0;
|
53 |
-
}
|
54 |
-
|
55 |
-
#sbc-calendar table thead th
|
56 |
-
{
|
57 |
-
text-transform: uppercase;
|
58 |
-
}
|
59 |
-
|
60 |
-
.sbc-calendar-month {
|
61 |
-
float: left;
|
62 |
-
padding: 10px;
|
63 |
-
width: 172px;
|
64 |
-
border: 1px solid #ccc;
|
65 |
-
background-color: #fff;
|
66 |
-
margin-right: 10px;
|
67 |
-
}
|
68 |
-
|
69 |
-
#sbc-calendar .sbc-navigation {
|
70 |
-
padding-bottom: 10px;
|
71 |
-
line-height: 21px;
|
72 |
-
}
|
73 |
-
|
74 |
-
#sbc-calendar .sbc-navigation select {
|
75 |
-
margin: 0; padding: 0 !important; width: auto; height: auto; font-size: 12px;
|
76 |
-
}
|
77 |
-
|
78 |
-
#sbc-calendar form {margin: 0 !important;}
|
79 |
-
|
80 |
-
#sbc-calendar .sbc-loader {
|
81 |
-
background-color: #ffc0bd;
|
82 |
-
font-weight: bold;
|
83 |
-
margin: 4px 0;
|
84 |
-
padding: 1px 0;
|
85 |
-
text-align: center;
|
86 |
-
visibility: hidden;
|
87 |
-
}
|
88 |
-
|
89 |
-
#sbc-calendar .sbc-loader-visible {
|
90 |
-
visibility: visible;
|
91 |
-
}
|
92 |
-
|
93 |
-
#sbc-calendar table {
|
94 |
-
border-top: 1px solid #000;
|
95 |
-
}
|
96 |
-
|
97 |
-
#sbc-calendar table thead th,#sbc-calendar tr td {
|
98 |
-
color: #333;
|
99 |
-
font-family: Arial, Helvetica, sans-serif;
|
100 |
-
font-size: 12px;
|
101 |
-
text-align: center;
|
102 |
-
line-height: 16px;
|
103 |
-
padding: 8px 0 4px;
|
104 |
-
width: 22px;
|
105 |
-
height: 22px;
|
106 |
-
border:none;
|
107 |
-
}
|
108 |
-
|
109 |
-
#sbc-calendar table tfoot td {
|
110 |
-
padding-top: 5px;
|
111 |
-
text-align: left;
|
112 |
-
}
|
113 |
-
|
114 |
-
#sbc-calendar tr td {
|
115 |
-
border: 1px solid #fff;
|
116 |
-
padding: 2px 0;
|
117 |
-
}
|
118 |
-
|
119 |
-
#sbc-calendar tr td.pad {
|
120 |
-
width: auto;
|
121 |
-
}
|
122 |
-
|
123 |
-
#sbc-calendar td.sbc-status-free {
|
124 |
-
border-color: #dfc;
|
125 |
-
}
|
126 |
-
|
127 |
-
#sbc-calendar td.sbc-status-booked {
|
128 |
-
border-color: #ffc0bd;
|
129 |
-
}
|
130 |
-
|
131 |
-
#sbc-calendar td.sbc-status-changeover {
|
132 |
-
border-color: #fee2a0;
|
133 |
-
}
|
134 |
-
|
135 |
-
#sbc-calendar td.sbc-today {
|
136 |
-
border-color: #aeaeae
|
137 |
-
}
|
138 |
-
|
139 |
-
#sbc-editor {
|
140 |
-
border: 1px solid #ccc;
|
141 |
-
float: left;
|
142 |
-
padding: 5px;
|
143 |
-
background-color:#ffffff;
|
144 |
-
}
|
145 |
-
|
146 |
-
#sbc-editor td.sbc-editor-day {
|
147 |
-
font-family: Arial, Helvetica, sans-serif;
|
148 |
-
font-size: 12px;
|
149 |
-
text-align: center;
|
150 |
-
width: 25px;
|
151 |
-
}
|
152 |
-
|
153 |
-
#sbc-editor td.sbc-editor-status select {
|
154 |
-
width: 120px;
|
155 |
-
height:auto !important;
|
156 |
-
}
|
157 |
-
|
158 |
-
|
159 |
-
.widget-sbc #sbc-calendar {
|
160 |
-
float: none;
|
161 |
-
margin: 0 0 10px 0;
|
162 |
-
}
|
163 |
-
|
164 |
-
.alignRight {
|
165 |
-
text-align: right !important;
|
166 |
-
}
|
167 |
-
|
168 |
-
span.powered-by {width:192px; text-align:center; padding-top:3px; clear:both; }
|
169 |
-
|
170 |
-
div#sbc-calendar-wrapper p { padding:0 !important;}
|
171 |
-
div#sbc-calendar-wrapper br {display:none !important;}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
images/button-bg.png
DELETED
Binary file
|
images/checked-icon.jpg
DELETED
Binary file
|
images/checked.png
DELETED
Binary file
|
includes/abstracts/abstract-class-db.php
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Base class for all core database objects.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
abstract class WPSBC_DB {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Database table name
|
15 |
+
*
|
16 |
+
* @access public
|
17 |
+
* @var string
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
public $table_name;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Primary key of the table
|
24 |
+
*
|
25 |
+
* @access public
|
26 |
+
* @var string
|
27 |
+
*
|
28 |
+
*/
|
29 |
+
public $primary_key;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The context of the object affected
|
33 |
+
*
|
34 |
+
* @access public
|
35 |
+
* @var string
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
public $context = '';
|
39 |
+
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Constructor
|
43 |
+
*
|
44 |
+
* Subclasses should set the $table_name, $primary_key, $context
|
45 |
+
*
|
46 |
+
* @access public
|
47 |
+
*
|
48 |
+
*/
|
49 |
+
public function __construct() {}
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Retrieves the list of columns for the database table
|
54 |
+
*
|
55 |
+
* @access public
|
56 |
+
*
|
57 |
+
* @return array
|
58 |
+
*
|
59 |
+
*/
|
60 |
+
public function get_columns() {
|
61 |
+
|
62 |
+
return array();
|
63 |
+
|
64 |
+
}
|
65 |
+
|
66 |
+
}
|
includes/abstracts/abstract-class-list-table.php
ADDED
@@ -0,0 +1,1373 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Copy of WordPress's WP_List_Table class
|
8 |
+
*
|
9 |
+
* Base class for displaying a list of items in an ajaxified HTML table.
|
10 |
+
*
|
11 |
+
*/
|
12 |
+
abstract class WPSBC_WP_List_Table {
|
13 |
+
|
14 |
+
/**
|
15 |
+
* The current list of items.
|
16 |
+
*
|
17 |
+
* @since 3.1.0
|
18 |
+
* @access public
|
19 |
+
* @var array
|
20 |
+
*/
|
21 |
+
public $items;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Various information about the current table.
|
25 |
+
*
|
26 |
+
* @since 3.1.0
|
27 |
+
* @access protected
|
28 |
+
* @var array
|
29 |
+
*/
|
30 |
+
protected $_args;
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Various information needed for displaying the pagination.
|
34 |
+
*
|
35 |
+
* @since 3.1.0
|
36 |
+
* @access protected
|
37 |
+
* @var array
|
38 |
+
*/
|
39 |
+
protected $_pagination_args = array();
|
40 |
+
|
41 |
+
/**
|
42 |
+
* The current screen.
|
43 |
+
*
|
44 |
+
* @since 3.1.0
|
45 |
+
* @access protected
|
46 |
+
* @var object
|
47 |
+
*/
|
48 |
+
protected $screen;
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Cached bulk actions.
|
52 |
+
*
|
53 |
+
* @since 3.1.0
|
54 |
+
* @access private
|
55 |
+
* @var array
|
56 |
+
*/
|
57 |
+
private $_actions;
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Cached pagination output.
|
61 |
+
*
|
62 |
+
* @since 3.1.0
|
63 |
+
* @access private
|
64 |
+
* @var string
|
65 |
+
*/
|
66 |
+
private $_pagination;
|
67 |
+
|
68 |
+
/**
|
69 |
+
* The view switcher modes.
|
70 |
+
*
|
71 |
+
* @since 4.1.0
|
72 |
+
* @access protected
|
73 |
+
* @var array
|
74 |
+
*/
|
75 |
+
protected $modes = array();
|
76 |
+
|
77 |
+
/**
|
78 |
+
* Stores the value returned by ->get_column_info().
|
79 |
+
*
|
80 |
+
* @since 4.1.0
|
81 |
+
* @access protected
|
82 |
+
* @var array
|
83 |
+
*/
|
84 |
+
protected $_column_headers;
|
85 |
+
|
86 |
+
/**
|
87 |
+
* {@internal Missing Summary}
|
88 |
+
*
|
89 |
+
* @access protected
|
90 |
+
* @var array
|
91 |
+
*/
|
92 |
+
protected $compat_fields = array( '_args', '_pagination_args', 'screen', '_actions', '_pagination' );
|
93 |
+
|
94 |
+
/**
|
95 |
+
* {@internal Missing Summary}
|
96 |
+
*
|
97 |
+
* @access protected
|
98 |
+
* @var array
|
99 |
+
*/
|
100 |
+
protected $compat_methods = array( 'set_pagination_args', 'get_views', 'get_bulk_actions', 'bulk_actions',
|
101 |
+
'row_actions', 'months_dropdown', 'view_switcher', 'comments_bubble', 'get_items_per_page', 'pagination',
|
102 |
+
'get_sortable_columns', 'get_column_info', 'get_table_classes', 'display_tablenav', 'extra_tablenav',
|
103 |
+
'single_row_columns' );
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Constructor.
|
107 |
+
*
|
108 |
+
* The child class should call this constructor from its own constructor to override
|
109 |
+
* the default $args.
|
110 |
+
*
|
111 |
+
* @since 3.1.0
|
112 |
+
* @access public
|
113 |
+
*
|
114 |
+
* @param array|string $args {
|
115 |
+
* Array or string of arguments.
|
116 |
+
*
|
117 |
+
* @type string $plural Plural value used for labels and the objects being listed.
|
118 |
+
* This affects things such as CSS class-names and nonces used
|
119 |
+
* in the list table, e.g. 'posts'. Default empty.
|
120 |
+
* @type string $singular Singular label for an object being listed, e.g. 'post'.
|
121 |
+
* Default empty
|
122 |
+
* @type bool $ajax Whether the list table supports Ajax. This includes loading
|
123 |
+
* and sorting data, for example. If true, the class will call
|
124 |
+
* the _js_vars() method in the footer to provide variables
|
125 |
+
* to any scripts handling Ajax events. Default false.
|
126 |
+
* @type string $screen String containing the hook name used to determine the current
|
127 |
+
* screen. If left null, the current screen will be automatically set.
|
128 |
+
* Default null.
|
129 |
+
* }
|
130 |
+
*/
|
131 |
+
public function __construct( $args = array() ) {
|
132 |
+
$args = wp_parse_args( $args, array(
|
133 |
+
'plural' => '',
|
134 |
+
'singular' => '',
|
135 |
+
'ajax' => false,
|
136 |
+
'screen' => null,
|
137 |
+
) );
|
138 |
+
|
139 |
+
$this->screen = convert_to_screen( $args['screen'] );
|
140 |
+
|
141 |
+
add_filter( "manage_{$this->screen->id}_columns", array( $this, 'get_columns' ), 0 );
|
142 |
+
|
143 |
+
if ( !$args['plural'] )
|
144 |
+
$args['plural'] = $this->screen->base;
|
145 |
+
|
146 |
+
$args['plural'] = sanitize_key( $args['plural'] );
|
147 |
+
$args['singular'] = sanitize_key( $args['singular'] );
|
148 |
+
|
149 |
+
$this->_args = $args;
|
150 |
+
|
151 |
+
if ( $args['ajax'] ) {
|
152 |
+
// wp_enqueue_script( 'list-table' );
|
153 |
+
add_action( 'admin_footer', array( $this, '_js_vars' ) );
|
154 |
+
}
|
155 |
+
|
156 |
+
if ( empty( $this->modes ) ) {
|
157 |
+
$this->modes = array(
|
158 |
+
'list' => __( 'List View' ),
|
159 |
+
'excerpt' => __( 'Excerpt View' )
|
160 |
+
);
|
161 |
+
}
|
162 |
+
}
|
163 |
+
|
164 |
+
/**
|
165 |
+
* Make private properties readable for backward compatibility.
|
166 |
+
*
|
167 |
+
* @since 4.0.0
|
168 |
+
* @access public
|
169 |
+
*
|
170 |
+
* @param string $name Property to get.
|
171 |
+
* @return mixed Property.
|
172 |
+
*/
|
173 |
+
public function __get( $name ) {
|
174 |
+
if ( in_array( $name, $this->compat_fields ) ) {
|
175 |
+
return $this->$name;
|
176 |
+
}
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Make private properties settable for backward compatibility.
|
181 |
+
*
|
182 |
+
* @since 4.0.0
|
183 |
+
* @access public
|
184 |
+
*
|
185 |
+
* @param string $name Property to check if set.
|
186 |
+
* @param mixed $value Property value.
|
187 |
+
* @return mixed Newly-set property.
|
188 |
+
*/
|
189 |
+
public function __set( $name, $value ) {
|
190 |
+
if ( in_array( $name, $this->compat_fields ) ) {
|
191 |
+
return $this->$name = $value;
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
/**
|
196 |
+
* Make private properties checkable for backward compatibility.
|
197 |
+
*
|
198 |
+
* @since 4.0.0
|
199 |
+
* @access public
|
200 |
+
*
|
201 |
+
* @param string $name Property to check if set.
|
202 |
+
* @return bool Whether the property is set.
|
203 |
+
*/
|
204 |
+
public function __isset( $name ) {
|
205 |
+
if ( in_array( $name, $this->compat_fields ) ) {
|
206 |
+
return isset( $this->$name );
|
207 |
+
}
|
208 |
+
}
|
209 |
+
|
210 |
+
/**
|
211 |
+
* Make private properties un-settable for backward compatibility.
|
212 |
+
*
|
213 |
+
* @since 4.0.0
|
214 |
+
* @access public
|
215 |
+
*
|
216 |
+
* @param string $name Property to unset.
|
217 |
+
*/
|
218 |
+
public function __unset( $name ) {
|
219 |
+
if ( in_array( $name, $this->compat_fields ) ) {
|
220 |
+
unset( $this->$name );
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Make private/protected methods readable for backward compatibility.
|
226 |
+
*
|
227 |
+
* @since 4.0.0
|
228 |
+
* @access public
|
229 |
+
*
|
230 |
+
* @param callable $name Method to call.
|
231 |
+
* @param array $arguments Arguments to pass when calling.
|
232 |
+
* @return mixed|bool Return value of the callback, false otherwise.
|
233 |
+
*/
|
234 |
+
public function __call( $name, $arguments ) {
|
235 |
+
if ( in_array( $name, $this->compat_methods ) ) {
|
236 |
+
return call_user_func_array( array( $this, $name ), $arguments );
|
237 |
+
}
|
238 |
+
return false;
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Checks the current user's permissions
|
243 |
+
*
|
244 |
+
* @since 3.1.0
|
245 |
+
* @access public
|
246 |
+
* @abstract
|
247 |
+
*/
|
248 |
+
public function ajax_user_can() {
|
249 |
+
die( 'function WP_List_Table::ajax_user_can() must be over-ridden in a sub-class.' );
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Prepares the list of items for displaying.
|
254 |
+
* @uses WP_List_Table::set_pagination_args()
|
255 |
+
*
|
256 |
+
* @since 3.1.0
|
257 |
+
* @access public
|
258 |
+
* @abstract
|
259 |
+
*/
|
260 |
+
public function prepare_items() {
|
261 |
+
die( 'function WP_List_Table::prepare_items() must be over-ridden in a sub-class.' );
|
262 |
+
}
|
263 |
+
|
264 |
+
/**
|
265 |
+
* An internal method that sets all the necessary pagination arguments
|
266 |
+
*
|
267 |
+
* @since 3.1.0
|
268 |
+
* @access protected
|
269 |
+
*
|
270 |
+
* @param array|string $args Array or string of arguments with information about the pagination.
|
271 |
+
*/
|
272 |
+
protected function set_pagination_args( $args ) {
|
273 |
+
$args = wp_parse_args( $args, array(
|
274 |
+
'total_items' => 0,
|
275 |
+
'total_pages' => 0,
|
276 |
+
'per_page' => 0,
|
277 |
+
) );
|
278 |
+
|
279 |
+
if ( !$args['total_pages'] && $args['per_page'] > 0 )
|
280 |
+
$args['total_pages'] = ceil( $args['total_items'] / $args['per_page'] );
|
281 |
+
|
282 |
+
// Redirect if page number is invalid and headers are not already sent.
|
283 |
+
if ( ! headers_sent() && ! wp_doing_ajax() && $args['total_pages'] > 0 && $this->get_pagenum() > $args['total_pages'] ) {
|
284 |
+
wp_redirect( add_query_arg( 'paged', $args['total_pages'] ) );
|
285 |
+
exit;
|
286 |
+
}
|
287 |
+
|
288 |
+
$this->_pagination_args = $args;
|
289 |
+
}
|
290 |
+
|
291 |
+
/**
|
292 |
+
* Access the pagination args.
|
293 |
+
*
|
294 |
+
* @since 3.1.0
|
295 |
+
* @access public
|
296 |
+
*
|
297 |
+
* @param string $key Pagination argument to retrieve. Common values include 'total_items',
|
298 |
+
* 'total_pages', 'per_page', or 'infinite_scroll'.
|
299 |
+
* @return int Number of items that correspond to the given pagination argument.
|
300 |
+
*/
|
301 |
+
public function get_pagination_arg( $key ) {
|
302 |
+
if ( 'page' === $key ) {
|
303 |
+
return $this->get_pagenum();
|
304 |
+
}
|
305 |
+
|
306 |
+
if ( isset( $this->_pagination_args[$key] ) ) {
|
307 |
+
return $this->_pagination_args[$key];
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Whether the table has items to display or not
|
313 |
+
*
|
314 |
+
* @since 3.1.0
|
315 |
+
* @access public
|
316 |
+
*
|
317 |
+
* @return bool
|
318 |
+
*/
|
319 |
+
public function has_items() {
|
320 |
+
return !empty( $this->items );
|
321 |
+
}
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Message to be displayed when there are no items
|
325 |
+
*
|
326 |
+
* @since 3.1.0
|
327 |
+
* @access public
|
328 |
+
*/
|
329 |
+
public function no_items() {
|
330 |
+
_e( 'No items found.' );
|
331 |
+
}
|
332 |
+
|
333 |
+
/**
|
334 |
+
* Displays the search box.
|
335 |
+
*
|
336 |
+
* @since 3.1.0
|
337 |
+
* @access public
|
338 |
+
*
|
339 |
+
* @param string $text The 'submit' button label.
|
340 |
+
* @param string $input_id ID attribute value for the search input field.
|
341 |
+
*/
|
342 |
+
public function search_box( $text, $input_id ) {
|
343 |
+
if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
|
344 |
+
return;
|
345 |
+
|
346 |
+
$input_id = $input_id . '-search-input';
|
347 |
+
|
348 |
+
if ( ! empty( $_REQUEST['orderby'] ) )
|
349 |
+
echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
|
350 |
+
if ( ! empty( $_REQUEST['order'] ) )
|
351 |
+
echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
|
352 |
+
if ( ! empty( $_REQUEST['post_mime_type'] ) )
|
353 |
+
echo '<input type="hidden" name="post_mime_type" value="' . esc_attr( $_REQUEST['post_mime_type'] ) . '" />';
|
354 |
+
if ( ! empty( $_REQUEST['detached'] ) )
|
355 |
+
echo '<input type="hidden" name="detached" value="' . esc_attr( $_REQUEST['detached'] ) . '" />';
|
356 |
+
?>
|
357 |
+
<p class="search-box">
|
358 |
+
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo $text; ?>:</label>
|
359 |
+
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>" />
|
360 |
+
<?php submit_button( $text, '', '', false, array( 'id' => 'search-submit' ) ); ?>
|
361 |
+
</p>
|
362 |
+
<?php
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Get an associative array ( id => link ) with the list
|
367 |
+
* of views available on this table.
|
368 |
+
*
|
369 |
+
* @since 3.1.0
|
370 |
+
* @access protected
|
371 |
+
*
|
372 |
+
* @return array
|
373 |
+
*/
|
374 |
+
protected function get_views() {
|
375 |
+
return array();
|
376 |
+
}
|
377 |
+
|
378 |
+
/**
|
379 |
+
* Display the list of views available on this table.
|
380 |
+
*
|
381 |
+
* @since 3.1.0
|
382 |
+
* @access public
|
383 |
+
*/
|
384 |
+
public function views() {
|
385 |
+
$views = $this->get_views();
|
386 |
+
/**
|
387 |
+
* Filters the list of available list table views.
|
388 |
+
*
|
389 |
+
* The dynamic portion of the hook name, `$this->screen->id`, refers
|
390 |
+
* to the ID of the current screen, usually a string.
|
391 |
+
*
|
392 |
+
* @since 3.5.0
|
393 |
+
*
|
394 |
+
* @param array $views An array of available list table views.
|
395 |
+
*/
|
396 |
+
$views = apply_filters( "views_{$this->screen->id}", $views );
|
397 |
+
|
398 |
+
if ( empty( $views ) )
|
399 |
+
return;
|
400 |
+
|
401 |
+
$this->screen->render_screen_reader_content( 'heading_views' );
|
402 |
+
|
403 |
+
echo "<ul class='subsubsub'>\n";
|
404 |
+
foreach ( $views as $class => $view ) {
|
405 |
+
$views[ $class ] = "\t<li class='$class'>$view";
|
406 |
+
}
|
407 |
+
echo implode( " |</li>\n", $views ) . "</li>\n";
|
408 |
+
echo "</ul>";
|
409 |
+
}
|
410 |
+
|
411 |
+
/**
|
412 |
+
* Get an associative array ( option_name => option_title ) with the list
|
413 |
+
* of bulk actions available on this table.
|
414 |
+
*
|
415 |
+
* @since 3.1.0
|
416 |
+
* @access protected
|
417 |
+
*
|
418 |
+
* @return array
|
419 |
+
*/
|
420 |
+
protected function get_bulk_actions() {
|
421 |
+
return array();
|
422 |
+
}
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Display the bulk actions dropdown.
|
426 |
+
*
|
427 |
+
* @since 3.1.0
|
428 |
+
* @access protected
|
429 |
+
*
|
430 |
+
* @param string $which The location of the bulk actions: 'top' or 'bottom'.
|
431 |
+
* This is designated as optional for backward compatibility.
|
432 |
+
*/
|
433 |
+
protected function bulk_actions( $which = '' ) {
|
434 |
+
if ( is_null( $this->_actions ) ) {
|
435 |
+
$this->_actions = $this->get_bulk_actions();
|
436 |
+
/**
|
437 |
+
* Filters the list table Bulk Actions drop-down.
|
438 |
+
*
|
439 |
+
* The dynamic portion of the hook name, `$this->screen->id`, refers
|
440 |
+
* to the ID of the current screen, usually a string.
|
441 |
+
*
|
442 |
+
* This filter can currently only be used to remove bulk actions.
|
443 |
+
*
|
444 |
+
* @since 3.5.0
|
445 |
+
*
|
446 |
+
* @param array $actions An array of the available bulk actions.
|
447 |
+
*/
|
448 |
+
$this->_actions = apply_filters( "bulk_actions-{$this->screen->id}", $this->_actions );
|
449 |
+
$two = '';
|
450 |
+
} else {
|
451 |
+
$two = '2';
|
452 |
+
}
|
453 |
+
|
454 |
+
if ( empty( $this->_actions ) )
|
455 |
+
return;
|
456 |
+
|
457 |
+
echo '<label for="bulk-action-selector-' . esc_attr( $which ) . '" class="screen-reader-text">' . __( 'Select bulk action' ) . '</label>';
|
458 |
+
echo '<select name="action' . $two . '" id="bulk-action-selector-' . esc_attr( $which ) . "\">\n";
|
459 |
+
echo '<option value="-1">' . __( 'Bulk Actions' ) . "</option>\n";
|
460 |
+
|
461 |
+
foreach ( $this->_actions as $name => $title ) {
|
462 |
+
$class = 'edit' === $name ? ' class="hide-if-no-js"' : '';
|
463 |
+
|
464 |
+
echo "\t" . '<option value="' . $name . '"' . $class . '>' . $title . "</option>\n";
|
465 |
+
}
|
466 |
+
|
467 |
+
echo "</select>\n";
|
468 |
+
|
469 |
+
submit_button( __( 'Apply' ), 'action', '', false, array( 'id' => "doaction$two" ) );
|
470 |
+
echo "\n";
|
471 |
+
}
|
472 |
+
|
473 |
+
/**
|
474 |
+
* Get the current action selected from the bulk actions dropdown.
|
475 |
+
*
|
476 |
+
* @since 3.1.0
|
477 |
+
* @access public
|
478 |
+
*
|
479 |
+
* @return string|false The action name or False if no action was selected
|
480 |
+
*/
|
481 |
+
public function current_action() {
|
482 |
+
if ( isset( $_REQUEST['filter_action'] ) && ! empty( $_REQUEST['filter_action'] ) )
|
483 |
+
return false;
|
484 |
+
|
485 |
+
if ( isset( $_REQUEST['action'] ) && -1 != $_REQUEST['action'] )
|
486 |
+
return $_REQUEST['action'];
|
487 |
+
|
488 |
+
if ( isset( $_REQUEST['action2'] ) && -1 != $_REQUEST['action2'] )
|
489 |
+
return $_REQUEST['action2'];
|
490 |
+
|
491 |
+
return false;
|
492 |
+
}
|
493 |
+
|
494 |
+
/**
|
495 |
+
* Generate row actions div
|
496 |
+
*
|
497 |
+
* @since 3.1.0
|
498 |
+
* @access protected
|
499 |
+
*
|
500 |
+
* @param array $actions The list of actions
|
501 |
+
* @param bool $always_visible Whether the actions should be always visible
|
502 |
+
* @return string
|
503 |
+
*/
|
504 |
+
protected function row_actions( $actions, $always_visible = false ) {
|
505 |
+
$action_count = count( $actions );
|
506 |
+
$i = 0;
|
507 |
+
|
508 |
+
if ( !$action_count )
|
509 |
+
return '';
|
510 |
+
|
511 |
+
$out = '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
|
512 |
+
foreach ( $actions as $action => $link ) {
|
513 |
+
++$i;
|
514 |
+
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
|
515 |
+
$out .= "<span class='$action'>$link$sep</span>";
|
516 |
+
}
|
517 |
+
$out .= '</div>';
|
518 |
+
|
519 |
+
$out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>';
|
520 |
+
|
521 |
+
return $out;
|
522 |
+
}
|
523 |
+
|
524 |
+
/**
|
525 |
+
* Display a monthly dropdown for filtering items
|
526 |
+
*
|
527 |
+
* @since 3.1.0
|
528 |
+
* @access protected
|
529 |
+
*
|
530 |
+
* @global wpdb $wpdb
|
531 |
+
* @global WP_Locale $wp_locale
|
532 |
+
*
|
533 |
+
* @param string $post_type
|
534 |
+
*/
|
535 |
+
protected function months_dropdown( $post_type ) {
|
536 |
+
global $wpdb, $wp_locale;
|
537 |
+
|
538 |
+
/**
|
539 |
+
* Filters whether to remove the 'Months' drop-down from the post list table.
|
540 |
+
*
|
541 |
+
* @since 4.2.0
|
542 |
+
*
|
543 |
+
* @param bool $disable Whether to disable the drop-down. Default false.
|
544 |
+
* @param string $post_type The post type.
|
545 |
+
*/
|
546 |
+
if ( apply_filters( 'disable_months_dropdown', false, $post_type ) ) {
|
547 |
+
return;
|
548 |
+
}
|
549 |
+
|
550 |
+
$extra_checks = "AND post_status != 'auto-draft'";
|
551 |
+
if ( ! isset( $_GET['post_status'] ) || 'trash' !== $_GET['post_status'] ) {
|
552 |
+
$extra_checks .= " AND post_status != 'trash'";
|
553 |
+
} elseif ( isset( $_GET['post_status'] ) ) {
|
554 |
+
$extra_checks = $wpdb->prepare( ' AND post_status = %s', $_GET['post_status'] );
|
555 |
+
}
|
556 |
+
|
557 |
+
$months = $wpdb->get_results( $wpdb->prepare( "
|
558 |
+
SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
|
559 |
+
FROM $wpdb->posts
|
560 |
+
WHERE post_type = %s
|
561 |
+
$extra_checks
|
562 |
+
ORDER BY post_date DESC
|
563 |
+
", $post_type ) );
|
564 |
+
|
565 |
+
/**
|
566 |
+
* Filters the 'Months' drop-down results.
|
567 |
+
*
|
568 |
+
* @since 3.7.0
|
569 |
+
*
|
570 |
+
* @param object $months The months drop-down query results.
|
571 |
+
* @param string $post_type The post type.
|
572 |
+
*/
|
573 |
+
$months = apply_filters( 'months_dropdown_results', $months, $post_type );
|
574 |
+
|
575 |
+
$month_count = count( $months );
|
576 |
+
|
577 |
+
if ( !$month_count || ( 1 == $month_count && 0 == $months[0]->month ) )
|
578 |
+
return;
|
579 |
+
|
580 |
+
$m = isset( $_GET['m'] ) ? (int) $_GET['m'] : 0;
|
581 |
+
?>
|
582 |
+
<label for="filter-by-date" class="screen-reader-text"><?php _e( 'Filter by date' ); ?></label>
|
583 |
+
<select name="m" id="filter-by-date">
|
584 |
+
<option<?php selected( $m, 0 ); ?> value="0"><?php _e( 'All dates' ); ?></option>
|
585 |
+
<?php
|
586 |
+
foreach ( $months as $arc_row ) {
|
587 |
+
if ( 0 == $arc_row->year )
|
588 |
+
continue;
|
589 |
+
|
590 |
+
$month = zeroise( $arc_row->month, 2 );
|
591 |
+
$year = $arc_row->year;
|
592 |
+
|
593 |
+
printf( "<option %s value='%s'>%s</option>\n",
|
594 |
+
selected( $m, $year . $month, false ),
|
595 |
+
esc_attr( $arc_row->year . $month ),
|
596 |
+
/* translators: 1: month name, 2: 4-digit year */
|
597 |
+
sprintf( __( '%1$s %2$d' ), $wp_locale->get_month( $month ), $year )
|
598 |
+
);
|
599 |
+
}
|
600 |
+
?>
|
601 |
+
</select>
|
602 |
+
<?php
|
603 |
+
}
|
604 |
+
|
605 |
+
/**
|
606 |
+
* Display a view switcher
|
607 |
+
*
|
608 |
+
* @since 3.1.0
|
609 |
+
* @access protected
|
610 |
+
*
|
611 |
+
* @param string $current_mode
|
612 |
+
*/
|
613 |
+
protected function view_switcher( $current_mode ) {
|
614 |
+
?>
|
615 |
+
<input type="hidden" name="mode" value="<?php echo esc_attr( $current_mode ); ?>" />
|
616 |
+
<div class="view-switch">
|
617 |
+
<?php
|
618 |
+
foreach ( $this->modes as $mode => $title ) {
|
619 |
+
$classes = array( 'view-' . $mode );
|
620 |
+
if ( $current_mode === $mode )
|
621 |
+
$classes[] = 'current';
|
622 |
+
printf(
|
623 |
+
"<a href='%s' class='%s' id='view-switch-$mode'><span class='screen-reader-text'>%s</span></a>\n",
|
624 |
+
esc_url( add_query_arg( 'mode', $mode ) ),
|
625 |
+
implode( ' ', $classes ),
|
626 |
+
$title
|
627 |
+
);
|
628 |
+
}
|
629 |
+
?>
|
630 |
+
</div>
|
631 |
+
<?php
|
632 |
+
}
|
633 |
+
|
634 |
+
/**
|
635 |
+
* Display a comment count bubble
|
636 |
+
*
|
637 |
+
* @since 3.1.0
|
638 |
+
* @access protected
|
639 |
+
*
|
640 |
+
* @param int $post_id The post ID.
|
641 |
+
* @param int $pending_comments Number of pending comments.
|
642 |
+
*/
|
643 |
+
protected function comments_bubble( $post_id, $pending_comments ) {
|
644 |
+
$approved_comments = get_comments_number();
|
645 |
+
|
646 |
+
$approved_comments_number = number_format_i18n( $approved_comments );
|
647 |
+
$pending_comments_number = number_format_i18n( $pending_comments );
|
648 |
+
|
649 |
+
$approved_only_phrase = sprintf( _n( '%s comment', '%s comments', $approved_comments ), $approved_comments_number );
|
650 |
+
$approved_phrase = sprintf( _n( '%s approved comment', '%s approved comments', $approved_comments ), $approved_comments_number );
|
651 |
+
$pending_phrase = sprintf( _n( '%s pending comment', '%s pending comments', $pending_comments ), $pending_comments_number );
|
652 |
+
|
653 |
+
// No comments at all.
|
654 |
+
if ( ! $approved_comments && ! $pending_comments ) {
|
655 |
+
printf( '<span aria-hidden="true">—</span><span class="screen-reader-text">%s</span>',
|
656 |
+
__( 'No comments' )
|
657 |
+
);
|
658 |
+
// Approved comments have different display depending on some conditions.
|
659 |
+
} elseif ( $approved_comments ) {
|
660 |
+
printf( '<a href="%s" class="post-com-count post-com-count-approved"><span class="comment-count-approved" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
|
661 |
+
esc_url( add_query_arg( array( 'p' => $post_id, 'comment_status' => 'approved' ), admin_url( 'edit-comments.php' ) ) ),
|
662 |
+
$approved_comments_number,
|
663 |
+
$pending_comments ? $approved_phrase : $approved_only_phrase
|
664 |
+
);
|
665 |
+
} else {
|
666 |
+
printf( '<span class="post-com-count post-com-count-no-comments"><span class="comment-count comment-count-no-comments" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
|
667 |
+
$approved_comments_number,
|
668 |
+
$pending_comments ? __( 'No approved comments' ) : __( 'No comments' )
|
669 |
+
);
|
670 |
+
}
|
671 |
+
|
672 |
+
if ( $pending_comments ) {
|
673 |
+
printf( '<a href="%s" class="post-com-count post-com-count-pending"><span class="comment-count-pending" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></a>',
|
674 |
+
esc_url( add_query_arg( array( 'p' => $post_id, 'comment_status' => 'moderated' ), admin_url( 'edit-comments.php' ) ) ),
|
675 |
+
$pending_comments_number,
|
676 |
+
$pending_phrase
|
677 |
+
);
|
678 |
+
} else {
|
679 |
+
printf( '<span class="post-com-count post-com-count-pending post-com-count-no-pending"><span class="comment-count comment-count-no-pending" aria-hidden="true">%s</span><span class="screen-reader-text">%s</span></span>',
|
680 |
+
$pending_comments_number,
|
681 |
+
$approved_comments ? __( 'No pending comments' ) : __( 'No comments' )
|
682 |
+
);
|
683 |
+
}
|
684 |
+
}
|
685 |
+
|
686 |
+
/**
|
687 |
+
* Get the current page number
|
688 |
+
*
|
689 |
+
* @since 3.1.0
|
690 |
+
* @access public
|
691 |
+
*
|
692 |
+
* @return int
|
693 |
+
*/
|
694 |
+
public function get_pagenum() {
|
695 |
+
$pagenum = isset( $_REQUEST['paged'] ) ? absint( $_REQUEST['paged'] ) : 0;
|
696 |
+
|
697 |
+
if ( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] )
|
698 |
+
$pagenum = $this->_pagination_args['total_pages'];
|
699 |
+
|
700 |
+
return max( 1, $pagenum );
|
701 |
+
}
|
702 |
+
|
703 |
+
/**
|
704 |
+
* Get number of items to display on a single page
|
705 |
+
*
|
706 |
+
* @since 3.1.0
|
707 |
+
* @access protected
|
708 |
+
*
|
709 |
+
* @param string $option
|
710 |
+
* @param int $default
|
711 |
+
* @return int
|
712 |
+
*/
|
713 |
+
protected function get_items_per_page( $option, $default = 20 ) {
|
714 |
+
$per_page = (int) get_user_option( $option );
|
715 |
+
if ( empty( $per_page ) || $per_page < 1 )
|
716 |
+
$per_page = $default;
|
717 |
+
|
718 |
+
/**
|
719 |
+
* Filters the number of items to be displayed on each page of the list table.
|
720 |
+
*
|
721 |
+
* The dynamic hook name, $option, refers to the `per_page` option depending
|
722 |
+
* on the type of list table in use. Possible values include: 'edit_comments_per_page',
|
723 |
+
* 'sites_network_per_page', 'site_themes_network_per_page', 'themes_network_per_page',
|
724 |
+
* 'users_network_per_page', 'edit_post_per_page', 'edit_page_per_page',
|
725 |
+
* 'edit_{$post_type}_per_page', etc.
|
726 |
+
*
|
727 |
+
* @since 2.9.0
|
728 |
+
*
|
729 |
+
* @param int $per_page Number of items to be displayed. Default 20.
|
730 |
+
*/
|
731 |
+
return (int) apply_filters( $option, $per_page );
|
732 |
+
}
|
733 |
+
|
734 |
+
/**
|
735 |
+
* Display the pagination.
|
736 |
+
*
|
737 |
+
* @since 3.1.0
|
738 |
+
* @access protected
|
739 |
+
*
|
740 |
+
* @param string $which
|
741 |
+
*/
|
742 |
+
protected function pagination( $which ) {
|
743 |
+
if ( empty( $this->_pagination_args ) ) {
|
744 |
+
return;
|
745 |
+
}
|
746 |
+
|
747 |
+
$total_items = $this->_pagination_args['total_items'];
|
748 |
+
$total_pages = $this->_pagination_args['total_pages'];
|
749 |
+
$infinite_scroll = false;
|
750 |
+
if ( isset( $this->_pagination_args['infinite_scroll'] ) ) {
|
751 |
+
$infinite_scroll = $this->_pagination_args['infinite_scroll'];
|
752 |
+
}
|
753 |
+
|
754 |
+
if ( 'top' === $which && $total_pages > 1 ) {
|
755 |
+
$this->screen->render_screen_reader_content( 'heading_pagination' );
|
756 |
+
}
|
757 |
+
|
758 |
+
$output = '<span class="displaying-num">' . sprintf( _n( '%s item', '%s items', $total_items ), number_format_i18n( $total_items ) ) . '</span>';
|
759 |
+
|
760 |
+
$current = $this->get_pagenum();
|
761 |
+
$removable_query_args = wp_removable_query_args();
|
762 |
+
|
763 |
+
$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
|
764 |
+
|
765 |
+
$current_url = remove_query_arg( $removable_query_args, $current_url );
|
766 |
+
|
767 |
+
$page_links = array();
|
768 |
+
|
769 |
+
$total_pages_before = '<span class="paging-input">';
|
770 |
+
$total_pages_after = '</span></span>';
|
771 |
+
|
772 |
+
$disable_first = $disable_last = $disable_prev = $disable_next = false;
|
773 |
+
|
774 |
+
if ( $current == 1 ) {
|
775 |
+
$disable_first = true;
|
776 |
+
$disable_prev = true;
|
777 |
+
}
|
778 |
+
if ( $current == 2 ) {
|
779 |
+
$disable_first = true;
|
780 |
+
}
|
781 |
+
if ( $current == $total_pages ) {
|
782 |
+
$disable_last = true;
|
783 |
+
$disable_next = true;
|
784 |
+
}
|
785 |
+
if ( $current == $total_pages - 1 ) {
|
786 |
+
$disable_last = true;
|
787 |
+
}
|
788 |
+
|
789 |
+
if ( $disable_first ) {
|
790 |
+
$page_links[] = '<span class="tablenav-pages-navspan button" aria-hidden="true">«</span>';
|
791 |
+
} else {
|
792 |
+
$page_links[] = sprintf( "<a class='first-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
793 |
+
esc_url( remove_query_arg( 'paged', $current_url ) ),
|
794 |
+
__( 'First page' ),
|
795 |
+
'«'
|
796 |
+
);
|
797 |
+
}
|
798 |
+
|
799 |
+
if ( $disable_prev ) {
|
800 |
+
$page_links[] = '<span class="tablenav-pages-navspan button" aria-hidden="true">‹</span>';
|
801 |
+
} else {
|
802 |
+
$page_links[] = sprintf( "<a class='prev-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
803 |
+
esc_url( add_query_arg( 'paged', max( 1, $current-1 ), $current_url ) ),
|
804 |
+
__( 'Previous page' ),
|
805 |
+
'‹'
|
806 |
+
);
|
807 |
+
}
|
808 |
+
|
809 |
+
if ( 'bottom' === $which ) {
|
810 |
+
$html_current_page = $current;
|
811 |
+
$total_pages_before = '<span class="screen-reader-text">' . __( 'Current Page' ) . '</span><span id="table-paging" class="paging-input"><span class="tablenav-paging-text">';
|
812 |
+
} else {
|
813 |
+
$html_current_page = sprintf( "%s<input class='current-page' id='current-page-selector' type='text' name='paged' value='%s' size='%d' aria-describedby='table-paging' /><span class='tablenav-paging-text'>",
|
814 |
+
'<label for="current-page-selector" class="screen-reader-text">' . __( 'Current Page' ) . '</label>',
|
815 |
+
$current,
|
816 |
+
strlen( $total_pages )
|
817 |
+
);
|
818 |
+
}
|
819 |
+
$html_total_pages = sprintf( "<span class='total-pages'>%s</span>", number_format_i18n( $total_pages ) );
|
820 |
+
$page_links[] = $total_pages_before . sprintf( _x( '%1$s of %2$s', 'paging' ), $html_current_page, $html_total_pages ) . $total_pages_after;
|
821 |
+
|
822 |
+
if ( $disable_next ) {
|
823 |
+
$page_links[] = '<span class="tablenav-pages-navspan button" aria-hidden="true">›</span>';
|
824 |
+
} else {
|
825 |
+
$page_links[] = sprintf( "<a class='next-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
826 |
+
esc_url( add_query_arg( 'paged', min( $total_pages, $current+1 ), $current_url ) ),
|
827 |
+
__( 'Next page' ),
|
828 |
+
'›'
|
829 |
+
);
|
830 |
+
}
|
831 |
+
|
832 |
+
if ( $disable_last ) {
|
833 |
+
$page_links[] = '<span class="tablenav-pages-navspan button" aria-hidden="true">»</span>';
|
834 |
+
} else {
|
835 |
+
$page_links[] = sprintf( "<a class='last-page button' href='%s'><span class='screen-reader-text'>%s</span><span aria-hidden='true'>%s</span></a>",
|
836 |
+
esc_url( add_query_arg( 'paged', $total_pages, $current_url ) ),
|
837 |
+
__( 'Last page' ),
|
838 |
+
'»'
|
839 |
+
);
|
840 |
+
}
|
841 |
+
|
842 |
+
$pagination_links_class = 'pagination-links';
|
843 |
+
if ( ! empty( $infinite_scroll ) ) {
|
844 |
+
$pagination_links_class = ' hide-if-js';
|
845 |
+
}
|
846 |
+
$output .= "\n<span class='$pagination_links_class'>" . join( "\n", $page_links ) . '</span>';
|
847 |
+
|
848 |
+
if ( $total_pages ) {
|
849 |
+
$page_class = $total_pages < 2 ? ' one-page' : '';
|
850 |
+
} else {
|
851 |
+
$page_class = ' no-pages';
|
852 |
+
}
|
853 |
+
$this->_pagination = "<div class='tablenav-pages{$page_class}'>$output</div>";
|
854 |
+
|
855 |
+
echo $this->_pagination;
|
856 |
+
}
|
857 |
+
|
858 |
+
/**
|
859 |
+
* Get a list of columns. The format is:
|
860 |
+
* 'internal-name' => 'Title'
|
861 |
+
*
|
862 |
+
* @since 3.1.0
|
863 |
+
* @access public
|
864 |
+
* @abstract
|
865 |
+
*
|
866 |
+
* @return array
|
867 |
+
*/
|
868 |
+
public function get_columns() {
|
869 |
+
die( 'function WP_List_Table::get_columns() must be over-ridden in a sub-class.' );
|
870 |
+
}
|
871 |
+
|
872 |
+
/**
|
873 |
+
* Get a list of sortable columns. The format is:
|
874 |
+
* 'internal-name' => 'orderby'
|
875 |
+
* or
|
876 |
+
* 'internal-name' => array( 'orderby', true )
|
877 |
+
*
|
878 |
+
* The second format will make the initial sorting order be descending
|
879 |
+
*
|
880 |
+
* @since 3.1.0
|
881 |
+
* @access protected
|
882 |
+
*
|
883 |
+
* @return array
|
884 |
+
*/
|
885 |
+
protected function get_sortable_columns() {
|
886 |
+
return array();
|
887 |
+
}
|
888 |
+
|
889 |
+
/**
|
890 |
+
* Gets the name of the default primary column.
|
891 |
+
*
|
892 |
+
* @since 4.3.0
|
893 |
+
* @access protected
|
894 |
+
*
|
895 |
+
* @return string Name of the default primary column, in this case, an empty string.
|
896 |
+
*/
|
897 |
+
protected function get_default_primary_column_name() {
|
898 |
+
$columns = $this->get_columns();
|
899 |
+
$column = '';
|
900 |
+
|
901 |
+
if ( empty( $columns ) ) {
|
902 |
+
return $column;
|
903 |
+
}
|
904 |
+
|
905 |
+
// We need a primary defined so responsive views show something,
|
906 |
+
// so let's fall back to the first non-checkbox column.
|
907 |
+
foreach ( $columns as $col => $column_name ) {
|
908 |
+
if ( 'cb' === $col ) {
|
909 |
+
continue;
|
910 |
+
}
|
911 |
+
|
912 |
+
$column = $col;
|
913 |
+
break;
|
914 |
+
}
|
915 |
+
|
916 |
+
return $column;
|
917 |
+
}
|
918 |
+
|
919 |
+
/**
|
920 |
+
* Public wrapper for WP_List_Table::get_default_primary_column_name().
|
921 |
+
*
|
922 |
+
* @since 4.4.0
|
923 |
+
* @access public
|
924 |
+
*
|
925 |
+
* @return string Name of the default primary column.
|
926 |
+
*/
|
927 |
+
public function get_primary_column() {
|
928 |
+
return $this->get_primary_column_name();
|
929 |
+
}
|
930 |
+
|
931 |
+
/**
|
932 |
+
* Gets the name of the primary column.
|
933 |
+
*
|
934 |
+
* @since 4.3.0
|
935 |
+
* @access protected
|
936 |
+
*
|
937 |
+
* @return string The name of the primary column.
|
938 |
+
*/
|
939 |
+
protected function get_primary_column_name() {
|
940 |
+
$columns = get_column_headers( $this->screen );
|
941 |
+
$default = $this->get_default_primary_column_name();
|
942 |
+
|
943 |
+
// If the primary column doesn't exist fall back to the
|
944 |
+
// first non-checkbox column.
|
945 |
+
if ( ! isset( $columns[ $default ] ) ) {
|
946 |
+
$default = WPSBC_WP_List_Table::get_default_primary_column_name();
|
947 |
+
}
|
948 |
+
|
949 |
+
/**
|
950 |
+
* Filters the name of the primary column for the current list table.
|
951 |
+
*
|
952 |
+
* @since 4.3.0
|
953 |
+
*
|
954 |
+
* @param string $default Column name default for the specific list table, e.g. 'name'.
|
955 |
+
* @param string $context Screen ID for specific list table, e.g. 'plugins'.
|
956 |
+
*/
|
957 |
+
$column = apply_filters( 'list_table_primary_column', $default, $this->screen->id );
|
958 |
+
|
959 |
+
if ( empty( $column ) || ! isset( $columns[ $column ] ) ) {
|
960 |
+
$column = $default;
|
961 |
+
}
|
962 |
+
|
963 |
+
return $column;
|
964 |
+
}
|
965 |
+
|
966 |
+
/**
|
967 |
+
* Get a list of all, hidden and sortable columns, with filter applied
|
968 |
+
*
|
969 |
+
* @since 3.1.0
|
970 |
+
* @access protected
|
971 |
+
*
|
972 |
+
* @return array
|
973 |
+
*/
|
974 |
+
protected function get_column_info() {
|
975 |
+
// $_column_headers is already set / cached
|
976 |
+
if ( isset( $this->_column_headers ) && is_array( $this->_column_headers ) ) {
|
977 |
+
// Back-compat for list tables that have been manually setting $_column_headers for horse reasons.
|
978 |
+
// In 4.3, we added a fourth argument for primary column.
|
979 |
+
$column_headers = array( array(), array(), array(), $this->get_primary_column_name() );
|
980 |
+
foreach ( $this->_column_headers as $key => $value ) {
|
981 |
+
$column_headers[ $key ] = $value;
|
982 |
+
}
|
983 |
+
|
984 |
+
return $column_headers;
|
985 |
+
}
|
986 |
+
|
987 |
+
$columns = get_column_headers( $this->screen );
|
988 |
+
$hidden = get_hidden_columns( $this->screen );
|
989 |
+
|
990 |
+
$sortable_columns = $this->get_sortable_columns();
|
991 |
+
/**
|
992 |
+
* Filters the list table sortable columns for a specific screen.
|
993 |
+
*
|
994 |
+
* The dynamic portion of the hook name, `$this->screen->id`, refers
|
995 |
+
* to the ID of the current screen, usually a string.
|
996 |
+
*
|
997 |
+
* @since 3.5.0
|
998 |
+
*
|
999 |
+
* @param array $sortable_columns An array of sortable columns.
|
1000 |
+
*/
|
1001 |
+
$_sortable = apply_filters( "manage_{$this->screen->id}_sortable_columns", $sortable_columns );
|
1002 |
+
|
1003 |
+
$sortable = array();
|
1004 |
+
foreach ( $_sortable as $id => $data ) {
|
1005 |
+
if ( empty( $data ) )
|
1006 |
+
continue;
|
1007 |
+
|
1008 |
+
$data = (array) $data;
|
1009 |
+
if ( !isset( $data[1] ) )
|
1010 |
+
$data[1] = false;
|
1011 |
+
|
1012 |
+
$sortable[$id] = $data;
|
1013 |
+
}
|
1014 |
+
|
1015 |
+
$primary = $this->get_primary_column_name();
|
1016 |
+
$this->_column_headers = array( $columns, $hidden, $sortable, $primary );
|
1017 |
+
|
1018 |
+
return $this->_column_headers;
|
1019 |
+
}
|
1020 |
+
|
1021 |
+
/**
|
1022 |
+
* Return number of visible columns
|
1023 |
+
*
|
1024 |
+
* @since 3.1.0
|
1025 |
+
* @access public
|
1026 |
+
*
|
1027 |
+
* @return int
|
1028 |
+
*/
|
1029 |
+
public function get_column_count() {
|
1030 |
+
list ( $columns, $hidden ) = $this->get_column_info();
|
1031 |
+
$hidden = array_intersect( array_keys( $columns ), array_filter( $hidden ) );
|
1032 |
+
return count( $columns ) - count( $hidden );
|
1033 |
+
}
|
1034 |
+
|
1035 |
+
/**
|
1036 |
+
* Print column headers, accounting for hidden and sortable columns.
|
1037 |
+
*
|
1038 |
+
* @since 3.1.0
|
1039 |
+
* @access public
|
1040 |
+
*
|
1041 |
+
* @staticvar int $cb_counter
|
1042 |
+
*
|
1043 |
+
* @param bool $with_id Whether to set the id attribute or not
|
1044 |
+
*/
|
1045 |
+
public function print_column_headers( $with_id = true ) {
|
1046 |
+
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
|
1047 |
+
|
1048 |
+
$current_url = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
|
1049 |
+
$current_url = remove_query_arg( 'paged', $current_url );
|
1050 |
+
|
1051 |
+
if ( isset( $_GET['orderby'] ) ) {
|
1052 |
+
$current_orderby = $_GET['orderby'];
|
1053 |
+
} else {
|
1054 |
+
$current_orderby = '';
|
1055 |
+
}
|
1056 |
+
|
1057 |
+
if ( isset( $_GET['order'] ) && 'desc' === $_GET['order'] ) {
|
1058 |
+
$current_order = 'desc';
|
1059 |
+
} else {
|
1060 |
+
$current_order = 'asc';
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
if ( ! empty( $columns['cb'] ) ) {
|
1064 |
+
static $cb_counter = 1;
|
1065 |
+
$columns['cb'] = '<label class="screen-reader-text" for="cb-select-all-' . $cb_counter . '">' . __( 'Select All' ) . '</label>'
|
1066 |
+
. '<input id="cb-select-all-' . $cb_counter . '" type="checkbox" />';
|
1067 |
+
$cb_counter++;
|
1068 |
+
}
|
1069 |
+
|
1070 |
+
foreach ( $columns as $column_key => $column_display_name ) {
|
1071 |
+
$class = array( 'manage-column', "column-$column_key" );
|
1072 |
+
|
1073 |
+
if ( in_array( $column_key, $hidden ) ) {
|
1074 |
+
$class[] = 'hidden';
|
1075 |
+
}
|
1076 |
+
|
1077 |
+
if ( 'cb' === $column_key )
|
1078 |
+
$class[] = 'check-column';
|
1079 |
+
elseif ( in_array( $column_key, array( 'posts', 'comments', 'links' ) ) )
|
1080 |
+
$class[] = 'num';
|
1081 |
+
|
1082 |
+
if ( $column_key === $primary ) {
|
1083 |
+
$class[] = 'column-primary';
|
1084 |
+
}
|
1085 |
+
|
1086 |
+
if ( isset( $sortable[$column_key] ) ) {
|
1087 |
+
list( $orderby, $desc_first ) = $sortable[$column_key];
|
1088 |
+
|
1089 |
+
if ( $current_orderby === $orderby ) {
|
1090 |
+
$order = 'asc' === $current_order ? 'desc' : 'asc';
|
1091 |
+
$class[] = 'sorted';
|
1092 |
+
$class[] = $current_order;
|
1093 |
+
} else {
|
1094 |
+
$order = $desc_first ? 'desc' : 'asc';
|
1095 |
+
$class[] = 'sortable';
|
1096 |
+
$class[] = $desc_first ? 'asc' : 'desc';
|
1097 |
+
}
|
1098 |
+
|
1099 |
+
$column_display_name = '<a href="' . esc_url( add_query_arg( compact( 'orderby', 'order' ), $current_url ) ) . '"><span>' . $column_display_name . '</span><span class="sorting-indicator"></span></a>';
|
1100 |
+
}
|
1101 |
+
|
1102 |
+
$tag = ( 'cb' === $column_key ) ? 'td' : 'th';
|
1103 |
+
$scope = ( 'th' === $tag ) ? 'scope="col"' : '';
|
1104 |
+
$id = $with_id ? "id='$column_key'" : '';
|
1105 |
+
|
1106 |
+
if ( !empty( $class ) )
|
1107 |
+
$class = "class='" . join( ' ', $class ) . "'";
|
1108 |
+
|
1109 |
+
echo "<$tag $scope $id $class>$column_display_name</$tag>";
|
1110 |
+
}
|
1111 |
+
}
|
1112 |
+
|
1113 |
+
/**
|
1114 |
+
* Display the table
|
1115 |
+
*
|
1116 |
+
* @since 3.1.0
|
1117 |
+
* @access public
|
1118 |
+
*/
|
1119 |
+
public function display() {
|
1120 |
+
$singular = $this->_args['singular'];
|
1121 |
+
|
1122 |
+
$this->display_tablenav( 'top' );
|
1123 |
+
|
1124 |
+
$this->screen->render_screen_reader_content( 'heading_list' );
|
1125 |
+
?>
|
1126 |
+
<table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
|
1127 |
+
<thead>
|
1128 |
+
<tr>
|
1129 |
+
<?php $this->print_column_headers(); ?>
|
1130 |
+
</tr>
|
1131 |
+
</thead>
|
1132 |
+
|
1133 |
+
<tbody id="the-list"<?php
|
1134 |
+
if ( $singular ) {
|
1135 |
+
echo " data-wp-lists='list:$singular'";
|
1136 |
+
} ?>>
|
1137 |
+
<?php $this->display_rows_or_placeholder(); ?>
|
1138 |
+
</tbody>
|
1139 |
+
|
1140 |
+
<tfoot>
|
1141 |
+
<tr>
|
1142 |
+
<?php $this->print_column_headers( false ); ?>
|
1143 |
+
</tr>
|
1144 |
+
</tfoot>
|
1145 |
+
|
1146 |
+
</table>
|
1147 |
+
<?php
|
1148 |
+
$this->display_tablenav( 'bottom' );
|
1149 |
+
}
|
1150 |
+
|
1151 |
+
/**
|
1152 |
+
* Get a list of CSS classes for the WP_List_Table table tag.
|
1153 |
+
*
|
1154 |
+
* @since 3.1.0
|
1155 |
+
* @access protected
|
1156 |
+
*
|
1157 |
+
* @return array List of CSS classes for the table tag.
|
1158 |
+
*/
|
1159 |
+
protected function get_table_classes() {
|
1160 |
+
return array( 'widefat', 'fixed', 'striped', $this->_args['plural'] );
|
1161 |
+
}
|
1162 |
+
|
1163 |
+
/**
|
1164 |
+
* Generate the table navigation above or below the table
|
1165 |
+
*
|
1166 |
+
* @since 3.1.0
|
1167 |
+
* @access protected
|
1168 |
+
* @param string $which
|
1169 |
+
*/
|
1170 |
+
protected function display_tablenav( $which ) {
|
1171 |
+
if ( 'top' === $which ) {
|
1172 |
+
wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
|
1173 |
+
}
|
1174 |
+
?>
|
1175 |
+
<div class="tablenav <?php echo esc_attr( $which ); ?>">
|
1176 |
+
|
1177 |
+
<?php if ( $this->has_items() ): ?>
|
1178 |
+
<div class="alignleft actions bulkactions">
|
1179 |
+
<?php $this->bulk_actions( $which ); ?>
|
1180 |
+
</div>
|
1181 |
+
<?php endif;
|
1182 |
+
$this->extra_tablenav( $which );
|
1183 |
+
$this->pagination( $which );
|
1184 |
+
?>
|
1185 |
+
|
1186 |
+
<br class="clear" />
|
1187 |
+
</div>
|
1188 |
+
<?php
|
1189 |
+
}
|
1190 |
+
|
1191 |
+
/**
|
1192 |
+
* Extra controls to be displayed between bulk actions and pagination
|
1193 |
+
*
|
1194 |
+
* @since 3.1.0
|
1195 |
+
* @access protected
|
1196 |
+
*
|
1197 |
+
* @param string $which
|
1198 |
+
*/
|
1199 |
+
protected function extra_tablenav( $which ) {}
|
1200 |
+
|
1201 |
+
/**
|
1202 |
+
* Generate the tbody element for the list table.
|
1203 |
+
*
|
1204 |
+
* @since 3.1.0
|
1205 |
+
* @access public
|
1206 |
+
*/
|
1207 |
+
public function display_rows_or_placeholder() {
|
1208 |
+
if ( $this->has_items() ) {
|
1209 |
+
$this->display_rows();
|
1210 |
+
} else {
|
1211 |
+
echo '<tr class="no-items"><td class="colspanchange" colspan="' . $this->get_column_count() . '">';
|
1212 |
+
$this->no_items();
|
1213 |
+
echo '</td></tr>';
|
1214 |
+
}
|
1215 |
+
}
|
1216 |
+
|
1217 |
+
/**
|
1218 |
+
* Generate the table rows
|
1219 |
+
*
|
1220 |
+
* @since 3.1.0
|
1221 |
+
* @access public
|
1222 |
+
*/
|
1223 |
+
public function display_rows() {
|
1224 |
+
foreach ( $this->items as $item )
|
1225 |
+
$this->single_row( $item );
|
1226 |
+
}
|
1227 |
+
|
1228 |
+
/**
|
1229 |
+
* Generates content for a single row of the table
|
1230 |
+
*
|
1231 |
+
* @since 3.1.0
|
1232 |
+
* @access public
|
1233 |
+
*
|
1234 |
+
* @param object $item The current item
|
1235 |
+
*/
|
1236 |
+
public function single_row( $item ) {
|
1237 |
+
echo '<tr>';
|
1238 |
+
$this->single_row_columns( $item );
|
1239 |
+
echo '</tr>';
|
1240 |
+
}
|
1241 |
+
|
1242 |
+
/**
|
1243 |
+
*
|
1244 |
+
* @param object $item
|
1245 |
+
* @param string $column_name
|
1246 |
+
*/
|
1247 |
+
protected function column_default( $item, $column_name ) {}
|
1248 |
+
|
1249 |
+
/**
|
1250 |
+
*
|
1251 |
+
* @param object $item
|
1252 |
+
*/
|
1253 |
+
protected function column_cb( $item ) {}
|
1254 |
+
|
1255 |
+
/**
|
1256 |
+
* Generates the columns for a single row of the table
|
1257 |
+
*
|
1258 |
+
* @since 3.1.0
|
1259 |
+
* @access protected
|
1260 |
+
*
|
1261 |
+
* @param object $item The current item
|
1262 |
+
*/
|
1263 |
+
protected function single_row_columns( $item ) {
|
1264 |
+
list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info();
|
1265 |
+
|
1266 |
+
foreach ( $columns as $column_name => $column_display_name ) {
|
1267 |
+
$classes = "$column_name column-$column_name";
|
1268 |
+
if ( $primary === $column_name ) {
|
1269 |
+
$classes .= ' has-row-actions column-primary';
|
1270 |
+
}
|
1271 |
+
|
1272 |
+
if ( in_array( $column_name, $hidden ) ) {
|
1273 |
+
$classes .= ' hidden';
|
1274 |
+
}
|
1275 |
+
|
1276 |
+
// Comments column uses HTML in the display name with screen reader text.
|
1277 |
+
// Instead of using esc_attr(), we strip tags to get closer to a user-friendly string.
|
1278 |
+
$data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"';
|
1279 |
+
|
1280 |
+
$attributes = "class='$classes' $data";
|
1281 |
+
|
1282 |
+
if ( 'cb' === $column_name ) {
|
1283 |
+
echo '<th scope="row" class="check-column">';
|
1284 |
+
echo $this->column_cb( $item );
|
1285 |
+
echo '</th>';
|
1286 |
+
} elseif ( method_exists( $this, '_column_' . $column_name ) ) {
|
1287 |
+
echo call_user_func(
|
1288 |
+
array( $this, '_column_' . $column_name ),
|
1289 |
+
$item,
|
1290 |
+
$classes,
|
1291 |
+
$data,
|
1292 |
+
$primary
|
1293 |
+
);
|
1294 |
+
} elseif ( method_exists( $this, 'column_' . $column_name ) ) {
|
1295 |
+
echo "<td $attributes>";
|
1296 |
+
echo call_user_func( array( $this, 'column_' . $column_name ), $item );
|
1297 |
+
echo $this->handle_row_actions( $item, $column_name, $primary );
|
1298 |
+
echo "</td>";
|
1299 |
+
} else {
|
1300 |
+
echo "<td $attributes>";
|
1301 |
+
echo $this->column_default( $item, $column_name );
|
1302 |
+
echo $this->handle_row_actions( $item, $column_name, $primary );
|
1303 |
+
echo "</td>";
|
1304 |
+
}
|
1305 |
+
}
|
1306 |
+
}
|
1307 |
+
|
1308 |
+
/**
|
1309 |
+
* Generates and display row actions links for the list table.
|
1310 |
+
*
|
1311 |
+
* @since 4.3.0
|
1312 |
+
* @access protected
|
1313 |
+
*
|
1314 |
+
* @param object $item The item being acted upon.
|
1315 |
+
* @param string $column_name Current column name.
|
1316 |
+
* @param string $primary Primary column name.
|
1317 |
+
* @return string The row actions HTML, or an empty string if the current column is the primary column.
|
1318 |
+
*/
|
1319 |
+
protected function handle_row_actions( $item, $column_name, $primary ) {
|
1320 |
+
return $column_name === $primary ? '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>' : '';
|
1321 |
+
}
|
1322 |
+
|
1323 |
+
/**
|
1324 |
+
* Handle an incoming ajax request (called from admin-ajax.php)
|
1325 |
+
*
|
1326 |
+
* @since 3.1.0
|
1327 |
+
* @access public
|
1328 |
+
*/
|
1329 |
+
public function ajax_response() {
|
1330 |
+
$this->prepare_items();
|
1331 |
+
|
1332 |
+
ob_start();
|
1333 |
+
if ( ! empty( $_REQUEST['no_placeholder'] ) ) {
|
1334 |
+
$this->display_rows();
|
1335 |
+
} else {
|
1336 |
+
$this->display_rows_or_placeholder();
|
1337 |
+
}
|
1338 |
+
|
1339 |
+
$rows = ob_get_clean();
|
1340 |
+
|
1341 |
+
$response = array( 'rows' => $rows );
|
1342 |
+
|
1343 |
+
if ( isset( $this->_pagination_args['total_items'] ) ) {
|
1344 |
+
$response['total_items_i18n'] = sprintf(
|
1345 |
+
_n( '%s item', '%s items', $this->_pagination_args['total_items'] ),
|
1346 |
+
number_format_i18n( $this->_pagination_args['total_items'] )
|
1347 |
+
);
|
1348 |
+
}
|
1349 |
+
if ( isset( $this->_pagination_args['total_pages'] ) ) {
|
1350 |
+
$response['total_pages'] = $this->_pagination_args['total_pages'];
|
1351 |
+
$response['total_pages_i18n'] = number_format_i18n( $this->_pagination_args['total_pages'] );
|
1352 |
+
}
|
1353 |
+
|
1354 |
+
die( wp_json_encode( $response ) );
|
1355 |
+
}
|
1356 |
+
|
1357 |
+
/**
|
1358 |
+
* Send required variables to JavaScript land
|
1359 |
+
*
|
1360 |
+
* @access public
|
1361 |
+
*/
|
1362 |
+
public function _js_vars() {
|
1363 |
+
$args = array(
|
1364 |
+
'class' => get_class( $this ),
|
1365 |
+
'screen' => array(
|
1366 |
+
'id' => $this->screen->id,
|
1367 |
+
'base' => $this->screen->base,
|
1368 |
+
)
|
1369 |
+
);
|
1370 |
+
|
1371 |
+
printf( "<script type='text/javascript'>list_args = %s;</script>\n", wp_json_encode( $args ) );
|
1372 |
+
}
|
1373 |
+
}
|
includes/abstracts/abstract-class-object-db.php
ADDED
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Base class for all core database objects
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
abstract class WPSBC_Object_DB extends WPSBC_DB {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Object type to query for
|
15 |
+
*
|
16 |
+
* @access public
|
17 |
+
* @var string
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
public $query_object_type = 'stdClass';
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Constructor
|
25 |
+
*
|
26 |
+
* Subclasses should set the $table_name, $primary_key, $context and $query_object_type
|
27 |
+
*
|
28 |
+
* @access public
|
29 |
+
*
|
30 |
+
*/
|
31 |
+
public function __construct() {}
|
32 |
+
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Returns a table row for the given row id
|
36 |
+
*
|
37 |
+
* @param int $row_id
|
38 |
+
*
|
39 |
+
* @return mixed object|null
|
40 |
+
*
|
41 |
+
*/
|
42 |
+
public function get( $row_id ) {
|
43 |
+
|
44 |
+
global $wpdb;
|
45 |
+
|
46 |
+
$row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE {$this->primary_key} = %s LIMIT 1", $row_id ) );
|
47 |
+
|
48 |
+
// json decode
|
49 |
+
if( is_object( $row ) ) {
|
50 |
+
|
51 |
+
foreach( array_keys( get_object_vars( $row ) ) as $key )
|
52 |
+
$row->$key = $this->json_decode( $row->$key );
|
53 |
+
|
54 |
+
}
|
55 |
+
|
56 |
+
return $row;
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Retrieves results for the given query clauses
|
63 |
+
*
|
64 |
+
* @param array $clauses - an array with SQL ready clauses
|
65 |
+
* @param array $args - the query args
|
66 |
+
* @param string $callback - a callback to be run against every returned result
|
67 |
+
*
|
68 |
+
* @return mixed array|int|null
|
69 |
+
*
|
70 |
+
*/
|
71 |
+
protected function get_results( $clauses, $args, $callback = '' ) {
|
72 |
+
|
73 |
+
global $wpdb;
|
74 |
+
|
75 |
+
if( true === $clauses['count'] ) {
|
76 |
+
|
77 |
+
$results = $wpdb->get_var( "SELECT COUNT({$this->primary_key}) FROM {$this->table_name} {$clauses['where']}" );
|
78 |
+
|
79 |
+
return absint( $results );
|
80 |
+
|
81 |
+
} else {
|
82 |
+
|
83 |
+
$results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$this->table_name} {$clauses['where']} ORDER BY {$clauses['orderby']} {$clauses['order']} LIMIT %d, %d", absint( $args['offset'] ), absint( $args['number'] ) ) );
|
84 |
+
|
85 |
+
}
|
86 |
+
|
87 |
+
// json decode
|
88 |
+
if( ! empty( $results ) ) {
|
89 |
+
|
90 |
+
foreach( $results as $result_key => $row ) {
|
91 |
+
|
92 |
+
if( is_object( $row ) ) {
|
93 |
+
|
94 |
+
foreach( array_keys( get_object_vars( $row ) ) as $key )
|
95 |
+
$row->$key = $this->json_decode( $row->$key );
|
96 |
+
|
97 |
+
}
|
98 |
+
|
99 |
+
$results[$result_key] = $row;
|
100 |
+
|
101 |
+
}
|
102 |
+
|
103 |
+
}
|
104 |
+
|
105 |
+
|
106 |
+
if( ! empty( $callback ) && is_callable( $callback ) )
|
107 |
+
$results = array_map( $callback, $results );
|
108 |
+
|
109 |
+
return $results;
|
110 |
+
|
111 |
+
}
|
112 |
+
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Inserts a new row into the database table
|
116 |
+
*
|
117 |
+
* @param array $data
|
118 |
+
*
|
119 |
+
* @return mixed int|false
|
120 |
+
*
|
121 |
+
*/
|
122 |
+
public function insert( $data ) {
|
123 |
+
|
124 |
+
global $wpdb;
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Modify the data to be added into a new row just before
|
128 |
+
* the insert procedure
|
129 |
+
*
|
130 |
+
* @param array $data
|
131 |
+
*
|
132 |
+
*/
|
133 |
+
$data = apply_filters( "wpsbc_pre_insert_{$this->context}_data", $data );
|
134 |
+
|
135 |
+
if( empty( $data ) )
|
136 |
+
return false;
|
137 |
+
|
138 |
+
$column_formats = $this->get_columns();
|
139 |
+
|
140 |
+
// Encodes the values of the array that are arrays
|
141 |
+
foreach( $data as $key => $val ) {
|
142 |
+
$data[$key] = $this->json_encode( $val );
|
143 |
+
}
|
144 |
+
|
145 |
+
// Make array keys lowercase
|
146 |
+
$data = array_change_key_case( $data );
|
147 |
+
|
148 |
+
// Filter out unwanted keys
|
149 |
+
$data = array_intersect_key( $data, $column_formats );
|
150 |
+
|
151 |
+
// Strip slashes
|
152 |
+
$data = wp_unslash( $data );
|
153 |
+
|
154 |
+
/**
|
155 |
+
* Fires just before a new row is to be inserted into the table
|
156 |
+
*
|
157 |
+
* @param array $data
|
158 |
+
*
|
159 |
+
*/
|
160 |
+
do_action( 'wpsbc_pre_insert_' . $this->context, $data );
|
161 |
+
|
162 |
+
// Arrange column formats to match data elements
|
163 |
+
$data_keys = array_keys( $data );
|
164 |
+
$column_formats = array_merge( array_flip( $data_keys ), $column_formats );
|
165 |
+
|
166 |
+
// Insert the new row
|
167 |
+
$inserted = $wpdb->insert( $this->table_name, $data, $column_formats );
|
168 |
+
|
169 |
+
if( ! $inserted )
|
170 |
+
return false;
|
171 |
+
|
172 |
+
$insert_id = $wpdb->insert_id;
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Fires right after a new row has been inserted
|
176 |
+
*
|
177 |
+
* @param int $insert_id
|
178 |
+
* @param array $data
|
179 |
+
*
|
180 |
+
*/
|
181 |
+
do_action( 'wpsbc_insert_' . $this->context, $insert_id, $data );
|
182 |
+
|
183 |
+
return $insert_id;
|
184 |
+
|
185 |
+
}
|
186 |
+
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Updates a row from the database table
|
190 |
+
*
|
191 |
+
* @param int $row_id
|
192 |
+
*
|
193 |
+
* @return bool
|
194 |
+
*
|
195 |
+
*/
|
196 |
+
public function update( $row_id, $data ) {
|
197 |
+
|
198 |
+
global $wpdb;
|
199 |
+
|
200 |
+
$row_id = absint( $row_id );
|
201 |
+
|
202 |
+
$column_formats = $this->get_columns();
|
203 |
+
|
204 |
+
// Encodes the values of the array that are arrays
|
205 |
+
foreach( $data as $key => $val ) {
|
206 |
+
$data[$key] = $this->json_encode( $val );
|
207 |
+
}
|
208 |
+
|
209 |
+
// Make array keys lowercase
|
210 |
+
$data = array_change_key_case( $data );
|
211 |
+
|
212 |
+
// Filter out unwanted keys
|
213 |
+
$data = array_intersect_key( $data, $column_formats );
|
214 |
+
|
215 |
+
// Strip slashes
|
216 |
+
$data = wp_unslash( $data );
|
217 |
+
|
218 |
+
// Make sure the primary key is not included
|
219 |
+
if( isset( $data[ $this->primary_key ] ) )
|
220 |
+
unset( $data[ $this->primary_key ] );
|
221 |
+
|
222 |
+
$data_keys = array_keys( $data );
|
223 |
+
$column_formats = array_merge( array_flip( $data_keys ), $column_formats );
|
224 |
+
|
225 |
+
// Update
|
226 |
+
$updated = $wpdb->update( $this->table_name, $data, array( $this->primary_key => $row_id ), $column_formats );
|
227 |
+
|
228 |
+
if( false === $updated )
|
229 |
+
return false;
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Fires right after a row has been updated
|
233 |
+
*
|
234 |
+
* @param int $inserted
|
235 |
+
* @param array $data
|
236 |
+
*
|
237 |
+
*/
|
238 |
+
do_action( 'wpsbc_update_' . $this->context, $row_id, $data );
|
239 |
+
|
240 |
+
return true;
|
241 |
+
|
242 |
+
}
|
243 |
+
|
244 |
+
|
245 |
+
/**
|
246 |
+
* Removes a row from the database table
|
247 |
+
*
|
248 |
+
* @param int $row_id
|
249 |
+
*
|
250 |
+
* @return bool
|
251 |
+
*
|
252 |
+
*/
|
253 |
+
public function delete( $row_id ) {
|
254 |
+
|
255 |
+
global $wpdb;
|
256 |
+
|
257 |
+
$row_id = absint( $row_id );
|
258 |
+
|
259 |
+
/**
|
260 |
+
* Fires right before a row is removed from the database table
|
261 |
+
*
|
262 |
+
* @param int $row_id
|
263 |
+
*
|
264 |
+
*/
|
265 |
+
do_action( 'wpsbc_pre_delete_' . $this->context, $row_id );
|
266 |
+
|
267 |
+
// Delete the row
|
268 |
+
$deleted = $wpdb->query( $wpdb->prepare( "DELETE FROM {$this->table_name} WHERE {$this->primary_key} = %d", $row_id ) );
|
269 |
+
|
270 |
+
if( false === $deleted )
|
271 |
+
return false;
|
272 |
+
|
273 |
+
/**
|
274 |
+
* Fires right after the row is removed from the database table
|
275 |
+
*
|
276 |
+
* @param int $row_id
|
277 |
+
*
|
278 |
+
*/
|
279 |
+
do_action( 'wpsbc_delete_' . $this->context, $row_id );
|
280 |
+
|
281 |
+
return true;
|
282 |
+
|
283 |
+
}
|
284 |
+
|
285 |
+
|
286 |
+
/**
|
287 |
+
* Returns an instance of the $query_object_type given an object or an id
|
288 |
+
*
|
289 |
+
* @param mixed int|object
|
290 |
+
*
|
291 |
+
* @return mixed object|null
|
292 |
+
*
|
293 |
+
*/
|
294 |
+
public function get_object( $object ) {
|
295 |
+
|
296 |
+
if( ! class_exists( $this->query_object_type ) )
|
297 |
+
return null;
|
298 |
+
|
299 |
+
if( $object instanceof $this->query_object_type )
|
300 |
+
$_object = $object;
|
301 |
+
|
302 |
+
elseif( is_object( $object ) )
|
303 |
+
$_object = new $this->query_object_type( $object );
|
304 |
+
|
305 |
+
else {
|
306 |
+
|
307 |
+
$object = $this->get( $object );
|
308 |
+
|
309 |
+
if( is_null( $object ) )
|
310 |
+
$_object = null;
|
311 |
+
else
|
312 |
+
$_object = new $this->query_object_type( $object );
|
313 |
+
|
314 |
+
}
|
315 |
+
|
316 |
+
return $_object;
|
317 |
+
|
318 |
+
}
|
319 |
+
|
320 |
+
|
321 |
+
/**
|
322 |
+
* Encodes each value of a given array to json
|
323 |
+
*
|
324 |
+
* @param array $val
|
325 |
+
*
|
326 |
+
* @return string
|
327 |
+
*
|
328 |
+
*/
|
329 |
+
protected function json_encode( $val ) {
|
330 |
+
|
331 |
+
if( is_array( $val ) || is_object( $val ) )
|
332 |
+
$val = json_encode( $val );
|
333 |
+
|
334 |
+
return $val;
|
335 |
+
|
336 |
+
}
|
337 |
+
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Decodes a given json string to array
|
341 |
+
*
|
342 |
+
*/
|
343 |
+
protected function json_decode( $str ) {
|
344 |
+
|
345 |
+
$arr = json_decode( $str, true );
|
346 |
+
|
347 |
+
return ( json_last_error() == JSON_ERROR_NONE ? $arr : $str );
|
348 |
+
|
349 |
+
}
|
350 |
+
|
351 |
+
}
|
includes/abstracts/abstract-class-object-meta-db.php
ADDED
@@ -0,0 +1,95 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Base class for all core database objects.
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
abstract class WPSBC_Object_Meta_DB extends WPSBC_DB {
|
12 |
+
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Constructor
|
16 |
+
*
|
17 |
+
* Subclasses should set the $table_name, $primary_key, $context
|
18 |
+
*
|
19 |
+
* @access public
|
20 |
+
*
|
21 |
+
*/
|
22 |
+
public function __construct() {}
|
23 |
+
|
24 |
+
|
25 |
+
/**
|
26 |
+
* Inserts a new meta entry for the object
|
27 |
+
*
|
28 |
+
* @param int $object_id
|
29 |
+
* @param string $meta_key
|
30 |
+
* @param string $meta_value
|
31 |
+
* @param bool $unique
|
32 |
+
*
|
33 |
+
* @return mixed int|false
|
34 |
+
*
|
35 |
+
*/
|
36 |
+
public function add( $object_id, $meta_key, $meta_value, $unique = false ) {
|
37 |
+
|
38 |
+
return add_metadata( $this->context, $object_id, $meta_key, $meta_value, $unique );
|
39 |
+
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Updates a meta entry for the object
|
45 |
+
*
|
46 |
+
* @param int $object_id
|
47 |
+
* @param string $meta_key
|
48 |
+
* @param string $meta_value
|
49 |
+
* @param bool $prev_value
|
50 |
+
*
|
51 |
+
* @return bool
|
52 |
+
*
|
53 |
+
*/
|
54 |
+
public function update( $object_id, $meta_key, $meta_value, $prev_value = '' ) {
|
55 |
+
|
56 |
+
return update_metadata( $this->context, $object_id, $meta_key, $meta_value, $prev_value );
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Returns a meta entry for the object
|
63 |
+
*
|
64 |
+
* @param int $object_id
|
65 |
+
* @param string $meta_key
|
66 |
+
* @param bool $single
|
67 |
+
*
|
68 |
+
* @return mixed
|
69 |
+
*
|
70 |
+
*/
|
71 |
+
public function get( $object_id, $meta_key = '', $single = false ) {
|
72 |
+
|
73 |
+
return get_metadata( $this->context, $object_id, $meta_key, $single );
|
74 |
+
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Removes a meta entry for the object
|
80 |
+
*
|
81 |
+
* @param int $object_id
|
82 |
+
* @param string $meta_key
|
83 |
+
* @param string $meta_value
|
84 |
+
* @param bool $delete_all
|
85 |
+
*
|
86 |
+
* @return bool
|
87 |
+
*
|
88 |
+
*/
|
89 |
+
public function delete( $object_id, $meta_key, $meta_value = '', $delete_all = '' ) {
|
90 |
+
|
91 |
+
return delete_metadata( $this->context, $object_id, $meta_key, $meta_value, $delete_all );
|
92 |
+
|
93 |
+
}
|
94 |
+
|
95 |
+
}
|
includes/abstracts/abstract-class-object.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Base class for all object
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
abstract class WPSBC_Base_Object {
|
12 |
+
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Constructor
|
16 |
+
*
|
17 |
+
*/
|
18 |
+
public function __construct( $object ) {
|
19 |
+
|
20 |
+
foreach( get_object_vars( $object ) as $key => $value ) {
|
21 |
+
|
22 |
+
if( ! property_exists( $object, $key ) )
|
23 |
+
continue;
|
24 |
+
|
25 |
+
$this->$key = $value;
|
26 |
+
|
27 |
+
}
|
28 |
+
|
29 |
+
}
|
30 |
+
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Getter
|
34 |
+
*
|
35 |
+
* @param string $property
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
public function get( $property = '' ) {
|
39 |
+
|
40 |
+
if( method_exists( $this, 'get_' . $property ) )
|
41 |
+
return $this->{'get_' . $property}();
|
42 |
+
else
|
43 |
+
return $this->$property;
|
44 |
+
|
45 |
+
}
|
46 |
+
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Returns the object attributes and their values as an array
|
50 |
+
*
|
51 |
+
*/
|
52 |
+
public function to_array() {
|
53 |
+
|
54 |
+
return get_object_vars( $this );
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
}
|
includes/abstracts/abstract-class-submenu-page.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Base class to add custom submenu pages
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
abstract class WPSBC_Submenu_Page {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The menu page under which the submenu page should be added
|
15 |
+
*
|
16 |
+
* @access protected
|
17 |
+
* @var string
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
protected $parent_slug;
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* The title of the submenu page
|
25 |
+
*
|
26 |
+
* @access protected
|
27 |
+
* @var string
|
28 |
+
*
|
29 |
+
*/
|
30 |
+
protected $page_title;
|
31 |
+
|
32 |
+
|
33 |
+
/**
|
34 |
+
* The title that should appear in the menu
|
35 |
+
*
|
36 |
+
* @access protected
|
37 |
+
* @var string
|
38 |
+
*
|
39 |
+
*/
|
40 |
+
protected $menu_title;
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* The user capability required to view this page
|
45 |
+
*
|
46 |
+
* @access protected
|
47 |
+
* @var string
|
48 |
+
*
|
49 |
+
*/
|
50 |
+
protected $capability;
|
51 |
+
|
52 |
+
|
53 |
+
/**
|
54 |
+
* The menu
|
55 |
+
*
|
56 |
+
* @access protected
|
57 |
+
* @var string
|
58 |
+
*
|
59 |
+
*/
|
60 |
+
protected $menu_slug;
|
61 |
+
|
62 |
+
/**
|
63 |
+
* The current subpage url query arg
|
64 |
+
*
|
65 |
+
* @access protected
|
66 |
+
* @var string
|
67 |
+
*
|
68 |
+
*/
|
69 |
+
protected $current_subpage;
|
70 |
+
|
71 |
+
/**
|
72 |
+
* The current tab url query arg
|
73 |
+
*
|
74 |
+
* @access protected
|
75 |
+
* @var string
|
76 |
+
*
|
77 |
+
*/
|
78 |
+
protected $current_tab;
|
79 |
+
|
80 |
+
/**
|
81 |
+
* The admin path to the page, used in admin_url
|
82 |
+
*
|
83 |
+
* @access protected
|
84 |
+
* @var string
|
85 |
+
*
|
86 |
+
*/
|
87 |
+
protected $admin_url;
|
88 |
+
|
89 |
+
/**
|
90 |
+
* A list with admin notices to be printed on the page
|
91 |
+
*
|
92 |
+
* @access protected
|
93 |
+
* @var string
|
94 |
+
*
|
95 |
+
*/
|
96 |
+
protected $admin_notices = array();
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Constructor
|
101 |
+
*
|
102 |
+
*/
|
103 |
+
public function __construct( $page_title = '', $menu_title = '', $capability = '', $menu_slug = '' ) {
|
104 |
+
|
105 |
+
$this->parent_slug = 'wp-simple-booking-calendar';
|
106 |
+
$this->page_title = $page_title;
|
107 |
+
$this->menu_title = $menu_title;
|
108 |
+
$this->capability = $capability;
|
109 |
+
$this->menu_slug = $menu_slug;
|
110 |
+
|
111 |
+
$this->current_subpage = ( ! empty( $_GET['subpage'] ) ? $_GET['subpage'] : '' );
|
112 |
+
$this->current_tab = ( ! empty( $_GET['tab'] ) ? $_GET['tab'] : '' );
|
113 |
+
|
114 |
+
add_action( 'admin_menu', array( $this, 'add_submenu_page' ) );
|
115 |
+
|
116 |
+
$this->init();
|
117 |
+
|
118 |
+
}
|
119 |
+
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Helper init method to avoid rewriting of the __construct method by subclasses
|
123 |
+
*
|
124 |
+
*/
|
125 |
+
protected function init() {}
|
126 |
+
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Getter
|
130 |
+
*
|
131 |
+
* @param string $property
|
132 |
+
*
|
133 |
+
*/
|
134 |
+
public function get( $property = '' ) {
|
135 |
+
|
136 |
+
if( method_exists( $this, 'get_' . $property ) )
|
137 |
+
return $this->{'get_' . $property}();
|
138 |
+
else
|
139 |
+
return $this->$property;
|
140 |
+
|
141 |
+
}
|
142 |
+
|
143 |
+
|
144 |
+
/**
|
145 |
+
* Callback to add the submenu page
|
146 |
+
*
|
147 |
+
*/
|
148 |
+
public function add_submenu_page() {
|
149 |
+
|
150 |
+
$hook_sufix = add_submenu_page( $this->parent_slug, $this->page_title, $this->menu_title, $this->capability, $this->menu_slug, array( $this, 'output' ) );
|
151 |
+
|
152 |
+
if( $hook_sufix ) {
|
153 |
+
|
154 |
+
$this->admin_url = add_query_arg( array( 'page' => $this->menu_slug ), 'admin.php' );
|
155 |
+
|
156 |
+
}
|
157 |
+
|
158 |
+
}
|
159 |
+
|
160 |
+
|
161 |
+
/**
|
162 |
+
* Callback for the HTML output for the page
|
163 |
+
*
|
164 |
+
*/
|
165 |
+
public function output() {}
|
166 |
+
|
167 |
+
}
|
includes/base/admin/backup/class-submenu-page-backup.php
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
Class WPSBC_Submenu_Page_Backup extends WPSBC_Submenu_Page {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Helper init method that runs on parent __construct
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
protected function init() {
|
14 |
+
|
15 |
+
add_action( 'admin_init', array( $this, 'register_admin_notices' ), 10 );
|
16 |
+
|
17 |
+
}
|
18 |
+
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Callback method to register admin notices that are sent via URL parameters
|
22 |
+
*
|
23 |
+
*/
|
24 |
+
public function register_admin_notices() {
|
25 |
+
|
26 |
+
if( empty( $_GET['wpsbc_message'] ) )
|
27 |
+
return;
|
28 |
+
|
29 |
+
// Calendar insert success
|
30 |
+
wpsbc_admin_notices()->register_notice( 'import_file_success', '<p>' . __( 'Data from the file has been imported successfully.', 'wp-simple-booking-calendar' ) . '</p>' );
|
31 |
+
|
32 |
+
}
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Callback for the HTML output for the Calendar page
|
37 |
+
*
|
38 |
+
*/
|
39 |
+
public function output() {
|
40 |
+
|
41 |
+
include 'views/view-backup.php';
|
42 |
+
|
43 |
+
}
|
44 |
+
|
45 |
+
}
|
includes/base/admin/backup/functions-actions-backup.php
ADDED
@@ -0,0 +1,148 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Handles the export of the backup file
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_action_backup_export() {
|
12 |
+
|
13 |
+
// Let only admins do this procedure
|
14 |
+
if( ! current_user_can( 'manage_options' ) )
|
15 |
+
return;
|
16 |
+
|
17 |
+
// Verify for nonce
|
18 |
+
if( empty( $_POST['wpsbc_token'] ) || ! wp_verify_nonce( $_POST['wpsbc_token'], 'wpsbc_backup_export' ) )
|
19 |
+
return;
|
20 |
+
|
21 |
+
// Set export data variable
|
22 |
+
$export_data = array();
|
23 |
+
|
24 |
+
// Get wpdb global
|
25 |
+
global $wpdb;
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Go through each custom db table and save the values
|
29 |
+
*
|
30 |
+
*/
|
31 |
+
foreach( wp_simple_booking_calendar()->db as $table_slug => $db_object ) {
|
32 |
+
|
33 |
+
$results = $wpdb->get_results( "SELECT * FROM {$db_object->table_name}" );
|
34 |
+
|
35 |
+
$export_data[$table_slug] = $results;
|
36 |
+
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* General settings and plugin version number
|
41 |
+
*
|
42 |
+
*/
|
43 |
+
$export_data['settings'] = get_option( 'wpsbc_settings', array() );
|
44 |
+
$export_data['plugin_version'] = WPSBC_VERSION;
|
45 |
+
|
46 |
+
header( 'Content-disposition: attachment; filename=wpsbc-export-' . current_time('Y') . '-' . current_time('m') . '-' . current_time('d') . '-' . current_time('H') . '-' . current_time('i') . '-' . current_time('s') . '.wpsbc' );
|
47 |
+
header( 'Content-type: application/json' );
|
48 |
+
|
49 |
+
echo( json_encode( $export_data ) );
|
50 |
+
exit;
|
51 |
+
|
52 |
+
}
|
53 |
+
add_action( 'wpsbc_action_backup_export', 'wpsbc_action_backup_export' );
|
54 |
+
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Handles the export of the backup file
|
58 |
+
*
|
59 |
+
*/
|
60 |
+
function wpsbc_action_backup_import() {
|
61 |
+
|
62 |
+
// Let only admins do this procedure
|
63 |
+
if( ! current_user_can( 'manage_options' ) )
|
64 |
+
return;
|
65 |
+
|
66 |
+
// Verify for nonce
|
67 |
+
if( empty( $_POST['wpsbc_token'] ) || ! wp_verify_nonce( $_POST['wpsbc_token'], 'wpsbc_backup_import' ) )
|
68 |
+
return;
|
69 |
+
|
70 |
+
// Check if file has been selected
|
71 |
+
if( empty( $_FILES['import_file']['tmp_name'] ) ) {
|
72 |
+
|
73 |
+
wpsbc_admin_notices()->register_notice( 'import_file_missing', '<p>' . __( 'Please select a file.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
74 |
+
wpsbc_admin_notices()->display_notice( 'import_file_missing' );
|
75 |
+
|
76 |
+
return;
|
77 |
+
|
78 |
+
}
|
79 |
+
|
80 |
+
// Check for proper extension
|
81 |
+
if( false === strpos( $_FILES['import_file']['name'], '.wpsbc' ) ) {
|
82 |
+
|
83 |
+
wpsbc_admin_notices()->register_notice( 'import_file_extension_fail', '<p>' . __( 'The file you are trying to import does not have a valid extension. The extension of the file should be ".wpsbc".', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
84 |
+
wpsbc_admin_notices()->display_notice( 'import_file_extension_fail' );
|
85 |
+
|
86 |
+
return;
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
// Decode the file
|
91 |
+
$file_contents = json_decode( file_get_contents( $_FILES['import_file']['tmp_name'] ), true );
|
92 |
+
|
93 |
+
// Check for proper plugin version
|
94 |
+
if( empty( $file_contents['plugin_version'] ) ) {
|
95 |
+
|
96 |
+
wpsbc_admin_notices()->register_notice( 'import_file_version_fail', '<p>' . __( 'The file you are trying to import is not compatible with this version of the plugin.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
97 |
+
wpsbc_admin_notices()->display_notice( 'import_file_version_fail' );
|
98 |
+
|
99 |
+
return;
|
100 |
+
|
101 |
+
}
|
102 |
+
|
103 |
+
|
104 |
+
// Get wpdb global
|
105 |
+
global $wpdb;
|
106 |
+
|
107 |
+
|
108 |
+
/**
|
109 |
+
* Empty all registered tables
|
110 |
+
*
|
111 |
+
*/
|
112 |
+
foreach( wp_simple_booking_calendar()->db as $table_slug => $db_object ) {
|
113 |
+
|
114 |
+
$wpdb->query( "TRUNCATE {$db_object->table_name}" );
|
115 |
+
|
116 |
+
}
|
117 |
+
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Go through each custom db table and insert the values from the file
|
121 |
+
*
|
122 |
+
*/
|
123 |
+
foreach( wp_simple_booking_calendar()->db as $table_slug => $db_object ) {
|
124 |
+
|
125 |
+
if( empty( $file_contents[$table_slug] ) || ! is_array( $file_contents[$table_slug] ) )
|
126 |
+
continue;
|
127 |
+
|
128 |
+
foreach( $file_contents[$table_slug] as $key => $values ) {
|
129 |
+
|
130 |
+
$wpdb->insert( $db_object->table_name, $values );
|
131 |
+
|
132 |
+
}
|
133 |
+
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Add general settings
|
138 |
+
*
|
139 |
+
*/
|
140 |
+
if( ! empty( $file_contents['settings'] ) )
|
141 |
+
update_option( 'wpsbc_settings', $file_contents['settings'] );
|
142 |
+
|
143 |
+
// Redirect with a success message
|
144 |
+
wp_redirect( add_query_arg( array( 'page' => 'wpsbc-backup', 'wpsbc_message' => 'import_file_success' ), admin_url( 'admin.php' ) ) );
|
145 |
+
exit;
|
146 |
+
|
147 |
+
}
|
148 |
+
add_action( 'wpsbc_action_backup_import', 'wpsbc_action_backup_import' );
|
includes/base/admin/backup/functions.php
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Includes the files needed for the Backup/Restore admin area
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_include_files_admin_backup() {
|
12 |
+
|
13 |
+
// Get legend admin dir path
|
14 |
+
$dir_path = plugin_dir_path( __FILE__ );
|
15 |
+
|
16 |
+
// Include actions
|
17 |
+
if( file_exists( $dir_path . 'functions-actions-backup.php' ) )
|
18 |
+
include $dir_path . 'functions-actions-backup.php';
|
19 |
+
|
20 |
+
// Include submenu page
|
21 |
+
if( file_exists( $dir_path . 'class-submenu-page-backup.php' ) )
|
22 |
+
include $dir_path . 'class-submenu-page-backup.php';
|
23 |
+
|
24 |
+
}
|
25 |
+
add_action( 'wpsbc_include_files', 'wpsbc_include_files_admin_backup' );
|
26 |
+
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Register the Backup/Restore admin submenu page
|
30 |
+
*
|
31 |
+
*/
|
32 |
+
function wpsbc_register_submenu_page_backup( $submenu_pages ) {
|
33 |
+
|
34 |
+
if( ! is_array( $submenu_pages ) )
|
35 |
+
return $submenu_pages;
|
36 |
+
|
37 |
+
$submenu_pages['backup'] = array(
|
38 |
+
'class_name' => 'WPSBC_Submenu_Page_Backup',
|
39 |
+
'data' => array(
|
40 |
+
'page_title' => __( 'Backup/Restore', 'wp-simple-booking-calendar' ),
|
41 |
+
'menu_title' => __( 'Backup/Restore', 'wp-simple-booking-calendar' ),
|
42 |
+
'capability' => apply_filters( 'wpsbc_submenu_page_capability_backup', 'manage_options' ),
|
43 |
+
'menu_slug' => 'wpsbc-backup'
|
44 |
+
)
|
45 |
+
);
|
46 |
+
|
47 |
+
return $submenu_pages;
|
48 |
+
|
49 |
+
}
|
50 |
+
add_filter( 'wpsbc_register_submenu_page', 'wpsbc_register_submenu_page_backup', 75 );
|
includes/base/admin/backup/views/view-backup.php
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div class="wrap wpsbc-wrap">
|
9 |
+
|
10 |
+
<!-- Page Heading -->
|
11 |
+
<h1 class="wp-heading-inline"><?php echo __( 'Backup/Restore', 'wp-simple-booking-calendar' ); ?></h1>
|
12 |
+
<hr class="wp-header-end" />
|
13 |
+
|
14 |
+
<div id="poststuff" class="postbox-container">
|
15 |
+
|
16 |
+
<!-- Postbox Export -->
|
17 |
+
<div class="postbox">
|
18 |
+
|
19 |
+
<form method="POST" action="">
|
20 |
+
|
21 |
+
<h2 class="hndle"><?php echo __( 'Create export file', 'wp-simple-booking-calendar' ); ?></h2>
|
22 |
+
|
23 |
+
<!-- Form Fields -->
|
24 |
+
<div class="inside">
|
25 |
+
|
26 |
+
<p><?php echo __( 'To export a backup file for WP Simple Booking Calendar, please click the Download Export File button.', 'wp-simple-booking-calendar' ); ?></p>
|
27 |
+
|
28 |
+
<p><?php echo __( 'The export file will contain all information saved by the plugin, including calendars, bookings and general settings.', 'wp-simple-booking-calendar' ); ?></p>
|
29 |
+
|
30 |
+
</div>
|
31 |
+
|
32 |
+
<!-- Card Bottom -->
|
33 |
+
<div class="wpsbc-plugin-card-bottom plugin-card-bottom">
|
34 |
+
<input type="submit" class="button-primary" value="<?php echo __( 'Download Export File', 'wp-simple-booking-calendar' ); ?>" />
|
35 |
+
</div>
|
36 |
+
|
37 |
+
<!-- Nonce -->
|
38 |
+
<?php wp_nonce_field( 'wpsbc_backup_export', 'wpsbc_token', false ); ?>
|
39 |
+
<input type="hidden" name="wpsbc_action" value="backup_export" />
|
40 |
+
|
41 |
+
</form>
|
42 |
+
|
43 |
+
</div>
|
44 |
+
|
45 |
+
<!-- Postbox Import -->
|
46 |
+
<div class="postbox">
|
47 |
+
|
48 |
+
<form enctype="multipart/form-data" method="POST" action="">
|
49 |
+
|
50 |
+
<h2 class="hndle"><?php echo __( 'Import data from file', 'wp-simple-booking-calendar' ); ?></h2>
|
51 |
+
|
52 |
+
<!-- Form Fields -->
|
53 |
+
<div class="inside">
|
54 |
+
|
55 |
+
<p><?php echo __( 'To import all data from a WP Simple Booking Calendar export file, browse for that file and click the Import Data button.', 'wp-simple-booking-calendar' ); ?></p>
|
56 |
+
|
57 |
+
<p><?php echo __( 'Please take into account that this action will firstly remove all data that you currently have in the plugin, then import the data from the export file.', 'wp-simple-booking-calendar' ); ?></p>
|
58 |
+
|
59 |
+
<input type="file" name="import_file" />
|
60 |
+
|
61 |
+
</div>
|
62 |
+
|
63 |
+
<!-- Card Bottom -->
|
64 |
+
<div class="wpsbc-plugin-card-bottom plugin-card-bottom">
|
65 |
+
<input onclick="return confirm('<?php echo __( 'Are you sure you want to import data from the file?', 'wp-simple-booking-calendar' ); ?>' )" type="submit" class="button-primary" value="<?php echo __( 'Import Data', 'wp-simple-booking-calendar' ); ?>" />
|
66 |
+
</div>
|
67 |
+
|
68 |
+
<!-- Nonce -->
|
69 |
+
<?php wp_nonce_field( 'wpsbc_backup_import', 'wpsbc_token', false ); ?>
|
70 |
+
<input type="hidden" name="wpsbc_action" value="backup_import" />
|
71 |
+
|
72 |
+
</form>
|
73 |
+
|
74 |
+
</div>
|
75 |
+
|
76 |
+
</div>
|
77 |
+
|
78 |
+
</div>
|
includes/base/admin/calendar/class-calendar-editor-outputter.php
ADDED
@@ -0,0 +1,454 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if (!defined('ABSPATH')) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
class WPSBC_Calendar_Editor_Outputter
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* The arguments for the calendar outputter
|
13 |
+
*
|
14 |
+
* @access protected
|
15 |
+
* @var array
|
16 |
+
*
|
17 |
+
*/
|
18 |
+
protected $args;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* The WPSBC_Calendar
|
22 |
+
*
|
23 |
+
* @access protected
|
24 |
+
* @var WPSBC_Calendar
|
25 |
+
*
|
26 |
+
*/
|
27 |
+
protected $calendar = null;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* The list of legend items associated with the calendar
|
31 |
+
*
|
32 |
+
* @access protected
|
33 |
+
* @var array
|
34 |
+
*
|
35 |
+
*/
|
36 |
+
protected $legend_items = array();
|
37 |
+
|
38 |
+
/**
|
39 |
+
* The default legend item of the calendar
|
40 |
+
*
|
41 |
+
* @access protected
|
42 |
+
* @var WPSBC_Legend_Item
|
43 |
+
*
|
44 |
+
*/
|
45 |
+
protected $default_legend_item = null;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* The list of events for the calendar for the given displayed range
|
49 |
+
*
|
50 |
+
* @access protected
|
51 |
+
* @var array
|
52 |
+
*
|
53 |
+
*/
|
54 |
+
protected $events = array();
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Custom calendar data arranged by date
|
58 |
+
*
|
59 |
+
* @access protected
|
60 |
+
* @var array
|
61 |
+
*
|
62 |
+
*/
|
63 |
+
protected $data = array();
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Constructor
|
67 |
+
*
|
68 |
+
* @param int $calendar - the calendar for which to print the editable calendar fields
|
69 |
+
* @param array $args - arguments from which to build the calendar fields
|
70 |
+
* @param array $data - extra data to be populated in the calendar fields on top of the
|
71 |
+
* already saved events
|
72 |
+
*
|
73 |
+
*/
|
74 |
+
public function __construct($calendar, $args, $data = array())
|
75 |
+
{
|
76 |
+
|
77 |
+
$defaults = array(
|
78 |
+
'current_year' => (!empty($args['current_year']) ? $args['current_year'] : current_time('Y')),
|
79 |
+
'current_month' => (!empty($args['current_month']) ? $args['current_month'] : current_time('n')),
|
80 |
+
);
|
81 |
+
|
82 |
+
/**
|
83 |
+
* Set arguments
|
84 |
+
*
|
85 |
+
*/
|
86 |
+
$this->args = wp_parse_args($args, $defaults);
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Set the calendar
|
90 |
+
*
|
91 |
+
*/
|
92 |
+
$this->calendar = $calendar;
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Set the calendar legend items
|
96 |
+
*
|
97 |
+
*/
|
98 |
+
$this->legend_items = wpsbc_get_legend_items(array('calendar_id' => $calendar->get('id')));
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Set the default legend item
|
102 |
+
*
|
103 |
+
*/
|
104 |
+
foreach ($this->legend_items as $legend_item) {
|
105 |
+
|
106 |
+
if ($legend_item->get('is_default') == 1) {
|
107 |
+
$this->default_legend_item = $legend_item;
|
108 |
+
}
|
109 |
+
|
110 |
+
}
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Set the calendar events
|
114 |
+
*
|
115 |
+
*/
|
116 |
+
$this->events = wpsbc_get_events(array('calendar_id' => $calendar->get('id'), 'date_year' => $this->args['current_year'], 'date_month' => $this->args['current_month']));
|
117 |
+
|
118 |
+
/**
|
119 |
+
* Set the calendar data
|
120 |
+
*
|
121 |
+
*/
|
122 |
+
$this->data = $data;
|
123 |
+
|
124 |
+
}
|
125 |
+
|
126 |
+
/**
|
127 |
+
* Constructs and returns the HTML for the entire calendar month editor
|
128 |
+
*
|
129 |
+
* @return string
|
130 |
+
*
|
131 |
+
*/
|
132 |
+
public function get_display()
|
133 |
+
{
|
134 |
+
|
135 |
+
$total_days = date('t', mktime(0, 0, 0, $this->args['current_month'], 1, $this->args['current_year']));
|
136 |
+
|
137 |
+
$output = '<div id="wpsbc-calendar-editor">';
|
138 |
+
|
139 |
+
$output .= $this->get_display_date_header();
|
140 |
+
|
141 |
+
for ($i = 1; $i <= $total_days; $i++) {
|
142 |
+
|
143 |
+
$output .= $this->get_display_date($this->args['current_year'], $this->args['current_month'], $i);
|
144 |
+
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Calendar Editor Custom CSS
|
149 |
+
*
|
150 |
+
*/
|
151 |
+
$output .= $this->get_custom_css();
|
152 |
+
|
153 |
+
$output .= '</div>';
|
154 |
+
|
155 |
+
return $output;
|
156 |
+
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Constructs and returns the HTML for the dates columns header
|
161 |
+
*
|
162 |
+
* @return string
|
163 |
+
*
|
164 |
+
*/
|
165 |
+
protected function get_display_date_header()
|
166 |
+
{
|
167 |
+
|
168 |
+
$output = '<div class="wpsbc-calendar-date">';
|
169 |
+
|
170 |
+
$output .= '<div class="wpsbc-calendar-date-legend-item-header">' . __('Availability', 'wp-simple-booking-calendar') . '</div>';
|
171 |
+
$output .= '<div class="wpsbc-calendar-date-description-header">' . __('Description', 'wp-simple-booking-calendar') . wpsbc_get_output_tooltip(__('You can use the description field of the date to add private information regarding your booking. This information will not be displayed anywhere else, but here.', 'wp-simple-booking-calendar')) . '</div>';
|
172 |
+
|
173 |
+
$output .= '</div>';
|
174 |
+
|
175 |
+
return $output;
|
176 |
+
|
177 |
+
}
|
178 |
+
|
179 |
+
/**
|
180 |
+
* Constructs and returns the HTML for a single calendar given date
|
181 |
+
*
|
182 |
+
* @param int $year
|
183 |
+
* @param int $month
|
184 |
+
* @param int $day
|
185 |
+
*
|
186 |
+
* @return string
|
187 |
+
*
|
188 |
+
*/
|
189 |
+
protected function get_display_date($year, $month, $day)
|
190 |
+
{
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Prepare data
|
194 |
+
*
|
195 |
+
*/
|
196 |
+
$data = $this->get_data_by_date($year, $month, $day);
|
197 |
+
$event = $this->get_event_by_date($year, $month, $day);
|
198 |
+
|
199 |
+
/**
|
200 |
+
* Prepare output
|
201 |
+
*
|
202 |
+
*/
|
203 |
+
$output = '<div class="wpsbc-calendar-date">';
|
204 |
+
|
205 |
+
// Get the date legend item
|
206 |
+
$output .= $this->get_display_date_legend_item($year, $month, $day, $event, $data);
|
207 |
+
|
208 |
+
// Get the date description
|
209 |
+
$output .= $this->get_display_date_description($year, $month, $day, $event, $data);
|
210 |
+
|
211 |
+
// Set-up extra data that can be added by others
|
212 |
+
$output .= '<div class="wpsbc-calendar-date-meta">';
|
213 |
+
|
214 |
+
/**
|
215 |
+
* Filter to add custom calendar date meta
|
216 |
+
*
|
217 |
+
* @param int $year
|
218 |
+
* @param int $month
|
219 |
+
* @param int $day
|
220 |
+
* @param mixed WPSBC_Event|null
|
221 |
+
* @param mixed array|null
|
222 |
+
*
|
223 |
+
*/
|
224 |
+
$output .= apply_filters('wpsbc_calendar_editor_display_date', '', $year, $month, $day, $event, $data);
|
225 |
+
|
226 |
+
$output .= '</div>';
|
227 |
+
|
228 |
+
$output .= '</div>';
|
229 |
+
|
230 |
+
return $output;
|
231 |
+
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Constructs and returns the HTML for the date legend item selector
|
236 |
+
*
|
237 |
+
* @param int $year
|
238 |
+
* @param int $month
|
239 |
+
* @param int $day
|
240 |
+
* @param mixed WPSBC_Event|null
|
241 |
+
* @param mixed array|null
|
242 |
+
*
|
243 |
+
* @return string
|
244 |
+
*
|
245 |
+
*/
|
246 |
+
protected function get_display_date_legend_item($year, $month, $day, $event, $data)
|
247 |
+
{
|
248 |
+
|
249 |
+
/**
|
250 |
+
* Set selected value
|
251 |
+
*
|
252 |
+
*/
|
253 |
+
$selected_id = '';
|
254 |
+
$selected = null;
|
255 |
+
|
256 |
+
if (!is_null($data)) {
|
257 |
+
|
258 |
+
$selected_id = $data['legend_item_id'];
|
259 |
+
|
260 |
+
} elseif (!is_null($event)) {
|
261 |
+
|
262 |
+
$selected_id = $event->get('legend_item_id');
|
263 |
+
|
264 |
+
}
|
265 |
+
|
266 |
+
foreach ($this->legend_items as $legend_item) {
|
267 |
+
|
268 |
+
if ($selected_id == $legend_item->get('id')) {
|
269 |
+
$selected = $legend_item;
|
270 |
+
break;
|
271 |
+
}
|
272 |
+
|
273 |
+
}
|
274 |
+
|
275 |
+
// If none of the existing legend items is the selected one,
|
276 |
+
// set the default legend item as the selected one
|
277 |
+
if (is_null($selected)) {
|
278 |
+
$selected = $this->default_legend_item;
|
279 |
+
$selected_id = $selected->get('id');
|
280 |
+
}
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Prepare output
|
284 |
+
*
|
285 |
+
*/
|
286 |
+
$output = '<div class="wpsbc-calendar-date-legend-item wpsbc-calendar-date-legend-item-' . esc_attr($selected->get('id')) . '">';
|
287 |
+
|
288 |
+
$output .= '<div class="wpsbc-legend-item-icon-wrapper">';
|
289 |
+
$output .= '<div class="wpsbc-date-inner">' . esc_attr($day) . '</div>';
|
290 |
+
$output .= wpsbc_get_legend_item_icon($selected->get('id'), $selected->get('type'));
|
291 |
+
$output .= '</div>';
|
292 |
+
|
293 |
+
$output .= '<select data-name="legend_item_id" data-year="' . esc_attr($year) . '" data-month="' . esc_attr($month) . '" data-day="' . esc_attr($day) . '" ' . (!is_null($event) && is_null($event->get('id')) ? 'disabled' : '') . '>';
|
294 |
+
|
295 |
+
foreach ($this->legend_items as $legend_item) {
|
296 |
+
|
297 |
+
$output .= '<option value="' . esc_attr($legend_item->get('id')) . '" ' . selected($selected_id, $legend_item->get('id'), false) . ' data-type="' . esc_attr($legend_item->get('type')) . '">' . $legend_item->get('name') . '</option>';
|
298 |
+
|
299 |
+
}
|
300 |
+
|
301 |
+
$output .= '</select>';
|
302 |
+
$output .= '</div>';
|
303 |
+
|
304 |
+
return $output;
|
305 |
+
|
306 |
+
}
|
307 |
+
|
308 |
+
/**
|
309 |
+
* Constructs and returns the HTML for the date description field
|
310 |
+
*
|
311 |
+
* @param int $year
|
312 |
+
* @param int $month
|
313 |
+
* @param int $day
|
314 |
+
* @param mixed WPSBC_Event|null
|
315 |
+
* @param mixed array|null
|
316 |
+
*
|
317 |
+
* @return string
|
318 |
+
*
|
319 |
+
*/
|
320 |
+
protected function get_display_date_description($year, $month, $day, $event, $data)
|
321 |
+
{
|
322 |
+
|
323 |
+
/**
|
324 |
+
* Set selected value
|
325 |
+
*
|
326 |
+
*/
|
327 |
+
$value = '';
|
328 |
+
|
329 |
+
if (!is_null($data) && isset($data['description'])) {
|
330 |
+
|
331 |
+
$value = $data['description'];
|
332 |
+
|
333 |
+
} elseif (!is_null($event)) {
|
334 |
+
|
335 |
+
$value = $event->get('description');
|
336 |
+
|
337 |
+
}
|
338 |
+
|
339 |
+
/**
|
340 |
+
* Prepare output
|
341 |
+
*
|
342 |
+
*/
|
343 |
+
$output = '<div class="wpsbc-calendar-date-description">';
|
344 |
+
|
345 |
+
$output .= '<span class="dashicons dashicons-edit"></span>';
|
346 |
+
$output .= '<input type="text" value="' . esc_attr($value) . '" data-name="description" data-year="' . esc_attr($year) . '" data-month="' . esc_attr($month) . '" data-day="' . esc_attr($day) . '" />';
|
347 |
+
|
348 |
+
$output .= '</div>';
|
349 |
+
|
350 |
+
return $output;
|
351 |
+
|
352 |
+
}
|
353 |
+
|
354 |
+
/**
|
355 |
+
* Passes through all stored events and searches for the event that matches the given date
|
356 |
+
* If an event is found it is returned, else null is returned
|
357 |
+
*
|
358 |
+
* @param int $year
|
359 |
+
* @param int $month
|
360 |
+
* @param int $day
|
361 |
+
*
|
362 |
+
* @return mixed WPSBC_Event|null
|
363 |
+
*
|
364 |
+
*/
|
365 |
+
protected function get_event_by_date($year, $month, $day)
|
366 |
+
{
|
367 |
+
|
368 |
+
foreach ($this->events as $event) {
|
369 |
+
|
370 |
+
if ($event->get('date_year') == $year && $event->get('date_month') == $month && $event->get('date_day') == $day) {
|
371 |
+
return $event;
|
372 |
+
}
|
373 |
+
|
374 |
+
}
|
375 |
+
|
376 |
+
return null;
|
377 |
+
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Passes through all stored calendar data and searches for the data that matches the given date
|
382 |
+
* If data is found it is returned, else null is returned
|
383 |
+
*
|
384 |
+
* @param int $year
|
385 |
+
* @param int $month
|
386 |
+
* @param int $day
|
387 |
+
*
|
388 |
+
* @return mixed array|null
|
389 |
+
*
|
390 |
+
*/
|
391 |
+
protected function get_data_by_date($year, $month, $day)
|
392 |
+
{
|
393 |
+
|
394 |
+
if (isset($this->data[$year][$month][$day])) {
|
395 |
+
return $this->data[$year][$month][$day];
|
396 |
+
}
|
397 |
+
|
398 |
+
return null;
|
399 |
+
|
400 |
+
}
|
401 |
+
|
402 |
+
/**
|
403 |
+
* Constructs and returns the calendar's custom CSS
|
404 |
+
*
|
405 |
+
* @return string
|
406 |
+
*
|
407 |
+
*/
|
408 |
+
protected function get_custom_css()
|
409 |
+
{
|
410 |
+
|
411 |
+
$output = '<style>';
|
412 |
+
|
413 |
+
// Set the parent calendar class
|
414 |
+
$calendar_parent_class = '#wpsbc-calendar-editor';
|
415 |
+
|
416 |
+
/**
|
417 |
+
* Legend Items CSS
|
418 |
+
*
|
419 |
+
*/
|
420 |
+
foreach ($this->legend_items as $legend_item) {
|
421 |
+
|
422 |
+
// Background colors
|
423 |
+
$colors = $legend_item->get('color');
|
424 |
+
|
425 |
+
$output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:first-of-type { background-color: ' . (!empty($colors[0]) ? esc_attr($colors[0]) : 'transparent') . '; }';
|
426 |
+
$output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:nth-of-type(2) { background-color: ' . (!empty($colors[1]) ? esc_attr($colors[1]) : 'transparent') . '; }';
|
427 |
+
|
428 |
+
// Text color
|
429 |
+
$color_text = $legend_item->get('color_text');
|
430 |
+
|
431 |
+
if (!empty($color_text)) {
|
432 |
+
$output .= $calendar_parent_class . ' .wpsbc-calendar-date-legend-item-' . esc_attr($legend_item->get('id')) . ' .wpsbc-date-inner { color: ' . esc_attr($color_text) . '; }';
|
433 |
+
}
|
434 |
+
|
435 |
+
}
|
436 |
+
|
437 |
+
$output .= '</style>';
|
438 |
+
|
439 |
+
return $output;
|
440 |
+
|
441 |
+
}
|
442 |
+
|
443 |
+
/**
|
444 |
+
* Helper function that prints the calendar editor
|
445 |
+
*
|
446 |
+
*/
|
447 |
+
public function display()
|
448 |
+
{
|
449 |
+
|
450 |
+
echo $this->get_display();
|
451 |
+
|
452 |
+
}
|
453 |
+
|
454 |
+
}
|
includes/base/admin/calendar/class-list-table-calendars.php
ADDED
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* List table class outputter for Calendars
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
Class WPSBC_WP_List_Table_Calendars extends WPSBC_WP_List_Table {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The number of calendars that should appear in the table
|
15 |
+
*
|
16 |
+
* @access private
|
17 |
+
* @var int
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
private $items_per_page;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* The number of the page being displayed by the pagination
|
24 |
+
*
|
25 |
+
* @access private
|
26 |
+
* @var int
|
27 |
+
*
|
28 |
+
*/
|
29 |
+
private $paged;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The data of the table
|
33 |
+
*
|
34 |
+
* @access public
|
35 |
+
* @var array
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
public $data = array();
|
39 |
+
|
40 |
+
|
41 |
+
/**
|
42 |
+
* Constructor
|
43 |
+
*
|
44 |
+
*/
|
45 |
+
public function __construct() {
|
46 |
+
|
47 |
+
parent::__construct( array(
|
48 |
+
'plural' => 'wpsbc_calendars',
|
49 |
+
'singular' => 'wpsbc_calendar',
|
50 |
+
'ajax' => false
|
51 |
+
));
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Filter the number of calendars shown in the table
|
55 |
+
*
|
56 |
+
* @param int
|
57 |
+
*
|
58 |
+
*/
|
59 |
+
$this->items_per_page = apply_filters( 'wpsbc_list_table_calendars_items_per_page', 20 );
|
60 |
+
|
61 |
+
$this->paged = ( ! empty( $_GET['paged'] ) ? (int)$_GET['paged'] : 1 );
|
62 |
+
|
63 |
+
$this->set_pagination_args( array(
|
64 |
+
'total_items' => wpsbc_get_calendars( array( 'number' => -1, 'search' => ( ! empty( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '' ) ), true ),
|
65 |
+
'per_page' => $this->items_per_page
|
66 |
+
));
|
67 |
+
|
68 |
+
// Get and set table data
|
69 |
+
$this->set_table_data();
|
70 |
+
|
71 |
+
// Add column headers and table items
|
72 |
+
$this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
|
73 |
+
$this->items = $this->data;
|
74 |
+
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Returns all the columns for the table
|
80 |
+
*
|
81 |
+
*/
|
82 |
+
public function get_columns() {
|
83 |
+
|
84 |
+
$columns = array(
|
85 |
+
'name' => __( 'Name', 'wp-simple-booking-calendar' ),
|
86 |
+
'id' => __( 'ID', 'wp-simple-booking-calendar' ),
|
87 |
+
'date_created' => __( 'Date Created', 'wp-simple-booking-calendar' ),
|
88 |
+
'date_modified' => __( 'Date Modified', 'wp-simple-booking-calendar' )
|
89 |
+
);
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Filter the columns of the calendars table
|
93 |
+
*
|
94 |
+
* @param array $columns
|
95 |
+
*
|
96 |
+
*/
|
97 |
+
return apply_filters( 'wpsbc_list_table_calendars_columns', $columns );
|
98 |
+
|
99 |
+
}
|
100 |
+
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Overwrites the parent class.
|
104 |
+
* Define which columns are sortable
|
105 |
+
*
|
106 |
+
* @return array
|
107 |
+
*
|
108 |
+
*/
|
109 |
+
public function get_sortable_columns() {
|
110 |
+
|
111 |
+
return array(
|
112 |
+
'name' => array( 'name', false ),
|
113 |
+
'id' => array( 'id', false ),
|
114 |
+
'date_created' => array( 'date_created', false ),
|
115 |
+
'date_modified' => array( 'date_modified', false )
|
116 |
+
);
|
117 |
+
|
118 |
+
}
|
119 |
+
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Returns the possible views for the calendar list table
|
123 |
+
*
|
124 |
+
*/
|
125 |
+
protected function get_views() {
|
126 |
+
|
127 |
+
$calendar_status = ( ! empty( $_GET['calendar_status'] ) ? sanitize_text_field( $_GET['calendar_status'] ) : 'active' );
|
128 |
+
|
129 |
+
$views = array(
|
130 |
+
'active' => '<a href="' . add_query_arg( array( 'page' => 'wpsbc-calendars', 'calendar_status' => 'active', 'paged' => 1, 's' => ( ! empty( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '' ) ), admin_url( 'admin.php' ) ) . '" ' . ( $calendar_status == 'active' ? 'class="current"' : '' ) . '>' . __( 'Active', 'wp-simple-booking-calendar' ) . ' <span class="count">(' . wpsbc_get_calendars( array( 'status' => 'active', 'search' => ( ! empty( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '' ) ), true ) . ')</span></a>',
|
131 |
+
'trash' => '<a href="' . add_query_arg( array( 'page' => 'wpsbc-calendars', 'calendar_status' => 'trash', 'paged' => 1, 's' => ( ! empty( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '' ) ), admin_url( 'admin.php' ) ) . '" ' . ( $calendar_status == 'trash' ? 'class="current"' : '' ) . '>' . __( 'Trash', 'wp-simple-booking-calendar' ) . ' <span class="count">(' . wpsbc_get_calendars( array( 'status' => 'trash', 'search' => ( ! empty( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '' ) ), true ) . ')</span></a>',
|
132 |
+
);
|
133 |
+
|
134 |
+
/**
|
135 |
+
* Filter the views of the calendars table
|
136 |
+
*
|
137 |
+
* @param array $views
|
138 |
+
*
|
139 |
+
*/
|
140 |
+
return apply_filters( 'wpsbc_list_table_calendars_views', $views );
|
141 |
+
|
142 |
+
}
|
143 |
+
|
144 |
+
|
145 |
+
/**
|
146 |
+
* Gets the calendars data and sets it
|
147 |
+
*
|
148 |
+
*/
|
149 |
+
private function set_table_data() {
|
150 |
+
|
151 |
+
$calendar_args = array(
|
152 |
+
'number' => $this->items_per_page,
|
153 |
+
'offset' => ( $this->paged - 1 ) * $this->items_per_page,
|
154 |
+
'status' => ( ! empty( $_GET['calendar_status'] ) ? sanitize_text_field( $_GET['calendar_status'] ) : 'active' ),
|
155 |
+
'orderby' => ( ! empty( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'id' ),
|
156 |
+
'order' => ( ! empty( $_GET['order'] ) ? sanitize_text_field( strtoupper( $_GET['order'] ) ) : 'DESC' ),
|
157 |
+
'search' => ( ! empty( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : '' )
|
158 |
+
);
|
159 |
+
|
160 |
+
$calendars = wpsbc_get_calendars( $calendar_args );
|
161 |
+
|
162 |
+
if( empty( $calendars ) )
|
163 |
+
return;
|
164 |
+
|
165 |
+
foreach( $calendars as $calendar ) {
|
166 |
+
|
167 |
+
$row_data = $calendar->to_array();
|
168 |
+
|
169 |
+
/**
|
170 |
+
* Filter the calendar row data
|
171 |
+
*
|
172 |
+
* @param array $row_data
|
173 |
+
* @param WPSBC_Calendar $calendar
|
174 |
+
*
|
175 |
+
*/
|
176 |
+
$row_data = apply_filters( 'wpsbc_list_table_calendars_row_data', $row_data, $calendar );
|
177 |
+
|
178 |
+
$this->data[] = $row_data;
|
179 |
+
|
180 |
+
}
|
181 |
+
|
182 |
+
}
|
183 |
+
|
184 |
+
|
185 |
+
/**
|
186 |
+
* Returns the HTML that will be displayed in each columns
|
187 |
+
*
|
188 |
+
* @param array $item - data for the current row
|
189 |
+
* @param string $column_name - name of the current column
|
190 |
+
*
|
191 |
+
* @return string
|
192 |
+
*
|
193 |
+
*/
|
194 |
+
public function column_default( $item, $column_name ) {
|
195 |
+
|
196 |
+
return isset( $item[ $column_name ] ) ? $item[ $column_name ] : '-';
|
197 |
+
|
198 |
+
}
|
199 |
+
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Returns the HTML that will be displayed in the "name" column
|
203 |
+
*
|
204 |
+
* @param array $item - data for the current row
|
205 |
+
*
|
206 |
+
* @return string
|
207 |
+
*
|
208 |
+
*/
|
209 |
+
public function column_name( $item ) {
|
210 |
+
|
211 |
+
if( $item['status'] == 'active' ) {
|
212 |
+
|
213 |
+
$output = '<strong><a class="row-title" href="' . add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'edit-calendar', 'calendar_id' => $item['id'] ) , admin_url( 'admin.php' ) ) . '">' . ( !empty( $item['name'] ) ? $item['name'] : '' ) . '</a></strong>';
|
214 |
+
|
215 |
+
$actions = array(
|
216 |
+
'edit_calendar' => '<a href="' . add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'edit-calendar', 'calendar_id' => $item['id'] ) , admin_url( 'admin.php' ) ) . '">' . __( 'Edit Calendar', 'wp-simple-booking-calendar' ) . '</a>',
|
217 |
+
'view_legend' => '<a href="' . add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'view-legend', 'calendar_id' => $item['id'] ) , admin_url( 'admin.php' ) ) . '">' . __( 'Edit Calendar Legend', 'wp-simple-booking-calendar' ) . '</a>',
|
218 |
+
'trash' => '<span class="trash"><a onclick="return confirm( \'' . __( "Are you sure you want to send this calendar to the trash?", "wp-simple-booking-calendar" ) . ' \' )" href="' . wp_nonce_url( add_query_arg( array( 'page' => 'wpsbc-calendars', 'wpsbc_action' => 'trash_calendar', 'calendar_id' => $item['id'] ) , admin_url( 'admin.php' ) ), 'wpsbc_trash_calendar', 'wpsbc_token' ) . '" class="submitdelete">' . __( 'Trash', 'wp-simple-booking-calendar' ) . '</a></span>'
|
219 |
+
);
|
220 |
+
|
221 |
+
}
|
222 |
+
|
223 |
+
if( $item['status'] == 'trash' ) {
|
224 |
+
|
225 |
+
$output = '<strong>' . ( !empty( $item['name'] ) ? $item['name'] : '' ) . '</strong>';
|
226 |
+
|
227 |
+
$actions = array(
|
228 |
+
'restore_calendar' => '<a href="' . wp_nonce_url( add_query_arg( array( 'page' => 'wpsbc-calendars', 'wpsbc_action' => 'restore_calendar', 'calendar_id' => $item['id'] ) , admin_url( 'admin.php' ) ), 'wpsbc_restore_calendar', 'wpsbc_token' ) . '">' . __( 'Restore Calendar', 'wp-simple-booking-calendar' ) . '</a>',
|
229 |
+
'delete' => '<span class="trash"><a onclick="return confirm( \'' . __( "Are you sure you want to delete this calendar?", "wp-simple-booking-calendar" ) . ' \' )" href="' . wp_nonce_url( add_query_arg( array( 'page' => 'wpsbc-calendars', 'wpsbc_action' => 'delete_calendar', 'calendar_id' => $item['id'] ) , admin_url( 'admin.php' ) ), 'wpsbc_delete_calendar', 'wpsbc_token' ) . '" class="submitdelete">' . __( 'Delete Permanently', 'wp-simple-booking-calendar' ) . '</a></span>'
|
230 |
+
);
|
231 |
+
|
232 |
+
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Filter the row actions before adding them to the table
|
236 |
+
*
|
237 |
+
* @param array $actions
|
238 |
+
* @param array $item
|
239 |
+
*
|
240 |
+
*/
|
241 |
+
$actions = apply_filters( 'wpsbc_list_table_calendars_row_actions', $actions, $item );
|
242 |
+
|
243 |
+
$output .= $this->row_actions( $actions );
|
244 |
+
|
245 |
+
return $output;
|
246 |
+
|
247 |
+
}
|
248 |
+
|
249 |
+
|
250 |
+
/**
|
251 |
+
* Returns the HTML that will be displayed in the "date_created" column
|
252 |
+
*
|
253 |
+
* @param array $item - data for the current row
|
254 |
+
*
|
255 |
+
* @return string
|
256 |
+
*
|
257 |
+
*/
|
258 |
+
public function column_date_created( $item ) {
|
259 |
+
|
260 |
+
$output = date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $item['date_created'] ) );
|
261 |
+
|
262 |
+
return $output;
|
263 |
+
|
264 |
+
}
|
265 |
+
|
266 |
+
|
267 |
+
/**
|
268 |
+
* Returns the HTML that will be displayed in the "date_created" column
|
269 |
+
*
|
270 |
+
* @param array $item - data for the current row
|
271 |
+
*
|
272 |
+
* @return string
|
273 |
+
*
|
274 |
+
*/
|
275 |
+
public function column_date_modified( $item ) {
|
276 |
+
|
277 |
+
$output = date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $item['date_modified'] ) );
|
278 |
+
|
279 |
+
return $output;
|
280 |
+
|
281 |
+
}
|
282 |
+
|
283 |
+
|
284 |
+
/**
|
285 |
+
* HTML display when there are no items in the table
|
286 |
+
*
|
287 |
+
*/
|
288 |
+
public function no_items() {
|
289 |
+
|
290 |
+
echo __( 'No calendars found.', 'wp-simple-booking-calendar' );
|
291 |
+
|
292 |
+
}
|
293 |
+
|
294 |
+
}
|
includes/base/admin/calendar/class-submenu-page-calendar.php
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if (!defined('ABSPATH')) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
class WPSBC_Submenu_Page_Calendars extends WPSBC_Submenu_Page
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Helper init method that runs on parent __construct
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
protected function init()
|
16 |
+
{
|
17 |
+
|
18 |
+
add_action('admin_init', array($this, 'register_admin_notices'), 10);
|
19 |
+
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Callback method to register admin notices that are sent via URL parameters
|
24 |
+
*
|
25 |
+
*/
|
26 |
+
public function register_admin_notices()
|
27 |
+
{
|
28 |
+
|
29 |
+
if (empty($_GET['wpsbc_message'])) {
|
30 |
+
return;
|
31 |
+
}
|
32 |
+
|
33 |
+
// Calendar insert success
|
34 |
+
wpsbc_admin_notices()->register_notice('calendar_insert_success', '<p>' . __('Calendar created successfully.', 'wp-simple-booking-calendar') . '</p>');
|
35 |
+
|
36 |
+
// Calendar updated successfully
|
37 |
+
wpsbc_admin_notices()->register_notice('calendar_update_success', '<p>' . __('Calendar updated successfully.', 'wp-simple-booking-calendar') . '</p>');
|
38 |
+
|
39 |
+
// Calendar updated fail
|
40 |
+
wpsbc_admin_notices()->register_notice('calendar_update_fail', '<p>' . __('Something went wrong. Could not update the calendar.', 'wp-simple-booking-calendar') . '</p>', 'error');
|
41 |
+
|
42 |
+
// Calendar trash success
|
43 |
+
wpsbc_admin_notices()->register_notice('calendar_trash_success', '<p>' . __('Calendar successfully moved to Trash.', 'wp-simple-booking-calendar') . '</p>');
|
44 |
+
|
45 |
+
// Calendar restore success
|
46 |
+
wpsbc_admin_notices()->register_notice('calendar_restore_success', '<p>' . __('Calendar has been successfully restored.', 'wp-simple-booking-calendar') . '</p>');
|
47 |
+
|
48 |
+
// Calendar delete success
|
49 |
+
wpsbc_admin_notices()->register_notice('calendar_delete_success', '<p>' . __('Calendar has been successfully deleted.', 'wp-simple-booking-calendar') . '</p>');
|
50 |
+
|
51 |
+
// Legend item insert success
|
52 |
+
wpsbc_admin_notices()->register_notice('legend_item_insert_success', '<p>' . __('Legend item created successfully.', 'wp-simple-booking-calendar') . '</p>');
|
53 |
+
|
54 |
+
// Legend item update success
|
55 |
+
wpsbc_admin_notices()->register_notice('legend_item_update_success', '<p>' . __('Legend item updated successfully.', 'wp-simple-booking-calendar') . '</p>');
|
56 |
+
|
57 |
+
// Legend item delete success
|
58 |
+
wpsbc_admin_notices()->register_notice('legend_item_delete_success', '<p>' . __('Legend item deleted successfully.', 'wp-simple-booking-calendar') . '</p>');
|
59 |
+
|
60 |
+
// Legend items sort fail
|
61 |
+
wpsbc_admin_notices()->register_notice('sort_legend_items_fail', '<p>' . __('Something went wrong. Could not sort the legend items.', 'wp-simple-booking-calendar') . '</p>', 'error');
|
62 |
+
|
63 |
+
// Legend item make visible/invisible
|
64 |
+
if ($_GET['wpsbc_message'] == 'legend_item_make_visible_success' || $_GET['wpsbc_message'] == 'legend_item_make_invisible_success') {
|
65 |
+
|
66 |
+
$legend_item_id = absint($_GET['legend_item_id']);
|
67 |
+
$legend_item = wpsbc_get_legend_item($legend_item_id);
|
68 |
+
|
69 |
+
wpsbc_admin_notices()->register_notice('legend_item_make_visible_success', '<p>' . sprintf(__('Legend item %s is now visible.', 'wp-simple-booking-calendar'), '<strong>' . $legend_item->get('name') . '</strong>') . '</p>');
|
70 |
+
wpsbc_admin_notices()->register_notice('legend_item_make_invisible_success', '<p>' . sprintf(__('Legend item %s is now hidden.', 'wp-simple-booking-calendar'), '<strong>' . $legend_item->get('name') . '</strong>') . '</p>');
|
71 |
+
|
72 |
+
}
|
73 |
+
|
74 |
+
// Legend item make default
|
75 |
+
if ($_GET['wpsbc_message'] == 'legend_item_make_default_success') {
|
76 |
+
|
77 |
+
$legend_item_id = absint($_GET['legend_item_id']);
|
78 |
+
$legend_item = wpsbc_get_legend_item($legend_item_id);
|
79 |
+
|
80 |
+
wpsbc_admin_notices()->register_notice('legend_item_make_default_success', '<p>' . sprintf(__('%s legend item is now the default one.', 'wp-simple-booking-calendar'), '<strong>' . $legend_item->get('name') . '</strong>') . '</p>');
|
81 |
+
|
82 |
+
}
|
83 |
+
|
84 |
+
}
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Callback for the HTML output for the Calendar page
|
88 |
+
*
|
89 |
+
*/
|
90 |
+
public function output()
|
91 |
+
{
|
92 |
+
|
93 |
+
if (empty($this->current_subpage)) {
|
94 |
+
include 'views/view-calendars.php';
|
95 |
+
} else {
|
96 |
+
|
97 |
+
if ($this->current_subpage == 'add-calendar') {
|
98 |
+
if (count(wpsbc_get_calendars()) > 0) {
|
99 |
+
include WPSBC_PLUGIN_DIR . 'includes/base/admin/upgrade-to-premium.php';
|
100 |
+
} else {
|
101 |
+
include 'views/view-add-calendar.php';
|
102 |
+
}
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
if ($this->current_subpage == 'edit-calendar') {
|
107 |
+
include 'views/view-edit-calendar.php';
|
108 |
+
}
|
109 |
+
|
110 |
+
if ($this->current_subpage == 'view-legend') {
|
111 |
+
include WPSBC_PLUGIN_DIR . 'includes/base/admin/upgrade-to-premium.php';
|
112 |
+
}
|
113 |
+
|
114 |
+
if ($this->current_subpage == 'ical-import-export') {
|
115 |
+
include WPSBC_PLUGIN_DIR . 'includes/base/admin/upgrade-to-premium.php';
|
116 |
+
}
|
117 |
+
|
118 |
+
if ($this->current_subpage == 'upgrade-to-premium') {
|
119 |
+
include WPSBC_PLUGIN_DIR . 'includes/base/admin/upgrade-to-premium.php';
|
120 |
+
}
|
121 |
+
|
122 |
+
if ($this->current_subpage == 'csv-export') {
|
123 |
+
include WPSBC_PLUGIN_DIR . 'includes/base/admin/upgrade-to-premium.php';
|
124 |
+
}
|
125 |
+
|
126 |
+
}
|
127 |
+
|
128 |
+
}
|
129 |
+
|
130 |
+
}
|
includes/base/admin/calendar/functions-actions-ajax-calendar.php
ADDED
@@ -0,0 +1,241 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Ajax callback to refresh the calendar with new given data from JS
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_refresh_calendar_editor() {
|
12 |
+
|
13 |
+
if( empty( $_POST['action'] ) || $_POST['action'] != 'wpsbc_refresh_calendar_editor' ) {
|
14 |
+
echo __( '', 'wp-simple-booking-calendar' );
|
15 |
+
wp_die();
|
16 |
+
}
|
17 |
+
|
18 |
+
if( empty( $_POST['id'] ) ) {
|
19 |
+
wp_die();
|
20 |
+
}
|
21 |
+
|
22 |
+
$_POST = stripslashes_deep( $_POST );
|
23 |
+
|
24 |
+
/**
|
25 |
+
* The calendar data had to be JSON encoded due to the php input limit which limited
|
26 |
+
* the number of arrays that could be sent.
|
27 |
+
*
|
28 |
+
* If the calendar data would contain data for a number of years this would be chopped
|
29 |
+
*
|
30 |
+
*/
|
31 |
+
$_POST['calendar_data'] = ( ! empty( $_POST['calendar_data'] ) ? json_decode( $_POST['calendar_data'], true ) : array() );
|
32 |
+
|
33 |
+
$calendar_id = absint( $_POST['id'] );
|
34 |
+
$calendar = wpsbc_get_calendar( $calendar_id );
|
35 |
+
|
36 |
+
$calendar_args = array();
|
37 |
+
$calendar_data = ( ! empty( $_POST['calendar_data'] ) ? $_POST['calendar_data'] : array() );
|
38 |
+
|
39 |
+
foreach( $_POST as $key => $val ) {
|
40 |
+
|
41 |
+
if( in_array( $key, array_keys( wpsbc_get_calendar_output_default_args() ) ) )
|
42 |
+
$calendar_args[$key] = sanitize_text_field( $val );
|
43 |
+
|
44 |
+
}
|
45 |
+
|
46 |
+
$calendar_outputter = new WPSBC_Calendar_Outputter( $calendar, $calendar_args );
|
47 |
+
$calendar_editor_outputter = new WPSBC_Calendar_Editor_Outputter( $calendar, $calendar_args, $calendar_data );
|
48 |
+
|
49 |
+
$output = array(
|
50 |
+
'calendar' => $calendar_outputter->get_display(),
|
51 |
+
'calendar_editor' => $calendar_editor_outputter->get_display()
|
52 |
+
);
|
53 |
+
|
54 |
+
echo json_encode( $output );
|
55 |
+
wp_die();
|
56 |
+
|
57 |
+
}
|
58 |
+
add_action( 'wp_ajax_wpsbc_refresh_calendar_editor', 'wpsbc_refresh_calendar_editor' );
|
59 |
+
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Ajax callback to save the calendar events data in the database
|
63 |
+
*
|
64 |
+
*/
|
65 |
+
function wpsbc_save_calendar_data() {
|
66 |
+
|
67 |
+
$_POST = stripslashes_deep( $_POST );
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Parse the form data as name value pair
|
71 |
+
*
|
72 |
+
*/
|
73 |
+
if( empty( $_POST['form_data'] ) ) {
|
74 |
+
|
75 |
+
echo add_query_arg( array( 'page' => 'wpsbc-calendars', 'wpsbc_message' => 'calendar_update_fail' ), admin_url( 'admin.php' ) );
|
76 |
+
wp_die();
|
77 |
+
|
78 |
+
}
|
79 |
+
|
80 |
+
parse_str( $_POST['form_data'], $_POST['form_data'] );
|
81 |
+
|
82 |
+
|
83 |
+
/**
|
84 |
+
* The calendar data had to be JSON encoded due to the php input limit which limited
|
85 |
+
* the number of arrays that could be sent.
|
86 |
+
*
|
87 |
+
* If the calendar data would contain data for a number of years this would be chopped
|
88 |
+
*
|
89 |
+
*/
|
90 |
+
$_POST['calendar_data'] = ( ! empty( $_POST['calendar_data'] ) ? json_decode( $_POST['calendar_data'], true ) : array() );
|
91 |
+
|
92 |
+
if( empty( $_POST['form_data']['calendar_id'] ) ) {
|
93 |
+
|
94 |
+
echo add_query_arg( array( 'page' => 'wpsbc-calendars', 'wpsbc_message' => 'calendar_update_fail' ), admin_url( 'admin.php' ) );
|
95 |
+
wp_die();
|
96 |
+
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Prepare variables
|
101 |
+
*
|
102 |
+
*/
|
103 |
+
$calendar_id = absint( $_POST['form_data']['calendar_id'] );
|
104 |
+
$calendar_name = sanitize_text_field( $_POST['form_data']['calendar_name'] );
|
105 |
+
$calendar_data = ( ! empty( $_POST['calendar_data'] ) ? _wpsbc_array_wp_kses_post( $_POST['calendar_data'] ) : array() );
|
106 |
+
|
107 |
+
/**
|
108 |
+
* Get default legend item
|
109 |
+
*
|
110 |
+
*/
|
111 |
+
$legend_items = wpsbc_get_legend_items( array( 'calendar_id' => $calendar_id, 'is_default' => 1 ) );
|
112 |
+
$default_legend_item = ( ! empty( $legend_items ) && is_array( $legend_items ) ? $legend_items[0] : null );
|
113 |
+
|
114 |
+
// If there is no default legend item return with an error
|
115 |
+
if( is_null( $default_legend_item ) ) {
|
116 |
+
|
117 |
+
echo add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'edit-calendar', 'calendar_id' => $calendar_id, 'wpsbc_message' => 'calendar_update_fail' ), admin_url( 'admin.php' ) );
|
118 |
+
wp_die();
|
119 |
+
|
120 |
+
}
|
121 |
+
|
122 |
+
|
123 |
+
/**
|
124 |
+
* Action hook to save extra calendar form data
|
125 |
+
*
|
126 |
+
* @param array $_POST
|
127 |
+
*
|
128 |
+
*/
|
129 |
+
do_action( 'wpsbc_save_calendar_data', $_POST );
|
130 |
+
|
131 |
+
|
132 |
+
/**
|
133 |
+
* Handle calendar object data
|
134 |
+
*
|
135 |
+
*/
|
136 |
+
|
137 |
+
// Get calendar
|
138 |
+
$calendar = wpsbc_get_calendar( $calendar_id );
|
139 |
+
|
140 |
+
// Update calendar
|
141 |
+
$update_data = array(
|
142 |
+
'name' => ( ! empty( $calendar_name ) ? $calendar_name : $calendar->get('name') ),
|
143 |
+
'date_modified' => current_time( 'Y-m-d H:i:s' )
|
144 |
+
);
|
145 |
+
|
146 |
+
wpsbc_update_calendar( $calendar_id, $update_data );
|
147 |
+
|
148 |
+
|
149 |
+
// Update Calendar Meta
|
150 |
+
$settings = get_option( 'wpsbc_settings', array() );
|
151 |
+
|
152 |
+
if(isset($settings['active_languages']) && count($settings['active_languages']) > 0){
|
153 |
+
foreach($settings['active_languages'] as $language){
|
154 |
+
wpsbc_update_calendar_meta($calendar_id, 'calendar_name_translation_' . $language, sanitize_text_field($_POST['form_data']['calendar_name_translation_' . $language]));
|
155 |
+
}
|
156 |
+
}
|
157 |
+
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Handle event objects data
|
161 |
+
*
|
162 |
+
*/
|
163 |
+
$events_args = array(
|
164 |
+
'calendar_id' => $calendar_id
|
165 |
+
);
|
166 |
+
|
167 |
+
$events = wpsbc_get_events( $events_args );
|
168 |
+
|
169 |
+
$events_data = array();
|
170 |
+
|
171 |
+
// Prepare events data for saving
|
172 |
+
foreach( $calendar_data as $year => $months ) {
|
173 |
+
|
174 |
+
foreach( $months as $month => $days ) {
|
175 |
+
|
176 |
+
foreach( $days as $day => $event_data ) {
|
177 |
+
|
178 |
+
// Set event calendar id
|
179 |
+
$event_data['calendar_id'] = $calendar_id;
|
180 |
+
|
181 |
+
// Set event date data
|
182 |
+
$event_data['date_year'] = $year;
|
183 |
+
$event_data['date_month'] = $month;
|
184 |
+
$event_data['date_day'] = $day;
|
185 |
+
|
186 |
+
// Add event to events array
|
187 |
+
if(checkdate($month, $day, $year)){
|
188 |
+
$events_data[] = $event_data;
|
189 |
+
}
|
190 |
+
}
|
191 |
+
}
|
192 |
+
}
|
193 |
+
|
194 |
+
|
195 |
+
// Save events data
|
196 |
+
foreach( $events_data as $event_data ) {
|
197 |
+
|
198 |
+
// Check to see if event exists
|
199 |
+
$event = null;
|
200 |
+
|
201 |
+
foreach( $events as $_event ) {
|
202 |
+
|
203 |
+
if( $_event->get('date_year') == $event_data['date_year'] && $_event->get('date_month') == $event_data['date_month'] && $_event->get('date_day') == $event_data['date_day'] ) {
|
204 |
+
$event = $_event;
|
205 |
+
break;
|
206 |
+
}
|
207 |
+
|
208 |
+
}
|
209 |
+
|
210 |
+
// Handle insert
|
211 |
+
if( is_null( $event ) ) {
|
212 |
+
|
213 |
+
if( $default_legend_item->get('id') == $event_data['legend_item_id'] && empty( $event_data['description'] ) && empty( $event_data['tooltip'] ) )
|
214 |
+
continue;
|
215 |
+
|
216 |
+
wpsbc_insert_event( $event_data );
|
217 |
+
|
218 |
+
// Handle update
|
219 |
+
} else {
|
220 |
+
|
221 |
+
// For update we don't need the entire data set
|
222 |
+
unset( $event_data['calendar_id'] );
|
223 |
+
unset( $event_data['date_year'] );
|
224 |
+
unset( $event_data['date_month'] );
|
225 |
+
unset( $event_data['date_day'] );
|
226 |
+
|
227 |
+
wpsbc_update_event( $event->get('id'), $event_data );
|
228 |
+
|
229 |
+
}
|
230 |
+
|
231 |
+
}
|
232 |
+
|
233 |
+
/**
|
234 |
+
* Success redirect
|
235 |
+
*
|
236 |
+
*/
|
237 |
+
echo add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'edit-calendar', 'calendar_id' => $calendar_id, 'year' => (int)$_POST['current_year'], 'month' => (int)$_POST['current_month'], 'wpsbc_message' => 'calendar_update_success' ), admin_url( 'admin.php' ) );
|
238 |
+
wp_die();
|
239 |
+
|
240 |
+
}
|
241 |
+
add_action( 'wp_ajax_wpsbc_save_calendar_data', 'wpsbc_save_calendar_data' );
|
includes/base/admin/calendar/functions-actions-calendar.php
ADDED
@@ -0,0 +1,299 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if (!defined('ABSPATH')) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Validates and handles the adding of the new calendar in the database
|
10 |
+
*
|
11 |
+
*/
|
12 |
+
function wpsbc_action_add_calendar()
|
13 |
+
{
|
14 |
+
|
15 |
+
// Verify for nonce
|
16 |
+
if (empty($_POST['wpsbc_token']) || !wp_verify_nonce($_POST['wpsbc_token'], 'wpsbc_add_calendar')) {
|
17 |
+
return;
|
18 |
+
}
|
19 |
+
|
20 |
+
// Verify for calendar name
|
21 |
+
if (empty($_POST['calendar_name'])) {
|
22 |
+
|
23 |
+
wpsbc_admin_notices()->register_notice('calendar_name_missing', '<p>' . __('Please add a name for your new calendar.', 'wp-simple-booking-calendar') . '</p>', 'error');
|
24 |
+
wpsbc_admin_notices()->display_notice('calendar_name_missing');
|
25 |
+
|
26 |
+
return;
|
27 |
+
|
28 |
+
}
|
29 |
+
|
30 |
+
// Prepare calendar data to be inserted
|
31 |
+
$calendar_data = array(
|
32 |
+
'name' => sanitize_text_field($_POST['calendar_name']),
|
33 |
+
'date_created' => current_time('Y-m-d H:i:s'),
|
34 |
+
'date_modified' => current_time('Y-m-d H:i:s'),
|
35 |
+
'status' => 'active',
|
36 |
+
'ical_hash' => wpsbc_generate_ical_hash(),
|
37 |
+
);
|
38 |
+
|
39 |
+
// Insert calendar into the database
|
40 |
+
$calendar_id = wpsbc_insert_calendar($calendar_data);
|
41 |
+
|
42 |
+
// If the calendar could not be inserted show a message to the user
|
43 |
+
if (!$calendar_id) {
|
44 |
+
|
45 |
+
wpsbc_admin_notices()->register_notice('calendar_insert_false', '<p>' . __('Something went wrong. Could not create the calendar. Please try again.', 'wp-simple-booking-calendar') . '</p>', 'error');
|
46 |
+
wpsbc_admin_notices()->display_notice('calendar_insert_false');
|
47 |
+
|
48 |
+
return;
|
49 |
+
|
50 |
+
}
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Add default legend items
|
54 |
+
*
|
55 |
+
*/
|
56 |
+
|
57 |
+
$legend_items_data = wpsbc_get_default_legend_items_data();
|
58 |
+
|
59 |
+
foreach ($legend_items_data as $legend_item_data) {
|
60 |
+
|
61 |
+
// Set the calendar id for the legend items data
|
62 |
+
$legend_item_data['calendar_id'] = $calendar_id;
|
63 |
+
|
64 |
+
// Insert legend item
|
65 |
+
$legend_id = wpsbc_insert_legend_item($legend_item_data);
|
66 |
+
|
67 |
+
// Add default translations
|
68 |
+
foreach ($legend_item_data['translations'] as $language_code => $legend_translation) {
|
69 |
+
wpsbc_add_legend_item_meta($legend_id, 'translation_' . $language_code, $legend_translation);
|
70 |
+
}
|
71 |
+
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Add legend items from another calendar
|
76 |
+
*
|
77 |
+
*/
|
78 |
+
if (!empty($_POST['calendar_legend'])) {
|
79 |
+
|
80 |
+
$copy_calendar_id = absint($_POST['calendar_legend']);
|
81 |
+
$copy_calendar_legend_items = wpsbc_get_legend_items(array('calendar_id' => $copy_calendar_id));
|
82 |
+
|
83 |
+
if (!empty($copy_calendar_legend_items)) {
|
84 |
+
|
85 |
+
foreach ($copy_calendar_legend_items as $legend_item) {
|
86 |
+
|
87 |
+
// Prepare data
|
88 |
+
$copy_legend_item_data = $legend_item->to_array();
|
89 |
+
$copy_legend_item_data['calendar_id'] = $calendar_id;
|
90 |
+
|
91 |
+
// Unset the legend item id from the array
|
92 |
+
unset($copy_legend_item_data['id']);
|
93 |
+
|
94 |
+
$copy_legend_item_id = $legend_item->get('id');
|
95 |
+
|
96 |
+
// Insert the new legend item
|
97 |
+
$legend_item_id = wpsbc_insert_legend_item($copy_legend_item_data);
|
98 |
+
|
99 |
+
if (!$legend_item_id) {
|
100 |
+
continue;
|
101 |
+
}
|
102 |
+
|
103 |
+
// Get all meta from the copy calendar legend items
|
104 |
+
$copy_legend_item_meta = wpsbc_get_legend_item_meta($copy_legend_item_id);
|
105 |
+
|
106 |
+
if (empty($copy_legend_item_meta)) {
|
107 |
+
continue;
|
108 |
+
}
|
109 |
+
|
110 |
+
foreach ($copy_legend_item_meta as $meta_key => $meta_values) {
|
111 |
+
|
112 |
+
foreach ($meta_values as $meta_value) {
|
113 |
+
wpsbc_add_legend_item_meta($legend_item_id, $meta_key, $meta_value);
|
114 |
+
}
|
115 |
+
|
116 |
+
}
|
117 |
+
|
118 |
+
}
|
119 |
+
|
120 |
+
}
|
121 |
+
|
122 |
+
}
|
123 |
+
|
124 |
+
// Redirect to the edit page of the calendar with a success message
|
125 |
+
wp_redirect(add_query_arg(array('page' => 'wpsbc-calendars', 'subpage' => 'edit-calendar', 'calendar_id' => $calendar_id, 'wpsbc_message' => 'calendar_insert_success'), admin_url('admin.php')));
|
126 |
+
exit;
|
127 |
+
|
128 |
+
}
|
129 |
+
add_action('wpsbc_action_add_calendar', 'wpsbc_action_add_calendar', 50);
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Handles the trash calendar action, which changes the status of the calendar from active to trash
|
133 |
+
*
|
134 |
+
*/
|
135 |
+
function wpsbc_action_trash_calendar()
|
136 |
+
{
|
137 |
+
|
138 |
+
// Verify for nonce
|
139 |
+
if (empty($_GET['wpsbc_token']) || !wp_verify_nonce($_GET['wpsbc_token'], 'wpsbc_trash_calendar')) {
|
140 |
+
return;
|
141 |
+
}
|
142 |
+
|
143 |
+
if (empty($_GET['calendar_id'])) {
|
144 |
+
return;
|
145 |
+
}
|
146 |
+
|
147 |
+
$calendar_id = absint($_GET['calendar_id']);
|
148 |
+
|
149 |
+
$calendar_data = array(
|
150 |
+
'status' => 'trash',
|
151 |
+
);
|
152 |
+
|
153 |
+
$updated = wpsbc_update_calendar($calendar_id, $calendar_data);
|
154 |
+
|
155 |
+
if (!$updated) {
|
156 |
+
return;
|
157 |
+
}
|
158 |
+
|
159 |
+
// Redirect to the current page
|
160 |
+
wp_redirect(add_query_arg(array('page' => 'wpsbc-calendars', 'calendar_status' => 'active', 'wpsbc_message' => 'calendar_trash_success'), admin_url('admin.php')));
|
161 |
+
exit;
|
162 |
+
|
163 |
+
}
|
164 |
+
add_action('wpsbc_action_trash_calendar', 'wpsbc_action_trash_calendar', 50);
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Handles the restore calendar action, which changes the status of the calendar from trash to active
|
168 |
+
*
|
169 |
+
*/
|
170 |
+
function wpsbc_action_restore_calendar()
|
171 |
+
{
|
172 |
+
|
173 |
+
// Verify for nonce
|
174 |
+
if (empty($_GET['wpsbc_token']) || !wp_verify_nonce($_GET['wpsbc_token'], 'wpsbc_restore_calendar')) {
|
175 |
+
return;
|
176 |
+
}
|
177 |
+
|
178 |
+
if (empty($_GET['calendar_id'])) {
|
179 |
+
return;
|
180 |
+
}
|
181 |
+
|
182 |
+
$calendar_id = absint($_GET['calendar_id']);
|
183 |
+
|
184 |
+
$calendar_data = array(
|
185 |
+
'status' => 'active',
|
186 |
+
);
|
187 |
+
|
188 |
+
$updated = wpsbc_update_calendar($calendar_id, $calendar_data);
|
189 |
+
|
190 |
+
if (!$updated) {
|
191 |
+
return;
|
192 |
+
}
|
193 |
+
|
194 |
+
// Redirect to the current page
|
195 |
+
wp_redirect(add_query_arg(array('page' => 'wpsbc-calendars', 'calendar_status' => 'trash', 'wpsbc_message' => 'calendar_restore_success'), admin_url('admin.php')));
|
196 |
+
exit;
|
197 |
+
|
198 |
+
}
|
199 |
+
add_action('wpsbc_action_restore_calendar', 'wpsbc_action_restore_calendar', 50);
|
200 |
+
|
201 |
+
/**
|
202 |
+
* Handles the delete calendar action, which removes all calendar data, legend items and events data
|
203 |
+
* associated with the calendar
|
204 |
+
*
|
205 |
+
*/
|
206 |
+
function wpsbc_action_delete_calendar()
|
207 |
+
{
|
208 |
+
|
209 |
+
// Verify for nonce
|
210 |
+
if (empty($_GET['wpsbc_token']) || !wp_verify_nonce($_GET['wpsbc_token'], 'wpsbc_delete_calendar')) {
|
211 |
+
return;
|
212 |
+
}
|
213 |
+
|
214 |
+
if (empty($_GET['calendar_id'])) {
|
215 |
+
return;
|
216 |
+
}
|
217 |
+
|
218 |
+
$calendar_id = absint($_GET['calendar_id']);
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Delete the calendar
|
222 |
+
*
|
223 |
+
*/
|
224 |
+
$deleted = wpsbc_delete_calendar($calendar_id);
|
225 |
+
|
226 |
+
if (!$deleted) {
|
227 |
+
return;
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Delete legend items
|
232 |
+
*
|
233 |
+
*/
|
234 |
+
$legend_items = wpsbc_get_legend_items(array('calendar_id' => $calendar_id));
|
235 |
+
|
236 |
+
foreach ($legend_items as $legend_item) {
|
237 |
+
|
238 |
+
wpsbc_delete_legend_item($legend_item->get('id'));
|
239 |
+
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Delete legend items meta
|
244 |
+
*
|
245 |
+
*/
|
246 |
+
foreach ($legend_items as $legend_item) {
|
247 |
+
|
248 |
+
$legend_item_meta = wpsbc_get_legend_item_meta($legend_item->get('id'));
|
249 |
+
|
250 |
+
if (!empty($legend_item_meta)) {
|
251 |
+
|
252 |
+
foreach ($legend_item_meta as $key => $value) {
|
253 |
+
|
254 |
+
wpsbc_delete_legend_item_meta($legend_item->get('id'), $key);
|
255 |
+
|
256 |
+
}
|
257 |
+
|
258 |
+
}
|
259 |
+
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Delete events
|
264 |
+
*
|
265 |
+
*/
|
266 |
+
$events = wpsbc_get_events(array('calendar_id' => $calendar_id));
|
267 |
+
|
268 |
+
foreach ($events as $event) {
|
269 |
+
|
270 |
+
wpsbc_delete_event($event->get('id'));
|
271 |
+
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Delete events meta
|
276 |
+
*
|
277 |
+
*/
|
278 |
+
foreach ($events as $event) {
|
279 |
+
|
280 |
+
$event_meta = wpsbc_get_legend_item_meta($event->get('id'));
|
281 |
+
|
282 |
+
if (!empty($event_meta)) {
|
283 |
+
|
284 |
+
foreach ($event_meta as $key => $value) {
|
285 |
+
|
286 |
+
wpsbc_delete_event_meta($event->get('id'), $key);
|
287 |
+
|
288 |
+
}
|
289 |
+
|
290 |
+
}
|
291 |
+
|
292 |
+
}
|
293 |
+
|
294 |
+
// Redirect to the current page
|
295 |
+
wp_redirect(add_query_arg(array('page' => 'wpsbc-calendars', 'calendar_status' => 'trash', 'wpsbc_message' => 'calendar_delete_success'), admin_url('admin.php')));
|
296 |
+
exit;
|
297 |
+
|
298 |
+
}
|
299 |
+
add_action('wpsbc_action_delete_calendar', 'wpsbc_action_delete_calendar', 50);
|
includes/base/admin/calendar/functions-actions-legend-item.php
ADDED
@@ -0,0 +1,396 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Handles "add new legend item" action
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
function wpsbc_action_add_legend_item() {
|
11 |
+
|
12 |
+
// Verify for nonce
|
13 |
+
if( empty( $_POST['wpsbc_token'] ) || ! wp_verify_nonce( $_POST['wpsbc_token'], 'wpsbc_add_legend_item' ) )
|
14 |
+
return;
|
15 |
+
|
16 |
+
// Verify for the calendar id
|
17 |
+
if( empty( $_GET['calendar_id'] ) ) {
|
18 |
+
|
19 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_calendar_id_missing', '<p>' . __( 'Something went wrong. Could not add the legend item.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
20 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_calendar_id_missing' );
|
21 |
+
|
22 |
+
return;
|
23 |
+
|
24 |
+
}
|
25 |
+
|
26 |
+
// Verify for legend item name
|
27 |
+
if( empty( $_POST['legend_item_name'] ) ) {
|
28 |
+
|
29 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_name_missing', '<p>' . __( 'Please add a name for your legend item.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
30 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_name_missing' );
|
31 |
+
|
32 |
+
return;
|
33 |
+
|
34 |
+
}
|
35 |
+
|
36 |
+
// Verify for legend item type
|
37 |
+
if( empty( $_POST['legend_item_type'] ) ) {
|
38 |
+
|
39 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_type_missing', '<p>' . __( 'Please select a type for your legend item.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
40 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_type_missing' );
|
41 |
+
|
42 |
+
return;
|
43 |
+
|
44 |
+
}
|
45 |
+
|
46 |
+
// Remove empty values from the colors array
|
47 |
+
if( isset( $_POST['legend_item_color'] ) && is_array( $_POST['legend_item_color'] ) )
|
48 |
+
$_POST['legend_item_color'] = array_filter( $_POST['legend_item_color'] );
|
49 |
+
|
50 |
+
// Verify for legend item type
|
51 |
+
if( empty( $_POST['legend_item_color'] ) || ( $_POST['legend_item_type'] != 'single' && count( $_POST['legend_item_color'] ) <= 1 ) ) {
|
52 |
+
|
53 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_color_missing', '<p>' . __( 'Please select the color for your legend item.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
54 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_color_missing' );
|
55 |
+
|
56 |
+
return;
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
// Get legend items to see if there are any added, if not we set this one to be the default one
|
61 |
+
$legend_items = wpsbc_get_legend_items( array( 'calendar_id' => absint( $_GET['calendar_id'] ), 'number' => 1 ) );
|
62 |
+
|
63 |
+
// Prepare legend item data to be inserted into the database
|
64 |
+
$legend_item_data = array(
|
65 |
+
'name' => sanitize_text_field( $_POST['legend_item_name'] ),
|
66 |
+
'type' => sanitize_text_field( $_POST['legend_item_type'] ),
|
67 |
+
'color' => $_POST['legend_item_color'],
|
68 |
+
'color_text' => ( ! empty( $_POST['legend_item_color_text'] ) ? sanitize_text_field( $_POST['legend_item_color_text'] ) : '' ),
|
69 |
+
'is_visible' => 1,
|
70 |
+
'is_default' => ( empty( $legend_items ) ? 1 : 0 ),
|
71 |
+
'calendar_id' => absint( $_GET['calendar_id'] )
|
72 |
+
);
|
73 |
+
|
74 |
+
|
75 |
+
// Insert the legend item
|
76 |
+
$inserted = wpsbc_insert_legend_item( $legend_item_data );
|
77 |
+
|
78 |
+
// If the legend item could not be inserted show a message to the user
|
79 |
+
if( ! $inserted ) {
|
80 |
+
|
81 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_insert_fail', '<p>' . __( 'Something went wrong. Could not add the legend item. Please try again.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
82 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_insert_fail' );
|
83 |
+
|
84 |
+
return;
|
85 |
+
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Handle translations
|
90 |
+
*
|
91 |
+
*/
|
92 |
+
$settings = get_option( 'wpsbc_settings', array() );
|
93 |
+
$active_languages = ( ! empty( $settings['active_languages'] ) ? $settings['active_languages'] : array() );
|
94 |
+
|
95 |
+
foreach( $active_languages as $code ) {
|
96 |
+
|
97 |
+
// Add translation
|
98 |
+
if( ! empty( $_POST['legend_item_translation_' . $code] ) )
|
99 |
+
wpsbc_add_legend_item_meta( $inserted, 'translation_' . $code, sanitize_text_field( $_POST['legend_item_translation_' . $code] ) );
|
100 |
+
|
101 |
+
}
|
102 |
+
|
103 |
+
// Redirect to the edit page of the calendar with a success message
|
104 |
+
wp_redirect( add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'view-legend', 'calendar_id' => absint( $_GET['calendar_id'] ), 'wpsbc_message' => 'legend_item_insert_success' ), admin_url( 'admin.php' ) ) );
|
105 |
+
exit;
|
106 |
+
|
107 |
+
}
|
108 |
+
add_action( 'wpsbc_action_add_legend_item', 'wpsbc_action_add_legend_item' );
|
109 |
+
|
110 |
+
|
111 |
+
/**
|
112 |
+
* Handles "add new legend item" action
|
113 |
+
*
|
114 |
+
*/
|
115 |
+
function wpsbc_action_edit_legend_item() {
|
116 |
+
|
117 |
+
// Verify for nonce
|
118 |
+
if( empty( $_POST['wpsbc_token'] ) || ! wp_verify_nonce( $_POST['wpsbc_token'], 'wpsbc_edit_legend_item' ) )
|
119 |
+
return;
|
120 |
+
|
121 |
+
// Verify for legend item name
|
122 |
+
if( empty( $_POST['legend_item_name'] ) ) {
|
123 |
+
|
124 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_name_missing', '<p>' . __( 'Please add a name for your legend item.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
125 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_name_missing' );
|
126 |
+
|
127 |
+
return;
|
128 |
+
|
129 |
+
}
|
130 |
+
|
131 |
+
// Verify for legend item type
|
132 |
+
if( empty( $_POST['legend_item_type'] ) ) {
|
133 |
+
|
134 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_type_missing', '<p>' . __( 'Please select a type for your legend item.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
135 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_type_missing' );
|
136 |
+
|
137 |
+
return;
|
138 |
+
|
139 |
+
}
|
140 |
+
|
141 |
+
// Remove empty values from the colors array
|
142 |
+
if( isset( $_POST['legend_item_color'] ) && is_array( $_POST['legend_item_color'] ) )
|
143 |
+
$_POST['legend_item_color'] = array_filter( $_POST['legend_item_color'] );
|
144 |
+
|
145 |
+
// Verify for legend item type
|
146 |
+
if( empty( $_POST['legend_item_color'] ) || ( $_POST['legend_item_type'] != 'single' && count( $_POST['legend_item_color'] ) <= 1 ) ) {
|
147 |
+
|
148 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_color_missing', '<p>' . __( 'Please select the color for your legend item.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
149 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_color_missing' );
|
150 |
+
|
151 |
+
return;
|
152 |
+
|
153 |
+
}
|
154 |
+
|
155 |
+
// Prepare legend item data to be inserted into the database
|
156 |
+
$legend_item_data = array(
|
157 |
+
'name' => sanitize_text_field( $_POST['legend_item_name'] ),
|
158 |
+
'type' => sanitize_text_field( $_POST['legend_item_type'] ),
|
159 |
+
'color' => $_POST['legend_item_color'],
|
160 |
+
'color_text' => ( ! empty( $_POST['legend_item_color_text'] ) ? sanitize_text_field( $_POST['legend_item_color_text'] ) : '' ),
|
161 |
+
);
|
162 |
+
|
163 |
+
// Insert the legend item
|
164 |
+
$updated = wpsbc_update_legend_item( absint( $_GET['legend_item_id'] ), $legend_item_data );
|
165 |
+
|
166 |
+
// If the legend item could not be updated show a message to the user
|
167 |
+
if( ! $updated ) {
|
168 |
+
|
169 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_update_fail', '<p>' . __( 'Something went wrong. Could not updated the legend item. Please try again.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
170 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_update_fail' );
|
171 |
+
|
172 |
+
return;
|
173 |
+
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Handle translations
|
178 |
+
*
|
179 |
+
*/
|
180 |
+
$settings = get_option( 'wpsbc_settings', array() );
|
181 |
+
$active_languages = ( ! empty( $settings['active_languages'] ) ? $settings['active_languages'] : array() );
|
182 |
+
|
183 |
+
foreach( $active_languages as $code ) {
|
184 |
+
|
185 |
+
// Firstly remove the translation
|
186 |
+
wpsbc_delete_legend_item_meta( absint( $_GET['legend_item_id'] ), 'translation_' . $code );
|
187 |
+
|
188 |
+
// Add translation
|
189 |
+
if( ! empty( $_POST['legend_item_translation_' . $code] ) )
|
190 |
+
wpsbc_add_legend_item_meta( absint( $_GET['legend_item_id'] ), 'translation_' . $code, sanitize_text_field( $_POST['legend_item_translation_' . $code] ) );
|
191 |
+
|
192 |
+
}
|
193 |
+
|
194 |
+
// Redirect to the edit page of the calendar with a success message
|
195 |
+
wp_redirect( add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'edit-legend-item', 'legend_item_id' => absint( $_GET['legend_item_id'] ), 'calendar_id' => absint( $_GET['calendar_id'] ), 'wpsbc_message' => 'legend_item_update_success' ), admin_url( 'admin.php' ) ) );
|
196 |
+
exit;
|
197 |
+
|
198 |
+
}
|
199 |
+
add_action( 'wpsbc_action_edit_legend_item', 'wpsbc_action_edit_legend_item' );
|
200 |
+
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Handles the "delete legend item" action
|
204 |
+
*
|
205 |
+
*/
|
206 |
+
function wpsbc_action_delete_legend_item() {
|
207 |
+
|
208 |
+
// Verify for nonce
|
209 |
+
if( empty( $_GET['wpsbc_token'] ) || ! wp_verify_nonce( $_GET['wpsbc_token'], 'wpsbc_delete_legend_item' ) )
|
210 |
+
return;
|
211 |
+
|
212 |
+
// Verify for legend item id
|
213 |
+
if( empty( $_GET['legend_item_id'] ) ) {
|
214 |
+
|
215 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_id_missing', '<p>' . __( 'Something went wrong. Could not delete the legend item. Please try again.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
216 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_id_missing' );
|
217 |
+
|
218 |
+
return;
|
219 |
+
|
220 |
+
}
|
221 |
+
|
222 |
+
// Set legend item id
|
223 |
+
$legend_item_id = absint( $_GET['legend_item_id'] );
|
224 |
+
|
225 |
+
// Get legend item to see if it exists
|
226 |
+
$legend_item = wpsbc_get_legend_item( $legend_item_id );
|
227 |
+
|
228 |
+
if( is_null( $legend_item ) ) {
|
229 |
+
|
230 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_is_null', '<p>' . __( 'Something went wrong. Could not delete the legend item. Please try again.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
231 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_is_null' );
|
232 |
+
|
233 |
+
return;
|
234 |
+
|
235 |
+
}
|
236 |
+
|
237 |
+
// Set calendar_id
|
238 |
+
$calendar_id = $legend_item->get('calendar_id');
|
239 |
+
|
240 |
+
// Delete the legend item
|
241 |
+
$deleted = wpsbc_delete_legend_item( $legend_item_id );
|
242 |
+
|
243 |
+
if( ! $deleted ) {
|
244 |
+
|
245 |
+
wpsbc_admin_notices()->register_notice( 'legend_item_delete_fail', '<p>' . __( 'Something went wrong. Could not delete the legend item. Please try again.', 'wp-simple-booking-calendar' ) . '</p>', 'error' );
|
246 |
+
wpsbc_admin_notices()->display_notice( 'legend_item_delete_fail' );
|
247 |
+
|
248 |
+
return;
|
249 |
+
|
250 |
+
}
|
251 |
+
|
252 |
+
// Delete the legend item meta data
|
253 |
+
$legend_item_meta = wpsbc_get_legend_item_meta( $legend_item_id );
|
254 |
+
|
255 |
+
if( ! empty( $legend_item_meta ) ) {
|
256 |
+
|
257 |
+
foreach( $legend_item_meta as $meta_key => $meta_value )
|
258 |
+
wpsbc_delete_legend_item_meta( $legend_item_id, $meta_key );
|
259 |
+
|
260 |
+
}
|
261 |
+
|
262 |
+
// Redirect to the view legend page with a success message
|
263 |
+
wp_redirect( add_query_arg( array( 'wpsbc_message' => 'legend_item_delete_success', 'calendar_id' => $calendar_id ), remove_query_arg( array( 'wpsbc_action', 'wpsbc_token' ) ) ) );
|
264 |
+
exit;
|
265 |
+
|
266 |
+
}
|
267 |
+
add_action( 'wpsbc_action_delete_legend_item', 'wpsbc_action_delete_legend_item' );
|
268 |
+
|
269 |
+
|
270 |
+
/**
|
271 |
+
* Handles the "make legend item default" action
|
272 |
+
*
|
273 |
+
*/
|
274 |
+
function wpsbc_action_make_default_legend_item() {
|
275 |
+
|
276 |
+
// Verify for nonce
|
277 |
+
if( empty( $_GET['wpsbc_token'] ) || ! wp_verify_nonce( $_GET['wpsbc_token'], 'wpsbc_make_default_legend_item' ) )
|
278 |
+
return;
|
279 |
+
|
280 |
+
if( empty( $_GET['legend_item_id'] ) )
|
281 |
+
return;
|
282 |
+
|
283 |
+
$legend_item = wpsbc_get_legend_item( absint( $_GET['legend_item_id'] ) );
|
284 |
+
|
285 |
+
if( is_null( $legend_item ) )
|
286 |
+
return;
|
287 |
+
|
288 |
+
// Get default legend item
|
289 |
+
$default_legend_item = wpsbc_get_legend_items( array( 'calendar_id' => $legend_item->get('calendar_id'), 'is_default' => 1 ) );
|
290 |
+
$default_legend_item = ( ! empty( $default_legend_item ) && is_array( $default_legend_item ) ? $default_legend_item[0] : null );
|
291 |
+
|
292 |
+
// Update the default legend item to not be the default one
|
293 |
+
if( ! is_null( $default_legend_item ) ) {
|
294 |
+
|
295 |
+
$legend_item_data = array(
|
296 |
+
'is_default' => 0
|
297 |
+
);
|
298 |
+
|
299 |
+
$updated = wpsbc_update_legend_item( $default_legend_item->get('id'), $legend_item_data );
|
300 |
+
|
301 |
+
} else
|
302 |
+
$updated = true;
|
303 |
+
|
304 |
+
if( ! $updated )
|
305 |
+
return;
|
306 |
+
|
307 |
+
// Update the current legend item to be the default one
|
308 |
+
$legend_item_data = array(
|
309 |
+
'is_default' => 1
|
310 |
+
);
|
311 |
+
|
312 |
+
$updated = wpsbc_update_legend_item( $legend_item->get('id'), $legend_item_data );
|
313 |
+
|
314 |
+
if( ! $updated )
|
315 |
+
return;
|
316 |
+
|
317 |
+
// Redirect to the edit page of the legend with a success message
|
318 |
+
wp_redirect( add_query_arg( array( 'wpsbc_message' => 'legend_item_make_default_success' ), remove_query_arg( array( 'wpsbc_action', 'wpsbc_token' ) ) ) );
|
319 |
+
exit;
|
320 |
+
|
321 |
+
}
|
322 |
+
add_action( 'wpsbc_action_make_default_legend_item', 'wpsbc_action_make_default_legend_item' );
|
323 |
+
|
324 |
+
|
325 |
+
/**
|
326 |
+
* Handles the "make legend item invisible" action
|
327 |
+
*
|
328 |
+
*/
|
329 |
+
function wpsbc_action_make_visible_legend_item() {
|
330 |
+
|
331 |
+
// Verify for nonce
|
332 |
+
if( empty( $_GET['wpsbc_token'] ) || ! wp_verify_nonce( $_GET['wpsbc_token'], 'wpsbc_make_visible_legend_item' ) )
|
333 |
+
return;
|
334 |
+
|
335 |
+
if( empty( $_GET['legend_item_id'] ) )
|
336 |
+
return;
|
337 |
+
|
338 |
+
$legend_item = wpsbc_get_legend_item( absint( $_GET['legend_item_id'] ) );
|
339 |
+
|
340 |
+
if( is_null( $legend_item ) )
|
341 |
+
return;
|
342 |
+
|
343 |
+
// Prepare legend item data to be updated
|
344 |
+
$legend_item_data = array(
|
345 |
+
'is_visible' => 1
|
346 |
+
);
|
347 |
+
|
348 |
+
// Update legend item in the database
|
349 |
+
$updated = wpsbc_update_legend_item( $legend_item->get('id'), $legend_item_data );
|
350 |
+
|
351 |
+
if( ! $updated )
|
352 |
+
return;
|
353 |
+
|
354 |
+
// Redirect to the edit page of the legend with a success message
|
355 |
+
wp_redirect( add_query_arg( array( 'wpsbc_message' => 'legend_item_make_visible_success' ), remove_query_arg( array( 'wpsbc_action', 'wpsbc_token' ) ) ) );
|
356 |
+
exit;
|
357 |
+
|
358 |
+
}
|
359 |
+
add_action( 'wpsbc_action_make_visible_legend_item', 'wpsbc_action_make_visible_legend_item', 50 );
|
360 |
+
|
361 |
+
|
362 |
+
/**
|
363 |
+
* Handles the "make legend item invisible" action
|
364 |
+
*
|
365 |
+
*/
|
366 |
+
function wpsbc_action_make_invisible_legend_item() {
|
367 |
+
|
368 |
+
// Verify for nonce
|
369 |
+
if( empty( $_GET['wpsbc_token'] ) || ! wp_verify_nonce( $_GET['wpsbc_token'], 'wpsbc_make_invisible_legend_item' ) )
|
370 |
+
return;
|
371 |
+
|
372 |
+
if( empty( $_GET['legend_item_id'] ) )
|
373 |
+
return;
|
374 |
+
|
375 |
+
$legend_item = wpsbc_get_legend_item( absint( $_GET['legend_item_id'] ) );
|
376 |
+
|
377 |
+
if( is_null( $legend_item ) )
|
378 |
+
return;
|
379 |
+
|
380 |
+
// Prepare legend item data to be updated
|
381 |
+
$legend_item_data = array(
|
382 |
+
'is_visible' => 0
|
383 |
+
);
|
384 |
+
|
385 |
+
// Update legend item in the database
|
386 |
+
$updated = wpsbc_update_legend_item( $legend_item->get('id'), $legend_item_data );
|
387 |
+
|
388 |
+
if( ! $updated )
|
389 |
+
return;
|
390 |
+
|
391 |
+
// Redirect to the edit page of the legend with a success message
|
392 |
+
wp_redirect( add_query_arg( array( 'wpsbc_message' => 'legend_item_make_invisible_success' ), remove_query_arg( array( 'wpsbc_action', 'wpsbc_token' ) ) ) );
|
393 |
+
exit;
|
394 |
+
|
395 |
+
}
|
396 |
+
add_action( 'wpsbc_action_make_invisible_legend_item', 'wpsbc_action_make_invisible_legend_item', 50 );
|
includes/base/admin/calendar/functions-shortcode-generator.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Adds the "Add Calendar" button to the text editor
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
function wpsbc_add_calendar_shortcode_media_button() {
|
11 |
+
|
12 |
+
if( ! function_exists( 'get_current_screen' ) )
|
13 |
+
return;
|
14 |
+
|
15 |
+
$screen = get_current_screen();
|
16 |
+
|
17 |
+
if( is_null( $screen ) )
|
18 |
+
return;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Filter the post types where the shortcode media button should appear
|
22 |
+
*
|
23 |
+
* @param array
|
24 |
+
*
|
25 |
+
*/
|
26 |
+
$post_types = get_post_types(array('public' => true));
|
27 |
+
|
28 |
+
$post_types = apply_filters( 'wpsbc_add_calendar_shortcode_media_button_post_types', $post_types );
|
29 |
+
|
30 |
+
if( ! in_array( $screen->post_type, $post_types ) )
|
31 |
+
return;
|
32 |
+
|
33 |
+
echo '<a href="#" id="wpsbc-shortcode-generator-button" class="button"><span class="dashicons dashicons-calendar-alt"></span>' . __( 'Add Calendar', 'wp-simple-booking-calendar' ) . '</a>';
|
34 |
+
|
35 |
+
}
|
36 |
+
add_action( 'media_buttons', 'wpsbc_add_calendar_shortcode_media_button', 20 );
|
37 |
+
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Adds the modal window triggered by the "Add Calendar" button
|
41 |
+
*
|
42 |
+
*/
|
43 |
+
function wpsbc_add_calendar_shortcode_modal() {
|
44 |
+
|
45 |
+
if( ! function_exists( 'get_current_screen' ) )
|
46 |
+
return;
|
47 |
+
|
48 |
+
$screen = get_current_screen();
|
49 |
+
|
50 |
+
if( is_null( $screen ) )
|
51 |
+
return;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Filter the post types where the shortcode modal generated by the shortcode media button should appear
|
55 |
+
*
|
56 |
+
* @param array
|
57 |
+
*
|
58 |
+
*/
|
59 |
+
$post_types = get_post_types(array('public' => true));
|
60 |
+
|
61 |
+
$post_types = apply_filters( 'wpsbc_add_calendar_shortcode_media_button_post_types', $post_types );
|
62 |
+
|
63 |
+
if( ! in_array( $screen->post_type, $post_types ) )
|
64 |
+
return;
|
65 |
+
|
66 |
+
include 'views/view-shortcode-generator.php';
|
67 |
+
|
68 |
+
}
|
69 |
+
add_action( 'admin_footer', 'wpsbc_add_calendar_shortcode_modal' );
|
includes/base/admin/calendar/functions.php
ADDED
@@ -0,0 +1,105 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Includes the files needed for the Legend Items admin area
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_include_files_admin_calendar() {
|
12 |
+
|
13 |
+
// Get legend admin dir path
|
14 |
+
$dir_path = plugin_dir_path( __FILE__ );
|
15 |
+
|
16 |
+
// Include submenu page
|
17 |
+
if( file_exists( $dir_path . 'class-submenu-page-calendar.php' ) )
|
18 |
+
include $dir_path . 'class-submenu-page-calendar.php';
|
19 |
+
|
20 |
+
// Include calendars list table
|
21 |
+
if( file_exists( $dir_path . 'class-list-table-calendars.php' ) )
|
22 |
+
include $dir_path . 'class-list-table-calendars.php';
|
23 |
+
|
24 |
+
// Include calendar editor outputter
|
25 |
+
if( file_exists( $dir_path . 'class-calendar-editor-outputter.php' ) )
|
26 |
+
include $dir_path . 'class-calendar-editor-outputter.php';
|
27 |
+
|
28 |
+
// Include admin actions
|
29 |
+
if( file_exists( $dir_path . 'functions-actions-ical.php' ) )
|
30 |
+
include $dir_path . 'functions-actions-ical.php';
|
31 |
+
|
32 |
+
if( file_exists( $dir_path . 'functions-actions-calendar.php' ) )
|
33 |
+
include $dir_path . 'functions-actions-calendar.php';
|
34 |
+
|
35 |
+
if( file_exists( $dir_path . 'functions-actions-legend-item.php' ) )
|
36 |
+
include $dir_path . 'functions-actions-legend-item.php';
|
37 |
+
|
38 |
+
if( file_exists( $dir_path . 'functions-actions-ajax-calendar.php' ) )
|
39 |
+
include $dir_path . 'functions-actions-ajax-calendar.php';
|
40 |
+
|
41 |
+
if( file_exists( $dir_path . 'functions-actions-ajax-legend-item.php' ) )
|
42 |
+
include $dir_path . 'functions-actions-ajax-legend-item.php';
|
43 |
+
|
44 |
+
if( file_exists( $dir_path . 'functions-shortcode-generator.php' ) )
|
45 |
+
include $dir_path . 'functions-shortcode-generator.php';
|
46 |
+
|
47 |
+
}
|
48 |
+
add_action( 'wpsbc_include_files', 'wpsbc_include_files_admin_calendar' );
|
49 |
+
|
50 |
+
|
51 |
+
/**
|
52 |
+
* Register the Calendars admin submenu page
|
53 |
+
*
|
54 |
+
*/
|
55 |
+
function wpsbc_register_submenu_page_calendars( $submenu_pages ) {
|
56 |
+
|
57 |
+
if( ! is_array( $submenu_pages ) )
|
58 |
+
return $submenu_pages;
|
59 |
+
|
60 |
+
$submenu_pages['calendars'] = array(
|
61 |
+
'class_name' => 'WPSBC_Submenu_Page_Calendars',
|
62 |
+
'data' => array(
|
63 |
+
'page_title' => __( 'Calendars', 'wp-simple-booking-calendar' ),
|
64 |
+
'menu_title' => __( 'Calendars', 'wp-simple-booking-calendar' ),
|
65 |
+
'capability' => apply_filters( 'wpsbc_submenu_page_capability_calendars', 'manage_options' ),
|
66 |
+
'menu_slug' => 'wpsbc-calendars'
|
67 |
+
)
|
68 |
+
);
|
69 |
+
|
70 |
+
return $submenu_pages;
|
71 |
+
|
72 |
+
}
|
73 |
+
add_filter( 'wpsbc_register_submenu_page', 'wpsbc_register_submenu_page_calendars', 20 );
|
74 |
+
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Returns the HTML for the legend item icon
|
78 |
+
*
|
79 |
+
* @param int $legend_item_id
|
80 |
+
* @param string $type
|
81 |
+
* @param array $color
|
82 |
+
*
|
83 |
+
* @return string
|
84 |
+
*
|
85 |
+
*/
|
86 |
+
function wpsbc_get_legend_item_icon( $legend_item_id, $type, $color = array() ) {
|
87 |
+
|
88 |
+
$output = '<div class="wpsbc-legend-item-icon wpsbc-legend-item-icon-' . esc_attr( $legend_item_id ) . '" data-type="' . esc_attr( $type ) . '">';
|
89 |
+
|
90 |
+
for( $i = 0; $i <= 1; $i++ ){
|
91 |
+
|
92 |
+
$svg = '';
|
93 |
+
if($type == "split"){
|
94 |
+
$svg = ($i == 0) ? '<svg height="100%" width="100%" viewBox="0 0 50 50" preserveAspectRatio="none"><polygon points="0,0 0,50 50,0" /></svg>' : '<svg height="100%" width="100%" viewBox="0 0 50 50" preserveAspectRatio="none"><polygon points="0,50 50,50 50,0" /></svg>';
|
95 |
+
}
|
96 |
+
|
97 |
+
|
98 |
+
$output .= '<div class="wpsbc-legend-item-icon-color" ' . ( ! empty( $color[$i] ) ? 'style="background-color: ' . esc_attr( $color[$i] ) . ';"' : '' ) . '>' . $svg . '</div>';
|
99 |
+
}
|
100 |
+
|
101 |
+
$output .= '</div>';
|
102 |
+
|
103 |
+
return $output;
|
104 |
+
|
105 |
+
}
|
includes/base/admin/calendar/views/view-add-calendar.php
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
$calendars = wpsbc_get_calendars( array( 'status' => 'active' ) );
|
7 |
+
|
8 |
+
?>
|
9 |
+
|
10 |
+
<div class="wrap wpsbc-wrap wpsbc-wrap-add-calendar">
|
11 |
+
|
12 |
+
<form action="" method="POST">
|
13 |
+
|
14 |
+
<!-- Icon -->
|
15 |
+
<div id="wpsbc-add-new-calendar-icon">
|
16 |
+
<div class="wpsbc-icon-wrap">
|
17 |
+
<span class="dashicons dashicons-calendar-alt"></span>
|
18 |
+
<span class="dashicons dashicons-plus"></span>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<!-- Heading -->
|
23 |
+
<h1 id="wpsbc-add-new-calendar-heading"><?php echo __( 'Add New Calendar', 'wp-simple-booking-calendar' ); ?></h1>
|
24 |
+
|
25 |
+
<!-- Postbox -->
|
26 |
+
<div id="wpsbc-add-new-calendar-postbox" class="postbox">
|
27 |
+
|
28 |
+
<!-- Form Fields -->
|
29 |
+
<div class="inside">
|
30 |
+
|
31 |
+
<!-- Add Calendar Name -->
|
32 |
+
<label for="wpsbc-new-calendar-name"><?php echo __( 'Calendar Name', 'wp-simple-booking-calendar' ); ?> *</label>
|
33 |
+
<input id="wpsbc-new-calendar-name" name="calendar_name" type="text" value="<?php echo ( ! empty( $_POST['calendar_name'] ) ? esc_attr( $_POST['calendar_name'] ) : '' ); ?>" />
|
34 |
+
|
35 |
+
</div>
|
36 |
+
|
37 |
+
<!-- Form Submit button -->
|
38 |
+
<div id="major-publishing-actions">
|
39 |
+
<a href="<?php echo admin_url( $this->admin_url ); ?>"><?php echo __( 'Cancel', 'wp-simple-booking-calendar' ); ?></a>
|
40 |
+
<input type="submit" class="button-primary wpsbc-button-large" value="<?php echo __( 'Add Calendar', 'wp-simple-booking-calendar' ); ?>" />
|
41 |
+
</div>
|
42 |
+
|
43 |
+
<!-- Action and nonce -->
|
44 |
+
<input type="hidden" name="wpsbc_action" value="add_calendar" />
|
45 |
+
<?php wp_nonce_field( 'wpsbc_add_calendar', 'wpsbc_token', false ); ?>
|
46 |
+
|
47 |
+
</div>
|
48 |
+
|
49 |
+
</form>
|
50 |
+
|
51 |
+
</div>
|
includes/base/admin/calendar/views/view-calendars.php
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div class="wrap wpsbc-wrap wpsbc-wrap-calendars">
|
9 |
+
|
10 |
+
<!-- Page Heading -->
|
11 |
+
<h1 class="wp-heading-inline"><?php echo __( 'Calendars', 'wp-simple-booking-calendar' ); ?></h1>
|
12 |
+
<a href="<?php echo add_query_arg( array( 'subpage' => 'add-calendar' ), $this->admin_url ); ?>" class="page-title-action"><?php echo __( 'Add New Calendar', 'wp-simple-booking-calendar' ); ?></a>
|
13 |
+
<hr class="wp-header-end" />
|
14 |
+
|
15 |
+
<!-- Calendars List Table -->
|
16 |
+
<form method="get">
|
17 |
+
|
18 |
+
<input type="hidden" name="page" value="wpsbc-calendars" />
|
19 |
+
<input type="hidden" name="paged" value="1">
|
20 |
+
|
21 |
+
<?php
|
22 |
+
$table = new WPSBC_WP_List_Table_Calendars();
|
23 |
+
$table->views();
|
24 |
+
$table->search_box( __( 'Search Calendars' ), 'wpsbc-search-calendars' );
|
25 |
+
$table->display();
|
26 |
+
?>
|
27 |
+
</form>
|
28 |
+
|
29 |
+
<a href="<?php echo add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'upgrade-to-premium' ), $this->admin_url ); ?>" class="wpsbc-wrap-upgrade-cta">
|
30 |
+
<span class="wpsbc-wrap-upgrade-cta-button">I'm interested</span>
|
31 |
+
<span class="wpsbc-wrap-upgrade-cta-heading">Missing anything? Discover more powerful features in the premium version now!</span>
|
32 |
+
</a>
|
33 |
+
|
34 |
+
</div>
|
includes/base/admin/calendar/views/view-edit-calendar.php
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
$calendar_id = absint( ! empty( $_GET['calendar_id'] ) ? $_GET['calendar_id'] : 0 );
|
7 |
+
$calendar = wpsbc_get_calendar( $calendar_id );
|
8 |
+
|
9 |
+
if( is_null( $calendar ) )
|
10 |
+
return;
|
11 |
+
|
12 |
+
$current_year = ( ! empty( $_GET['year'] ) ? absint( $_GET['year'] ) : current_time('Y') );
|
13 |
+
$current_month = ( ! empty( $_GET['month'] ) ? absint( $_GET['month'] ) : current_time('n') );
|
14 |
+
|
15 |
+
$settings = get_option( 'wpsbc_settings', array() );
|
16 |
+
|
17 |
+
$removable_query_args = wp_removable_query_args();
|
18 |
+
|
19 |
+
?>
|
20 |
+
|
21 |
+
<div class="wrap wpsbc-wrap wpsbc-wrap-edit-calendar">
|
22 |
+
|
23 |
+
<form method="POST" action="" autocomplete="off">
|
24 |
+
|
25 |
+
<!-- Page Heading -->
|
26 |
+
<h1 class="wp-heading-inline"><?php echo __( 'Edit Calendar', 'wp-simple-booking-calendar' ); ?><span class="wpsbc-heading-tag"><?php printf( __( 'Calendar ID: %d', 'wp-simple-booking-calendar' ), $calendar_id ); ?></span></h1>
|
27 |
+
|
28 |
+
<!-- Page Heading Actions -->
|
29 |
+
<div class="wpsbc-heading-actions">
|
30 |
+
|
31 |
+
<!-- Back Button -->
|
32 |
+
<a href="<?php echo add_query_arg( array( 'page' => 'wpsbc-calendars'), admin_url( 'admin.php' ) ); ?>" class="button-secondary"><?php echo __('Back to all calendars', 'wp-simple-booking-calendar') ?></a>
|
33 |
+
|
34 |
+
<!-- Save button -->
|
35 |
+
<input type="submit" class="wpsbc-save-calendar button-primary" value="<?php echo __( 'Save Calendar', 'wp-simple-booking-calendar' ); ?>" />
|
36 |
+
|
37 |
+
</div>
|
38 |
+
|
39 |
+
<hr class="wp-header-end" />
|
40 |
+
|
41 |
+
<div id="poststuff">
|
42 |
+
|
43 |
+
<!-- Calendar Title -->
|
44 |
+
<div id="titlediv">
|
45 |
+
<div id="titlewrap">
|
46 |
+
<input type="text" name="calendar_name" size="30" value="<?php echo esc_attr( $calendar->get('name') ) ?>" id="title">
|
47 |
+
|
48 |
+
<?php if(isset($settings['active_languages']) && count($settings['active_languages']) > 0): ?>
|
49 |
+
|
50 |
+
<a href="#" class="titlewrap-toggle"><?php echo __('Translate calendar title','wp-simple-booking-calendar') ?> <svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512" ><path fill="currentColor" d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z" class=""></path></svg></a>
|
51 |
+
<div class="titlewrap-translations">
|
52 |
+
<?php foreach($settings['active_languages'] as $language): ?>
|
53 |
+
<div class="titlewrap-translation">
|
54 |
+
<div class="titlewrap-translation-flag"><img src="<?php echo WPSBC_PLUGIN_DIR_URL; ?>assets/img/flags/<?php echo $language;?>.png" /></div>
|
55 |
+
<input type="text" name="calendar_name_translation_<?php echo $language;?>" size="30" value="<?php echo esc_attr( wpsbc_get_calendar_meta($calendar->get('id'), 'calendar_name_translation_' . $language, true) ) ?>" >
|
56 |
+
</div>
|
57 |
+
<?php endforeach; ?>
|
58 |
+
</div>
|
59 |
+
|
60 |
+
<?php endif ?>
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
|
64 |
+
<div id="post-body" class="metabox-holder columns-2">
|
65 |
+
|
66 |
+
<!-- Main Post Body Content -->
|
67 |
+
<div id="post-body-content">
|
68 |
+
|
69 |
+
<!-- Availability -->
|
70 |
+
<div class="postbox">
|
71 |
+
|
72 |
+
<h3 class="hndle"><?php echo __( 'Edit Dates', 'wp-simple-booking-calendar' ); ?></h3>
|
73 |
+
|
74 |
+
<div class="inside">
|
75 |
+
|
76 |
+
<div id="wpsbc-calendar-events">
|
77 |
+
<?php
|
78 |
+
$calendar_args = array(
|
79 |
+
'current_year' => $current_year,
|
80 |
+
'current_month' => $current_month
|
81 |
+
);
|
82 |
+
|
83 |
+
$calendar_editor = new WPSBC_Calendar_Editor_Outputter( $calendar, $calendar_args );
|
84 |
+
$calendar_editor->display();
|
85 |
+
?>
|
86 |
+
</div>
|
87 |
+
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
|
91 |
+
<?php
|
92 |
+
|
93 |
+
/**
|
94 |
+
* Action hook to add extra form fields to the main calendar edit area
|
95 |
+
*
|
96 |
+
* @param WPSBC_Calendar $calendar
|
97 |
+
*
|
98 |
+
*/
|
99 |
+
do_action( 'wpsbc_view_edit_calendar_main', $calendar );
|
100 |
+
|
101 |
+
?>
|
102 |
+
|
103 |
+
</div><!-- / Main Post Body Content -->
|
104 |
+
|
105 |
+
<!-- Sidebar Content -->
|
106 |
+
<div id="postbox-container-1" class="postbox-container">
|
107 |
+
|
108 |
+
<!-- Calendar -->
|
109 |
+
<div class="postbox">
|
110 |
+
|
111 |
+
<h3 class="hndle"><?php echo __( 'Calendar', 'wp-simple-booking-calendar' ); ?></h3>
|
112 |
+
|
113 |
+
<div class="inside">
|
114 |
+
|
115 |
+
<?php
|
116 |
+
$calendar_args = array(
|
117 |
+
'current_year' => $current_year,
|
118 |
+
'current_month' => $current_month,
|
119 |
+
'show_title' => 0,
|
120 |
+
'show_legend' => 0
|
121 |
+
);
|
122 |
+
|
123 |
+
$calendar_outputter = new WPSBC_Calendar_Outputter( $calendar, $calendar_args );
|
124 |
+
$calendar_outputter->display();
|
125 |
+
?>
|
126 |
+
|
127 |
+
</div>
|
128 |
+
</div><!-- / Calendar -->
|
129 |
+
|
130 |
+
<!-- Calendar Legend -->
|
131 |
+
<div class="postbox">
|
132 |
+
|
133 |
+
<h3 class="hndle"><?php echo __( 'Legend', 'wp-simple-booking-calendar' ); ?></h3>
|
134 |
+
|
135 |
+
<div class="inside">
|
136 |
+
|
137 |
+
<?php
|
138 |
+
$legend_items = wpsbc_get_legend_items( array( 'calendar_id' => $calendar_id ) );
|
139 |
+
|
140 |
+
foreach( $legend_items as $legend_item ) {
|
141 |
+
|
142 |
+
echo '<div class="wpsbc-legend-item">';
|
143 |
+
echo wpsbc_get_legend_item_icon( $legend_item->get('id'), $legend_item->get('type'), $legend_item->get('color') );
|
144 |
+
echo '<span class="wpsbc-legend-item-name">' . $legend_item->get('name') . '</span>';
|
145 |
+
echo '</div>';
|
146 |
+
|
147 |
+
}
|
148 |
+
?>
|
149 |
+
|
150 |
+
</div>
|
151 |
+
|
152 |
+
<div class="wpsbc-plugin-card-bottom plugin-card-bottom">
|
153 |
+
<a class="button-secondary" href="<?php echo add_query_arg( array( 'subpage' => 'view-legend' ), remove_query_arg( $removable_query_args ) ); ?>"><?php echo __( 'Edit Legend Items', 'wp-simple-booking-calendar' ); ?></a>
|
154 |
+
</div>
|
155 |
+
|
156 |
+
</div><!-- / Calendar Legend -->
|
157 |
+
|
158 |
+
<!-- iCal Export -->
|
159 |
+
<div class="postbox">
|
160 |
+
|
161 |
+
<h3 class="hndle"><?php echo __( 'iCal Import/Export', 'wp-simple-booking-calendar' ); ?></h3>
|
162 |
+
|
163 |
+
<div class="inside">
|
164 |
+
|
165 |
+
<p><?php echo __( 'To configure the iCal import & export settings and have access to the iCal export link please click the button below.', 'wp-simple-booking-calendar' ); ?></p>
|
166 |
+
|
167 |
+
<a href="<?php echo add_query_arg( array( 'subpage' => 'ical-import-export' ), remove_query_arg( $removable_query_args ) ); ?>" class="button-secondary"><span class="dashicons dashicons-upload"></span> <?php echo __( 'iCal Import/Export', 'wp-simple-booking-calendar' ); ?></a>
|
168 |
+
|
169 |
+
</div>
|
170 |
+
|
171 |
+
</div><!-- / iCal Export -->
|
172 |
+
|
173 |
+
|
174 |
+
<!-- CSV Export -->
|
175 |
+
<div class="postbox">
|
176 |
+
|
177 |
+
<h3 class="hndle"><?php echo __( 'CSV Export', 'wp-simple-booking-calendar' ); ?></h3>
|
178 |
+
|
179 |
+
<div class="inside">
|
180 |
+
|
181 |
+
<p><?php echo __( 'To configure the CSV export settings please click the button below. ', 'wp-simple-booking-calendar' ); ?></p>
|
182 |
+
|
183 |
+
<a href="<?php echo add_query_arg( array( 'subpage' => 'csv-export' ), remove_query_arg( $removable_query_args ) ); ?>" class="button-secondary"><span class="dashicons dashicons-media-spreadsheet"></span> <?php echo __( 'CSV Export', 'wp-simple-booking-calendar' ); ?></a>
|
184 |
+
|
185 |
+
</div>
|
186 |
+
|
187 |
+
</div><!-- / CSV Export -->
|
188 |
+
|
189 |
+
|
190 |
+
<?php
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Action hook to add extra form fields to the main calendar edit area
|
194 |
+
*
|
195 |
+
* @param WPSBC_Calendar $calendar
|
196 |
+
*
|
197 |
+
*/
|
198 |
+
do_action( 'wpsbc_view_edit_calendar_sidebar', $calendar );
|
199 |
+
|
200 |
+
?>
|
201 |
+
|
202 |
+
</div><!-- / Sidebar Content -->
|
203 |
+
|
204 |
+
</div><!-- / #post-body -->
|
205 |
+
|
206 |
+
</div><!-- / #poststuff -->
|
207 |
+
|
208 |
+
<!-- Hidden fields -->
|
209 |
+
<input type="hidden" name="calendar_id" value="<?php echo $calendar_id; ?>" />
|
210 |
+
|
211 |
+
<!-- Save button -->
|
212 |
+
<input type="submit" class="wpsbc-save-calendar button-primary" value="<?php echo __( 'Save Calendar', 'wp-simple-booking-calendar' ); ?>" />
|
213 |
+
|
214 |
+
<!-- Save Button Spinner -->
|
215 |
+
<div class="wpsbc-save-calendar-spinner spinner"><!-- --></div>
|
216 |
+
|
217 |
+
</form>
|
218 |
+
|
219 |
+
</div>
|
includes/base/admin/calendar/views/view-shortcode-generator.php
ADDED
@@ -0,0 +1,167 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div id="wpsbc-modal-add-calendar-shortcode" class="wpsbc-modal">
|
9 |
+
|
10 |
+
<!-- Modal Header -->
|
11 |
+
<div class="wpsbc-modal-header">
|
12 |
+
|
13 |
+
<h2>
|
14 |
+
<span class="dashicons dashicons-calendar-alt"><!-- --></span>
|
15 |
+
<?php echo __( 'Add Calendar', 'wp-simple-booking-calendar' ); ?>
|
16 |
+
</h2>
|
17 |
+
|
18 |
+
<span class="wpsbc-modal-close dashicons dashicons-no-alt"><!-- --></span>
|
19 |
+
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<!-- Modal Body -->
|
23 |
+
<div class="wpsbc-modal-body">
|
24 |
+
|
25 |
+
<!-- Modal Nav Tab -->
|
26 |
+
<ul class="wpsbc-modal-nav-tab-wrapper">
|
27 |
+
<li class="wpsbc-nav-tab wpsbc-modal-nav-tab wpsbc-active" data-tab="calendar-single"><a href="#"><?php echo __( 'Insert Calendar', 'wp-simple-booking-calendar' ); ?></a></li>
|
28 |
+
<li class="wpsbc-nav-tab wpsbc-modal-nav-tab" data-tab="calendar-overview"><a href="#"><?php echo __( 'Insert Overview Calendar', 'wp-simple-booking-calendar' ); ?></a></li>
|
29 |
+
<li class="wpsbc-nav-tab wpsbc-modal-nav-tab" data-tab="calendar-search-widget"><a href="#"><?php echo __( 'Insert Search Widget', 'wp-simple-booking-calendar' ); ?></a></li>
|
30 |
+
</ul>
|
31 |
+
|
32 |
+
<!-- Modal Body Inner -->
|
33 |
+
<div class="wpsbc-modal-inner">
|
34 |
+
|
35 |
+
<!-- Modal Tab: Calendar Single -->
|
36 |
+
<div class="wpsbc-tab wpsbc-modal-tab wpsbc-active" data-tab="calendar-single">
|
37 |
+
|
38 |
+
<h3><?php echo __( 'Insert a Calendar', 'wp-simple-booking-calendar' ); ?></h3>
|
39 |
+
<p><?php echo __( 'Select which calendar you wish to insert and use the options to customize it to your needs.', 'wp-simple-booking-calendar' ); ?></p>
|
40 |
+
|
41 |
+
<h4><?php echo __( 'Basic Options', 'wp-simple-booking-calendar' ); ?></h4>
|
42 |
+
<hr />
|
43 |
+
|
44 |
+
<!-- Row -->
|
45 |
+
<div class="wpsbc-row">
|
46 |
+
|
47 |
+
<!-- Column: Calendar -->
|
48 |
+
<div class="wpsbc-col-1-4">
|
49 |
+
|
50 |
+
<?php $calendars = wpsbc_get_calendars(); ?>
|
51 |
+
|
52 |
+
<label for="modal-add-calendar-shortcode-calendar"><?php echo __( 'Calendar', 'wp-simple-booking-calendar' ); ?></label>
|
53 |
+
|
54 |
+
<select id="modal-add-calendar-shortcode-calendar" class="wpsbc-shortcode-generator-field-calendar" data-attribute="id">
|
55 |
+
<?php
|
56 |
+
foreach( $calendars as $calendar )
|
57 |
+
echo '<option value="' . $calendar->get('id') . '">' . $calendar->get('name') . '</option>';
|
58 |
+
?>
|
59 |
+
</select>
|
60 |
+
|
61 |
+
</div>
|
62 |
+
|
63 |
+
<!-- Column: Calendar Title -->
|
64 |
+
<div class="wpsbc-col-1-4">
|
65 |
+
|
66 |
+
<label for="modal-add-calendar-shortcode-calendar-title"><?php echo __( 'Display Calendar Title', 'wp-simple-booking-calendar' ); ?></label>
|
67 |
+
|
68 |
+
<select id="modal-add-calendar-shortcode-calendar-title" class="wpsbc-shortcode-generator-field-calendar" data-attribute="title">
|
69 |
+
<option value="yes"><?php echo __( 'Yes', 'wp-simple-booking-calendar' ); ?></option>
|
70 |
+
<option value="no"><?php echo __( 'No', 'wp-simple-booking-calendar' ); ?></option>
|
71 |
+
</select>
|
72 |
+
|
73 |
+
</div>
|
74 |
+
|
75 |
+
<!-- Column: Legend -->
|
76 |
+
<div class="wpsbc-col-1-4">
|
77 |
+
|
78 |
+
<label for="modal-add-calendar-shortcode-legend"><?php echo __( 'Display Legend', 'wp-simple-booking-calendar' ); ?></label>
|
79 |
+
|
80 |
+
<select id="modal-add-calendar-shortcode-legend" class="wpsbc-shortcode-generator-field-calendar" data-attribute="legend">
|
81 |
+
<option value="yes"><?php echo __( 'Yes', 'wp-simple-booking-calendar' ); ?></option>
|
82 |
+
<option value="no"><?php echo __( 'No', 'wp-simple-booking-calendar' ); ?></option>
|
83 |
+
</select>
|
84 |
+
|
85 |
+
</div>
|
86 |
+
|
87 |
+
<!-- Column: Legend Position -->
|
88 |
+
<div class="wpsbc-col-1-4">
|
89 |
+
|
90 |
+
<label for="modal-add-calendar-shortcode-legend-position"><?php echo __( 'Legend Position', 'wp-simple-booking-calendar' ); ?></label>
|
91 |
+
|
92 |
+
<select id="modal-add-calendar-shortcode-legend-position" class="wpsbc-shortcode-generator-field-calendar" data-attribute="legend_position">
|
93 |
+
<option value="side"><?php echo __( 'Side', 'wp-simple-booking-calendar' ); ?></option>
|
94 |
+
<option value="top"><?php echo __( 'Top', 'wp-simple-booking-calendar' ); ?></option>
|
95 |
+
<option value="bottom"><?php echo __( 'Bottom', 'wp-simple-booking-calendar' ); ?></option>
|
96 |
+
</select>
|
97 |
+
|
98 |
+
</div>
|
99 |
+
|
100 |
+
</div><!-- / Row -->
|
101 |
+
|
102 |
+
<!-- Row -->
|
103 |
+
<div class="wpsbc-row">
|
104 |
+
|
105 |
+
<!-- Column: Language -->
|
106 |
+
<div class="wpsbc-col-1-4">
|
107 |
+
|
108 |
+
<label for="modal-add-calendar-shortcode-language"><?php echo __( 'Language', 'wp-simple-booking-calendar' ); ?></label>
|
109 |
+
|
110 |
+
<select id="modal-add-calendar-shortcode-language" class="wpsbc-shortcode-generator-field-calendar" data-attribute="language">
|
111 |
+
|
112 |
+
<option value="auto"><?php echo __( 'Auto (let WP choose)', 'wp-simple-booking-calendar' ); ?></option>
|
113 |
+
|
114 |
+
<?php
|
115 |
+
|
116 |
+
$settings = get_option( 'wpsbc_settings', array() );
|
117 |
+
$languages = wpsbc_get_languages();
|
118 |
+
$active_languages = ( ! empty( $settings['active_languages'] ) ? $settings['active_languages'] : array() );
|
119 |
+
|
120 |
+
foreach( $active_languages as $code ) {
|
121 |
+
|
122 |
+
echo '<option value="' . esc_attr( $code ) . '">' . ( ! empty( $languages[$code] ) ? $languages[$code] : '' ) . '</option>';
|
123 |
+
|
124 |
+
}
|
125 |
+
|
126 |
+
?>
|
127 |
+
|
128 |
+
</select>
|
129 |
+
|
130 |
+
</div>
|
131 |
+
|
132 |
+
</div><!-- / Row -->
|
133 |
+
|
134 |
+
<hr />
|
135 |
+
|
136 |
+
<!-- Shortcode insert -->
|
137 |
+
<a href="#" id="wpsbc-insert-shortcode-single-calendar" class="button button-primary"><?php echo __( 'Insert Calendar', 'wp-simple-booking-calendar' ); ?></a>
|
138 |
+
<a href="#" class="button button-secondary wpsbc-modal-close"><?php echo __( 'Cancel', 'wp-simple-booking-calendar' ); ?></a>
|
139 |
+
|
140 |
+
</div>
|
141 |
+
|
142 |
+
|
143 |
+
<!-- Modal Tab: Calendar Overview -->
|
144 |
+
<div class="wpsbc-tab wpsbc-modal-tab" data-tab="calendar-overview">
|
145 |
+
<a href="<?php echo add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'upgrade-to-premium' ), admin_url('admin.php') ); ?>" class="wpsbc-wrap-upgrade-cta">
|
146 |
+
<span class="wpsbc-wrap-upgrade-cta-button">See details</span>
|
147 |
+
<span class="wpsbc-wrap-upgrade-cta-heading">The overview calendar is only available in the premium version.</span>
|
148 |
+
</a>
|
149 |
+
</div>
|
150 |
+
|
151 |
+
<!-- Modal Tab: Search Widget -->
|
152 |
+
<div class="wpsbc-tab wpsbc-modal-tab" data-tab="calendar-search-widget">
|
153 |
+
|
154 |
+
<a href="<?php echo add_query_arg( array( 'page' => 'wpsbc-calendars', 'subpage' => 'upgrade-to-premium' ), admin_url('admin.php') ); ?>" class="wpsbc-wrap-upgrade-cta">
|
155 |
+
<span class="wpsbc-wrap-upgrade-cta-button">See details</span>
|
156 |
+
<span class="wpsbc-wrap-upgrade-cta-heading">The search widget is only available in the premium version.</span>
|
157 |
+
</a>
|
158 |
+
|
159 |
+
</div>
|
160 |
+
|
161 |
+
</div>
|
162 |
+
|
163 |
+
</div>
|
164 |
+
|
165 |
+
</div>
|
166 |
+
|
167 |
+
<div id="wpsbc-modal-add-calendar-shortcode-overlay" class="wpsbc-modal-overlay"><!-- --></div>
|
includes/base/admin/class-admin-notices.php
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class that handles admin notice registration and output
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
Class WPSBC_Admin_Notices {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* The current instance of the object
|
14 |
+
*
|
15 |
+
* @access private
|
16 |
+
* @var WPSBC_Admin_Notices
|
17 |
+
*
|
18 |
+
*/
|
19 |
+
private static $instance;
|
20 |
+
|
21 |
+
/**
|
22 |
+
* List of notices that have been registered
|
23 |
+
*
|
24 |
+
* @access protected
|
25 |
+
* @var array
|
26 |
+
*
|
27 |
+
*/
|
28 |
+
protected $notices = array();
|
29 |
+
|
30 |
+
/**
|
31 |
+
* List of notices that will be printed in the page
|
32 |
+
*
|
33 |
+
* @access protected
|
34 |
+
* @var array
|
35 |
+
*
|
36 |
+
*/
|
37 |
+
protected $display_notices = array();
|
38 |
+
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Constructor
|
42 |
+
*
|
43 |
+
*/
|
44 |
+
public function __construct() {
|
45 |
+
|
46 |
+
add_action( 'admin_init', array( $this, 'catch_url_admin_notice' ), 100 );
|
47 |
+
add_action( 'admin_notices', array( $this, 'print_notices' ) );
|
48 |
+
|
49 |
+
}
|
50 |
+
|
51 |
+
|
52 |
+
/**
|
53 |
+
* Returns an instance of the object
|
54 |
+
*
|
55 |
+
* @return WPSBC_Admin_Notices
|
56 |
+
*
|
57 |
+
*/
|
58 |
+
public static function instance() {
|
59 |
+
|
60 |
+
if( ! isset( self::$instance ) && ! ( self::$instance instanceof WPSBC_Admin_Notices ) )
|
61 |
+
self::$instance = new WPSBC_Admin_Notices;
|
62 |
+
|
63 |
+
return self::$instance;
|
64 |
+
|
65 |
+
}
|
66 |
+
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Adds a new admin notice to the $notices property
|
70 |
+
*
|
71 |
+
* @param string $slug
|
72 |
+
* @param string $message
|
73 |
+
* @param string $class
|
74 |
+
*
|
75 |
+
*/
|
76 |
+
public function register_notice( $slug, $message, $class = 'updated' ) {
|
77 |
+
|
78 |
+
$this->notices[$slug] = array(
|
79 |
+
'message' => $message,
|
80 |
+
'class' => $class
|
81 |
+
);
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Prepares a registered admin notice for printing on admin_notices action
|
88 |
+
*
|
89 |
+
* @param string $slug
|
90 |
+
*
|
91 |
+
*/
|
92 |
+
public function display_notice( $slug ) {
|
93 |
+
|
94 |
+
$this->display_notices[] = $slug;
|
95 |
+
|
96 |
+
}
|
97 |
+
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Callback function to print admin notices
|
101 |
+
*
|
102 |
+
*/
|
103 |
+
public function print_notices() {
|
104 |
+
|
105 |
+
if( ! isset( $this->display_notices ) )
|
106 |
+
return;
|
107 |
+
|
108 |
+
foreach( $this->display_notices as $notice_slug ) {
|
109 |
+
|
110 |
+
if( empty( $this->notices[$notice_slug] ) )
|
111 |
+
continue;
|
112 |
+
|
113 |
+
echo '<div class="' . $this->notices[$notice_slug]['class'] . ' notice">';
|
114 |
+
echo $this->notices[$notice_slug]['message'];
|
115 |
+
echo '</div>';
|
116 |
+
|
117 |
+
}
|
118 |
+
|
119 |
+
}
|
120 |
+
|
121 |
+
|
122 |
+
/**
|
123 |
+
* Catches messages sent through the URL
|
124 |
+
*
|
125 |
+
*/
|
126 |
+
public function catch_url_admin_notice() {
|
127 |
+
|
128 |
+
if( empty( $_GET['wpsbc_message'] ) )
|
129 |
+
return;
|
130 |
+
|
131 |
+
$message_slug = sanitize_text_field( $_GET['wpsbc_message'] );
|
132 |
+
|
133 |
+
if( ! empty( $this->notices[$message_slug] ) )
|
134 |
+
$this->display_notice( $message_slug );
|
135 |
+
|
136 |
+
}
|
137 |
+
|
138 |
+
|
139 |
+
}
|
140 |
+
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Returns the instance of WPSBC_Admin_Notices
|
144 |
+
*
|
145 |
+
* @return WPSBC_Admin_Notices
|
146 |
+
*
|
147 |
+
*/
|
148 |
+
function wpsbc_admin_notices() {
|
149 |
+
|
150 |
+
return WPSBC_Admin_Notices::instance();
|
151 |
+
|
152 |
+
}
|
153 |
+
|
154 |
+
wpsbc_admin_notices();
|
includes/base/admin/functions.php
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Includes the files needed for the admin area
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_include_files_admin() {
|
12 |
+
|
13 |
+
// Get calendar dir path
|
14 |
+
$dir_path = plugin_dir_path( __FILE__ );
|
15 |
+
|
16 |
+
// Include the db layer classes
|
17 |
+
if( file_exists( $dir_path . 'class-admin-notices.php' ) )
|
18 |
+
include $dir_path . 'class-admin-notices.php';
|
19 |
+
|
20 |
+
}
|
21 |
+
add_action( 'wpsbc_include_files', 'wpsbc_include_files_admin' );
|
22 |
+
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Adds a central action hook on the admin_init that the plugin and add-ons
|
26 |
+
* can use to do certain actions, like adding a new calendar, editing a calendar, deleting, etc.
|
27 |
+
*
|
28 |
+
*/
|
29 |
+
function wpsbc_register_do_actions() {
|
30 |
+
|
31 |
+
if( empty( $_REQUEST['wpsbc_action'] ) )
|
32 |
+
return;
|
33 |
+
|
34 |
+
$action = sanitize_text_field( $_REQUEST['wpsbc_action'] );
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Hook that should be used by all processes that make a certain action
|
38 |
+
* withing the plugin, like adding a new calendar, editing a calendar, deleting, etc.
|
39 |
+
*
|
40 |
+
*/
|
41 |
+
do_action( 'wpsbc_action_' . $action );
|
42 |
+
|
43 |
+
}
|
44 |
+
add_action( 'admin_init', 'wpsbc_register_do_actions' );
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Builds and returns the HTML with a tooltip for the given message
|
49 |
+
*
|
50 |
+
* @param string $message
|
51 |
+
*
|
52 |
+
* @return string
|
53 |
+
*
|
54 |
+
*/
|
55 |
+
function wpsbc_get_output_tooltip( $message ) {
|
56 |
+
|
57 |
+
$output = '<span class="wpsbc-tooltip-wrapper">';
|
58 |
+
|
59 |
+
// Icon
|
60 |
+
$output .= '<span class="wpsbc-tooltip-icon">?</span>';
|
61 |
+
|
62 |
+
// Message
|
63 |
+
$output .= '<span class="wpsbc-tooltip-message">';
|
64 |
+
|
65 |
+
$output .= $message;
|
66 |
+
|
67 |
+
// Arrow
|
68 |
+
$output .= '<span class="wpsbc-tooltip-arrow"></span>';
|
69 |
+
|
70 |
+
$output .= '</span>';
|
71 |
+
|
72 |
+
$output .= '</span>';
|
73 |
+
|
74 |
+
return $output;
|
75 |
+
|
76 |
+
}
|
includes/base/admin/settings/class-submenu-page-settings.php
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
Class WPSBC_Submenu_Page_Settings extends WPSBC_Submenu_Page {
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Helper init method that runs on parent __construct
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
protected function init() {
|
14 |
+
|
15 |
+
add_action( 'admin_init', array( $this, 'register_settings' ), 10 );
|
16 |
+
add_action( 'admin_init', array( $this, 'register_admin_notices' ), 10 );
|
17 |
+
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Callback method to register admin notices that are sent via URL parameters
|
22 |
+
*
|
23 |
+
*/
|
24 |
+
public function register_admin_notices() {
|
25 |
+
|
26 |
+
// Settings save success
|
27 |
+
if( ! empty( $_GET['settings-updated'] ) ) {
|
28 |
+
wpsbc_admin_notices()->register_notice( 'settings_save_success', '<p>' . __( 'Settings saved successfully.', 'wp-simple-booking-calendar' ) . '</p>' );
|
29 |
+
wpsbc_admin_notices()->display_notice( 'settings_save_success' );
|
30 |
+
}
|
31 |
+
|
32 |
+
}
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Returns an array with the page tabs that should be displayed on the page
|
37 |
+
*
|
38 |
+
* @return array
|
39 |
+
*
|
40 |
+
*/
|
41 |
+
protected function get_tabs() {
|
42 |
+
|
43 |
+
$tabs = array(
|
44 |
+
'languages' => __( 'Languages', 'wp-simple-booking-calendar' ),
|
45 |
+
);
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Filter the tabs before returning
|
49 |
+
*
|
50 |
+
* @param array $tabs
|
51 |
+
*
|
52 |
+
*/
|
53 |
+
return apply_filters( 'wpsbc_submenu_page_settings_tabs', $tabs );
|
54 |
+
|
55 |
+
}
|
56 |
+
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Registers the settings option
|
60 |
+
*
|
61 |
+
*/
|
62 |
+
public function register_settings() {
|
63 |
+
|
64 |
+
register_setting( 'wpsbc_settings', 'wpsbc_settings', array( $this, 'settings_sanitize' ) );
|
65 |
+
|
66 |
+
}
|
67 |
+
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Sanitizes the settings before saving them to the db
|
71 |
+
*
|
72 |
+
*/
|
73 |
+
public function settings_sanitize( $settings ) {
|
74 |
+
|
75 |
+
return $settings;
|
76 |
+
|
77 |
+
}
|
78 |
+
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Callback for the HTML output for the Calendar page
|
82 |
+
*
|
83 |
+
*/
|
84 |
+
public function output() {
|
85 |
+
|
86 |
+
include 'views/view-settings.php';
|
87 |
+
|
88 |
+
}
|
89 |
+
|
90 |
+
}
|
includes/base/admin/settings/functions.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Includes the files needed for the Settings admin area
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_include_files_admin_settings() {
|
12 |
+
|
13 |
+
// Get legend admin dir path
|
14 |
+
$dir_path = plugin_dir_path( __FILE__ );
|
15 |
+
|
16 |
+
// Include submenu page
|
17 |
+
if( file_exists( $dir_path . 'class-submenu-page-settings.php' ) )
|
18 |
+
include $dir_path . 'class-submenu-page-settings.php';
|
19 |
+
|
20 |
+
}
|
21 |
+
add_action( 'wpsbc_include_files', 'wpsbc_include_files_admin_settings' );
|
22 |
+
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Register the Settings admin submenu page
|
26 |
+
*
|
27 |
+
*/
|
28 |
+
function wpsbc_register_submenu_page_settings( $submenu_pages ) {
|
29 |
+
|
30 |
+
if( ! is_array( $submenu_pages ) )
|
31 |
+
return $submenu_pages;
|
32 |
+
|
33 |
+
$submenu_pages['settings'] = array(
|
34 |
+
'class_name' => 'WPSBC_Submenu_Page_Settings',
|
35 |
+
'data' => array(
|
36 |
+
'page_title' => __( 'Settings', 'wp-simple-booking-calendar' ),
|
37 |
+
'menu_title' => __( 'Settings', 'wp-simple-booking-calendar' ),
|
38 |
+
'capability' => apply_filters( 'wpsbc_submenu_page_capability_settings', 'manage_options' ),
|
39 |
+
'menu_slug' => 'wpsbc-settings'
|
40 |
+
)
|
41 |
+
);
|
42 |
+
|
43 |
+
return $submenu_pages;
|
44 |
+
|
45 |
+
}
|
46 |
+
add_filter( 'wpsbc_register_submenu_page', 'wpsbc_register_submenu_page_settings', 50 );
|
includes/base/admin/settings/views/view-settings-tab-languages.php
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div class="wpsbc-settings-field-wrapper wpsbc-settings-field-inline">
|
9 |
+
|
10 |
+
<label class="wpsbc-settings-field-label">
|
11 |
+
<strong><?php echo __( 'Languages', 'wp-simple-booking-calendar' ); ?></strong>
|
12 |
+
<br /><br />
|
13 |
+
<?php echo __( 'What languages do you wish to use?', 'wp-simple-booking-calendar' ); ?>
|
14 |
+
</label>
|
15 |
+
|
16 |
+
<div class="wpsbc-settings-field-inner">
|
17 |
+
|
18 |
+
<?php
|
19 |
+
|
20 |
+
$languages = wpsbc_get_languages();
|
21 |
+
|
22 |
+
foreach( $languages as $code => $name ) {
|
23 |
+
|
24 |
+
$flag_code = ( $code == 'sv' ? 'se' : ( $code == 'sl' ? 'si' : $code ) );
|
25 |
+
|
26 |
+
echo '<div>';
|
27 |
+
echo '<label>';
|
28 |
+
echo '<input type="checkbox" name="wpsbc_settings[active_languages][]" value="' . esc_attr( $code ) . '" ' . ( ! empty( $settings['active_languages'] ) && in_array( $code, $settings['active_languages'] ) ? 'checked' : '' ) . ' />';
|
29 |
+
echo '<img src="' . WPSBC_PLUGIN_DIR_URL . 'assets/img/flags/' . esc_attr( $flag_code ) . '.png" />';
|
30 |
+
echo esc_html( $name );
|
31 |
+
echo '</label>';
|
32 |
+
echo '</div>';
|
33 |
+
|
34 |
+
}
|
35 |
+
|
36 |
+
?>
|
37 |
+
|
38 |
+
</div>
|
39 |
+
|
40 |
+
</div>
|
41 |
+
|
42 |
+
<!-- Submit button -->
|
43 |
+
<input type="submit" class="button-primary" value="<?php echo __( 'Save Settings', 'wp-simple-booking-calendar' ); ?>" />
|
includes/base/admin/settings/views/view-settings.php
ADDED
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
$tabs = $this->get_tabs();
|
7 |
+
$active_tab = ( ! empty( $_GET['tab'] ) ? sanitize_text_field( $_GET['tab'] ) : 'languages' );
|
8 |
+
$settings = get_option( 'wpsbc_settings', array() );
|
9 |
+
|
10 |
+
?>
|
11 |
+
|
12 |
+
<div class="wrap wpsbc-wrap">
|
13 |
+
|
14 |
+
<form action="options.php" method="POST">
|
15 |
+
|
16 |
+
<?php settings_fields( 'wpsbc_settings' ); ?>
|
17 |
+
|
18 |
+
<!-- Page Heading -->
|
19 |
+
<h1 class="wp-heading-inline"><?php echo __( 'Settings', 'wp-simple-booking-calendar' ); ?></h1>
|
20 |
+
<hr class="wp-header-end" />
|
21 |
+
|
22 |
+
<!-- Navigation Tabs -->
|
23 |
+
<h2 class="wpsbc-nav-tab-wrapper nav-tab-wrapper">
|
24 |
+
<?php
|
25 |
+
|
26 |
+
if( ! empty( $tabs ) ) {
|
27 |
+
foreach( $tabs as $tab_slug => $tab_name ) {
|
28 |
+
|
29 |
+
echo '<a href="' . add_query_arg( array( 'page' => 'wpsbc-settings', 'tab' => $tab_slug ), admin_url('admin.php') ) . '" data-tab="' . $tab_slug . '" class="nav-tab wpsbc-nav-tab ' . ( $active_tab == $tab_slug ? 'nav-tab-active' : '' ) . '">' . $tab_name . '</a>';
|
30 |
+
|
31 |
+
}
|
32 |
+
}
|
33 |
+
|
34 |
+
?>
|
35 |
+
</h2>
|
36 |
+
|
37 |
+
<!-- Tabs Contents -->
|
38 |
+
<div class="wpsbc-tab-wrapper">
|
39 |
+
|
40 |
+
<?php
|
41 |
+
|
42 |
+
if( ! empty( $tabs ) ) {
|
43 |
+
|
44 |
+
foreach( $tabs as $tab_slug => $tab_name ) {
|
45 |
+
|
46 |
+
echo '<div class="wpsbc-tab wpsbc-tab-' . $tab_slug . ' ' . ( $active_tab == $tab_slug ? 'wpsbc-active' : '' ) . '" data-tab="' . $tab_slug . '">';
|
47 |
+
|
48 |
+
// Handle general tab
|
49 |
+
if( $tab_slug == 'general' ) {
|
50 |
+
|
51 |
+
include 'view-settings-tab-general.php';
|
52 |
+
|
53 |
+
// Handle languages tab
|
54 |
+
} else if( $tab_slug == 'languages' ) {
|
55 |
+
|
56 |
+
include 'view-settings-tab-languages.php';
|
57 |
+
|
58 |
+
} else if( $tab_slug == 'search-widget' ) {
|
59 |
+
|
60 |
+
include 'view-settings-tab-search-widget.php';
|
61 |
+
|
62 |
+
// Handle dynamic tabs
|
63 |
+
} else {
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Action to dynamically add content for each tab
|
67 |
+
*
|
68 |
+
*/
|
69 |
+
do_action( 'wpsbc_submenu_page_settings_tab_' . $tab_slug );
|
70 |
+
|
71 |
+
}
|
72 |
+
|
73 |
+
echo '</div>';
|
74 |
+
|
75 |
+
}
|
76 |
+
|
77 |
+
}
|
78 |
+
|
79 |
+
?>
|
80 |
+
</div>
|
81 |
+
|
82 |
+
<!-- Always update hidden -->
|
83 |
+
<input type="hidden" name="wpsbc_settings[always_update]" value="<?php echo ( isset( $wpsbc_settings['always_update'] ) && $wpsbc_settings['always_update'] == 1 ? 0 : 1 ); ?>" />
|
84 |
+
|
85 |
+
</form>
|
86 |
+
|
87 |
+
</div>
|
includes/base/admin/upgrade-to-premium.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div class="wrap wpsbc-wrap wpsbc-wrap-upgrade-to-premium">
|
9 |
+
|
10 |
+
<h2>Upgrade to Premium</h2>
|
11 |
+
|
12 |
+
<h3>Finally, a calendar plugin that has it all!</h3>
|
13 |
+
|
14 |
+
<ul>
|
15 |
+
<li>
|
16 |
+
<strong><span class="dashicons dashicons-yes"></span> Create unlimited calendars</strong>
|
17 |
+
<p>Create unlimited calendars as opposed to just one.</p>
|
18 |
+
</li>
|
19 |
+
<li>
|
20 |
+
<strong><span class="dashicons dashicons-yes"></span> Create your own legend</strong>
|
21 |
+
<p>Set custom statuses for your dates, add split days, or just change the colors for the available and booked legends.</p>
|
22 |
+
</li>
|
23 |
+
|
24 |
+
<li>
|
25 |
+
<strong><span class="dashicons dashicons-yes"></span> iCalendar Sync, Import and Export</strong>
|
26 |
+
<p>Sync the availability of your calendar to any website that can import iCal feeds (including Airbnb, Booking.com or Google Calendar). </p>
|
27 |
+
</li>
|
28 |
+
<li>
|
29 |
+
<strong><span class="dashicons dashicons-yes"></span> Split days</strong>
|
30 |
+
<p>Choose between using full days or half(changeover) days when displaying availability.</p>
|
31 |
+
</li>
|
32 |
+
|
33 |
+
<li>
|
34 |
+
<strong><span class="dashicons dashicons-yes"></span> User Management</strong>
|
35 |
+
<p>Control who has access to your calendars by assigning WordPress users. You can assign general access per user type or assign a specific user to a specific calendar.</p>
|
36 |
+
</li>
|
37 |
+
<li>
|
38 |
+
<strong><span class="dashicons dashicons-yes"></span> Display an overview calendar</strong>
|
39 |
+
<p>You can create multiple calendars and combine them into one clear overview.</p>
|
40 |
+
</li>
|
41 |
+
<li>
|
42 |
+
<strong><span class="dashicons dashicons-yes"></span> Fully Translatable</strong>
|
43 |
+
<p>Some texts can automatically be translated in other languages, and you can fully translate forms and calendars in any language you want/need manually. </p>
|
44 |
+
</li>
|
45 |
+
<li>
|
46 |
+
<strong><span class="dashicons dashicons-yes"></span> Create a search widget</strong>
|
47 |
+
<p>You can create and embed a search widget, allowing your customers to search for available dates in all your calendars.</p>
|
48 |
+
</li>
|
49 |
+
<li>
|
50 |
+
<strong><span class="dashicons dashicons-yes"></span> Bulk Editor</strong>
|
51 |
+
<p>Use the powerful bulk editor to edit the availability of multiple days with one click.</p>
|
52 |
+
</li>
|
53 |
+
<li>
|
54 |
+
<strong><span class="dashicons dashicons-yes"></span> Tooltips</strong>
|
55 |
+
<p>Show tooltips on the front-end when users hover over calendar dates.</p>
|
56 |
+
</li>
|
57 |
+
<li>
|
58 |
+
<strong><span class="dashicons dashicons-yes"></span> Display multiple months</strong>
|
59 |
+
<p>Display multiple months so your customers can easily see the availability without needing to scroll through months.</p>
|
60 |
+
</li>
|
61 |
+
<li>
|
62 |
+
<strong><span class="dashicons dashicons-yes"></span> ...and a lot more</strong>
|
63 |
+
<p>Like changing the starting day of the week, set a custom start month or year, hide past bookings, show week numbers, and the list goes on.</p>
|
64 |
+
</li>
|
65 |
+
|
66 |
+
</ul>
|
67 |
+
|
68 |
+
|
69 |
+
|
70 |
+
|
71 |
+
<div class="cta">
|
72 |
+
<h3>Ready to take full advantage of the premium version?</h3>
|
73 |
+
|
74 |
+
|
75 |
+
<a class="wpsbc-button" href="https://www.wpsimplebookingcalendar.com/pricing/" target="_blank">Get Started</a>
|
76 |
+
|
77 |
+
<p class="prices">Prices starting from $39.</p>
|
78 |
+
|
79 |
+
|
80 |
+
</div>
|
81 |
+
|
82 |
+
|
83 |
+
<div class="cta-2">
|
84 |
+
<h4>Use this coupon code for a 15% discount. </h4>
|
85 |
+
<p class="discount">
|
86 |
+
<strong>FREE-VERSION-UPGRADE</strong>
|
87 |
+
</p>
|
88 |
+
|
89 |
+
</div>
|
90 |
+
|
91 |
+
<h3 class="wpsbc-clear">Need more convincing? See how the features work for you. <a href="https://www.wpsimplebookingcalendar.com/" target="_blank">Access the demos now</a>.</h3>
|
92 |
+
|
93 |
+
</div>
|
includes/base/calendar/class-calendar-outputter.php
ADDED
@@ -0,0 +1,820 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if (!defined('ABSPATH')) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
class WPSBC_Calendar_Outputter
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* The arguments for the calendar outputter
|
13 |
+
*
|
14 |
+
* @access protected
|
15 |
+
* @var array
|
16 |
+
*
|
17 |
+
*/
|
18 |
+
protected $args;
|
19 |
+
|
20 |
+
/**
|
21 |
+
* The WPSBC_Calendar
|
22 |
+
*
|
23 |
+
* @access protected
|
24 |
+
* @var WPSBC_Calendar
|
25 |
+
*
|
26 |
+
*/
|
27 |
+
protected $calendar = null;
|
28 |
+
|
29 |
+
/**
|
30 |
+
* The list of legend items associated with the calendar
|
31 |
+
*
|
32 |
+
* @access protected
|
33 |
+
* @var array
|
34 |
+
*
|
35 |
+
*/
|
36 |
+
protected $legend_items = array();
|
37 |
+
|
38 |
+
/**
|
39 |
+
* The default legend item of the calendar
|
40 |
+
*
|
41 |
+
* @access protected
|
42 |
+
* @var WPSBC_Legend_Item
|
43 |
+
*
|
44 |
+
*/
|
45 |
+
protected $default_legend_item = null;
|
46 |
+
|
47 |
+
/**
|
48 |
+
* The list of events for the calendar for the given displayed range
|
49 |
+
*
|
50 |
+
* @access protected
|
51 |
+
* @var array
|
52 |
+
*
|
53 |
+
*/
|
54 |
+
protected $events = array();
|
55 |
+
|
56 |
+
/**
|
57 |
+
* The plugin general settings
|
58 |
+
*
|
59 |
+
* @access protected
|
60 |
+
* @var array
|
61 |
+
*
|
62 |
+
*/
|
63 |
+
protected $plugin_settings = array();
|
64 |
+
|
65 |
+
/**
|
66 |
+
* A counter for the number of months being displayed in the calendar while
|
67 |
+
* iterating through them
|
68 |
+
*
|
69 |
+
* @access private
|
70 |
+
* @var int
|
71 |
+
*
|
72 |
+
*/
|
73 |
+
private $_months_iterator;
|
74 |
+
|
75 |
+
/**
|
76 |
+
* Constructor
|
77 |
+
*
|
78 |
+
* @param WPSBC_Calendar $calendar
|
79 |
+
* @param array $args
|
80 |
+
*
|
81 |
+
*/
|
82 |
+
public function __construct($calendar, $args = array())
|
83 |
+
{
|
84 |
+
|
85 |
+
/**
|
86 |
+
* Set arguments
|
87 |
+
*
|
88 |
+
*/
|
89 |
+
$this->args = wp_parse_args($args, wpsbc_get_calendar_output_default_args());
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Set the calendar
|
93 |
+
*
|
94 |
+
*/
|
95 |
+
$this->calendar = $calendar;
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Set the calendar legend items
|
99 |
+
*
|
100 |
+
*/
|
101 |
+
$this->legend_items = wpsbc_get_legend_items(array('calendar_id' => $calendar->get('id')));
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Set the default legend item
|
105 |
+
*
|
106 |
+
*/
|
107 |
+
foreach ($this->legend_items as $legend_item) {
|
108 |
+
|
109 |
+
if ($legend_item->get('is_default') == 1) {
|
110 |
+
$this->default_legend_item = $legend_item;
|
111 |
+
}
|
112 |
+
|
113 |
+
}
|
114 |
+
|
115 |
+
/**
|
116 |
+
* Set the calendar events
|
117 |
+
*
|
118 |
+
*/
|
119 |
+
$this->events = wpsbc_get_events(array('calendar_id' => $calendar->get('id')));
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Set plugin settings
|
123 |
+
*
|
124 |
+
*/
|
125 |
+
$this->plugin_settings = get_option('wpsbc_settings', array());
|
126 |
+
|
127 |
+
|
128 |
+
}
|
129 |
+
|
130 |
+
/**
|
131 |
+
* Constructs and returns the HTML for the entire calendar
|
132 |
+
*
|
133 |
+
* @return string
|
134 |
+
*
|
135 |
+
*/
|
136 |
+
public function get_display()
|
137 |
+
{
|
138 |
+
|
139 |
+
/**
|
140 |
+
* Return nothing if calendar is in Trash
|
141 |
+
*
|
142 |
+
*/
|
143 |
+
if ($this->calendar->get('status') == 'trash') {
|
144 |
+
return '';
|
145 |
+
}
|
146 |
+
|
147 |
+
/**
|
148 |
+
* Prepare needed data
|
149 |
+
*
|
150 |
+
*/
|
151 |
+
$year_to_show = (int) $this->args['current_year'];
|
152 |
+
$month_to_show = (int) $this->args['current_month'];
|
153 |
+
|
154 |
+
$calendar_html_data = 'data-id="' . $this->calendar->get('id') . '" ';
|
155 |
+
|
156 |
+
foreach ($this->args as $arg => $val) {
|
157 |
+
$calendar_html_data .= 'data-' . $arg . '="' . esc_attr($val) . '" ';
|
158 |
+
}
|
159 |
+
|
160 |
+
/**
|
161 |
+
* Handle output for existing calendar
|
162 |
+
*
|
163 |
+
*/
|
164 |
+
$output = '<div class="wpsbc-container wpsbc-calendar-' . (int) $this->calendar->get('id') . '" ' . $calendar_html_data . '>';
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Calendar title
|
168 |
+
*
|
169 |
+
*/
|
170 |
+
if ($this->args['show_title']) {
|
171 |
+
|
172 |
+
$calendar_title_wrapper_el = apply_filters('wpsbc_calendar_output_title_wrapper_element', 'h2', $this->calendar->get('id'));
|
173 |
+
|
174 |
+
if(wpsbc_get_calendar_meta($this->calendar->get('id'), 'calendar_name_translation_' . $this->args['language'],true)){
|
175 |
+
$calendar_name = wpsbc_get_calendar_meta($this->calendar->get('id'), 'calendar_name_translation_' . $this->args['language'],true);
|
176 |
+
} else {
|
177 |
+
$calendar_name = $this->calendar->get('name');
|
178 |
+
}
|
179 |
+
|
180 |
+
$output .= '<' . $calendar_title_wrapper_el . '>' . $calendar_name . '</' . $calendar_title_wrapper_el . '>';
|
181 |
+
|
182 |
+
}
|
183 |
+
|
184 |
+
$output .= '<div class="wpsbc-calendars-wrapper ' . ($this->args['show_legend'] ? 'wpsbc-legend-position-' . esc_attr($this->args['legend_position']) : '') . '">';
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Calendar Legend Top
|
188 |
+
*
|
189 |
+
*/
|
190 |
+
if ($this->args['show_legend'] && $this->args['legend_position'] != 'bottom') {
|
191 |
+
$output .= $this->get_display_legend();
|
192 |
+
}
|
193 |
+
|
194 |
+
/**
|
195 |
+
* Iterate through the number of months to show and get the display
|
196 |
+
* of the given month and year
|
197 |
+
*
|
198 |
+
*/
|
199 |
+
$output .= '<div class="wpsbc-calendars">';
|
200 |
+
|
201 |
+
$excluded_months = apply_filters('wpsbc_calendar_output_exclude_months', array());
|
202 |
+
|
203 |
+
|
204 |
+
// Set the months iterator
|
205 |
+
$this->_months_iterator = 1;
|
206 |
+
|
207 |
+
// Check if we need to exclude any months
|
208 |
+
if (!empty($excluded_months)) {
|
209 |
+
|
210 |
+
while (in_array($month_to_show, $excluded_months)) {
|
211 |
+
// Increment month and year (if needed)
|
212 |
+
$year_to_show = ($month_to_show + 1 > 12 ? ($year_to_show + 1) : $year_to_show);
|
213 |
+
$month_to_show = ($month_to_show + 1 > 12 ? ($month_to_show + 1 - 12) : ($month_to_show + 1));
|
214 |
+
|
215 |
+
}
|
216 |
+
|
217 |
+
}
|
218 |
+
|
219 |
+
// Get the month
|
220 |
+
$output .= $this->get_display_month($year_to_show, $month_to_show);
|
221 |
+
|
222 |
+
// Increment month and year (if needed)
|
223 |
+
$year_to_show = ($month_to_show + 1 > 12 ? ($year_to_show + 1) : $year_to_show);
|
224 |
+
$month_to_show = ($month_to_show + 1 > 12 ? ($month_to_show + 1 - 12) : ($month_to_show + 1));
|
225 |
+
|
226 |
+
$output .= '</div>'; // end of .wpsbc-calendars
|
227 |
+
|
228 |
+
/**
|
229 |
+
* Calendar Legend Bottom
|
230 |
+
*
|
231 |
+
*/
|
232 |
+
if ($this->args['show_legend'] && $this->args['legend_position'] == 'bottom') {
|
233 |
+
$output .= $this->get_display_legend();
|
234 |
+
}
|
235 |
+
|
236 |
+
$output .= '</div>'; // end of .wpsbc-calendars-wrapper
|
237 |
+
|
238 |
+
/**
|
239 |
+
* Calendar Custom CSS
|
240 |
+
*
|
241 |
+
*/
|
242 |
+
$output .= $this->get_custom_css();
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Flag needed for Gutenberg block to properly display the calendar
|
246 |
+
* in the editor after the block settings are changed
|
247 |
+
*
|
248 |
+
*/
|
249 |
+
$output .= '<div class="wpsbc-container-loaded" data-just-loaded="1"></div>';
|
250 |
+
|
251 |
+
$output .= '</div>'; // end of .wpsbc-container
|
252 |
+
|
253 |
+
return $output;
|
254 |
+
|
255 |
+
}
|
256 |
+
|
257 |
+
/**
|
258 |
+
* Constructs and returns the HTML for the given month of the given year
|
259 |
+
*
|
260 |
+
* @param int $year
|
261 |
+
* @param int $month
|
262 |
+
*
|
263 |
+
* @return string
|
264 |
+
*
|
265 |
+
*/
|
266 |
+
protected function get_display_month($year, $month)
|
267 |
+
{
|
268 |
+
|
269 |
+
$day_names = wpsbc_get_days_first_letters($this->args['language']);
|
270 |
+
$first_day = getdate(mktime(0, 0, 0, $month, 1, $year));
|
271 |
+
$total_days = date('t', mktime(0, 0, 0, $month, 1, $year));
|
272 |
+
|
273 |
+
$output = '<div class="wpsbc-calendar">';
|
274 |
+
|
275 |
+
/**
|
276 |
+
* Month header
|
277 |
+
*
|
278 |
+
*/
|
279 |
+
$output .= $this->get_display_month_header($year, $month);
|
280 |
+
|
281 |
+
/**
|
282 |
+
* Table with the actual calendar
|
283 |
+
*
|
284 |
+
*/
|
285 |
+
$output .= '<div class="wpsbc-calendar-wrapper">';
|
286 |
+
$output .= '<table>';
|
287 |
+
|
288 |
+
/**
|
289 |
+
* Table head
|
290 |
+
*
|
291 |
+
* This will display the name of the week days
|
292 |
+
*
|
293 |
+
*/
|
294 |
+
$output .= '<thead>';
|
295 |
+
$output .= '<tr>';
|
296 |
+
|
297 |
+
|
298 |
+
|
299 |
+
// The name of each day
|
300 |
+
for ($i = 0; $i < 7; $i++) {
|
301 |
+
|
302 |
+
$index = ($i > 6 ? $i - 7 : $i);
|
303 |
+
|
304 |
+
$output .= '<th>' . $day_names[$index] . '</th>';
|
305 |
+
}
|
306 |
+
|
307 |
+
$output .= '</tr>';
|
308 |
+
$output .= '</thead>';
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Table body
|
312 |
+
*
|
313 |
+
* This will display the actual dates for the current month
|
314 |
+
*
|
315 |
+
*/
|
316 |
+
$output .= '<tbody>';
|
317 |
+
|
318 |
+
// The days array
|
319 |
+
$days = array();
|
320 |
+
|
321 |
+
// The empty days at the begining of the calendar
|
322 |
+
$offset = $first_day['wday'];
|
323 |
+
|
324 |
+
if ($offset < 1) {
|
325 |
+
$offset += 7;
|
326 |
+
}
|
327 |
+
|
328 |
+
// Add first empty days
|
329 |
+
for ($i = 1; $i < $offset; $i++) {
|
330 |
+
$days[$i] = 0;
|
331 |
+
}
|
332 |
+
|
333 |
+
for ($j = $i; $j < $total_days + $i; $j++) {
|
334 |
+
$days[$j] = $j - $i + 1;
|
335 |
+
}
|
336 |
+
|
337 |
+
// Add remaining empty days
|
338 |
+
for ($i = 1; $i <= 7; $i++) {
|
339 |
+
|
340 |
+
if (count($days) % 7 == 0) {
|
341 |
+
break;
|
342 |
+
}
|
343 |
+
|
344 |
+
$days[] = 0;
|
345 |
+
|
346 |
+
}
|
347 |
+
|
348 |
+
$output .= '<tr>';
|
349 |
+
|
350 |
+
foreach ($days as $key => $day) {
|
351 |
+
|
352 |
+
|
353 |
+
// Get the output for the current day
|
354 |
+
$output .= '<td>' . $this->get_display_day($year, $month, $day) . '</td>';
|
355 |
+
|
356 |
+
if ($key % 7 == 0 && $key != count($days)) {
|
357 |
+
$output .= '</tr><tr>';
|
358 |
+
}
|
359 |
+
|
360 |
+
}
|
361 |
+
|
362 |
+
$output .= '</tr>';
|
363 |
+
|
364 |
+
$output .= '</tbody>';
|
365 |
+
|
366 |
+
$output .= '</table>';
|
367 |
+
$output .= '</div>'; // end of .wpsbc-calendar-wrapper
|
368 |
+
$output .= '</div>'; // end of .wpsbc-calendar
|
369 |
+
|
370 |
+
return $output;
|
371 |
+
|
372 |
+
}
|
373 |
+
|
374 |
+
/**
|
375 |
+
* Constructs and returns the HTML of the calendar (month) header
|
376 |
+
*
|
377 |
+
* @param int $year
|
378 |
+
* @param int $month
|
379 |
+
*
|
380 |
+
* @return string
|
381 |
+
*
|
382 |
+
*/
|
383 |
+
protected function get_display_month_header($year, $month)
|
384 |
+
{
|
385 |
+
|
386 |
+
$output = '<div class="wpsbc-calendar-header wpsbc-heading">';
|
387 |
+
$output .= '<div class="wpsbc-calendar-header-navigation">';
|
388 |
+
|
389 |
+
// Add navigate previous
|
390 |
+
if ($this->_months_iterator == 1) {
|
391 |
+
$output .= '<a href="#" class="wpsbc-prev"><span class="wpsbc-arrow"></span></a>';
|
392 |
+
}
|
393 |
+
|
394 |
+
// Add month selector
|
395 |
+
$output .= $this->get_display_month_selector($year, $month);
|
396 |
+
|
397 |
+
|
398 |
+
// Add navigate next
|
399 |
+
if ($this->_months_iterator == 1) {
|
400 |
+
$output .= '<a href="#" class="wpsbc-next"><span class="wpsbc-arrow"></span></a>';
|
401 |
+
}
|
402 |
+
|
403 |
+
$output .= '</div>'; // end .wpsbc-calendar-header-navigation
|
404 |
+
$output .= '</div>'; // end .wpsbc-calendar-header
|
405 |
+
|
406 |
+
return $output;
|
407 |
+
|
408 |
+
}
|
409 |
+
|
410 |
+
/**
|
411 |
+
* Constructs and returns the HTML of the calendar month selector from the header
|
412 |
+
*
|
413 |
+
* @param int $year
|
414 |
+
* @param int $month
|
415 |
+
*
|
416 |
+
* @return string
|
417 |
+
*
|
418 |
+
*/
|
419 |
+
protected function get_display_month_selector($year, $month)
|
420 |
+
{
|
421 |
+
|
422 |
+
$output = '<div class="wpsbc-select-container">';
|
423 |
+
|
424 |
+
/**
|
425 |
+
* Hook to modify how many months are being displayed in the select dropdown
|
426 |
+
* before the current given month of the year
|
427 |
+
*
|
428 |
+
* @param int $months_before
|
429 |
+
* @param int $calendar_id
|
430 |
+
* @param int $year
|
431 |
+
* @param int $month
|
432 |
+
*
|
433 |
+
*/
|
434 |
+
$months_before = apply_filters('wpsbc_calendar_output_month_selector_months_before', 3, $this->calendar->get('id'), $year, $month);
|
435 |
+
|
436 |
+
/**
|
437 |
+
* Hook to modify how many months are being displayed in the select dropdown
|
438 |
+
* after the current given month of the year
|
439 |
+
*
|
440 |
+
* @param int $months_after
|
441 |
+
* @param int $calendar_id
|
442 |
+
* @param int $year
|
443 |
+
* @param int $month
|
444 |
+
*
|
445 |
+
*/
|
446 |
+
$months_after = apply_filters('wpsbc_calendar_output_month_selector_months_after', 12, $this->calendar->get('id'), $year, $month);
|
447 |
+
|
448 |
+
/**
|
449 |
+
* Hook to modify the maximum number of months to display before now()
|
450 |
+
*
|
451 |
+
* @param int $months_before_max
|
452 |
+
* @param int $calendar_id
|
453 |
+
* @param int $year
|
454 |
+
* @param int $month
|
455 |
+
*
|
456 |
+
*/
|
457 |
+
$months_before_max = apply_filters('wpsbc_calendar_output_month_selector_months_before_max', -1, $this->calendar->get('id'), $year, $month);
|
458 |
+
|
459 |
+
/**
|
460 |
+
* Hook to modify the maximum number of months to display after now()
|
461 |
+
*
|
462 |
+
* @param int $months_after_max
|
463 |
+
* @param int $calendar_id
|
464 |
+
* @param int $year
|
465 |
+
* @param int $month
|
466 |
+
*
|
467 |
+
*/
|
468 |
+
$months_after_max = apply_filters('wpsbc_calendar_output_month_selector_months_after_max', -1, $this->calendar->get('id'), $year, $month);
|
469 |
+
|
470 |
+
/**
|
471 |
+
* Hook to exclude months from the date selector
|
472 |
+
*
|
473 |
+
* @param array $months
|
474 |
+
*
|
475 |
+
*/
|
476 |
+
$excluded_months = apply_filters('wpsbc_calendar_output_month_selector_exclude_months', array());
|
477 |
+
|
478 |
+
/**
|
479 |
+
* Hook to exclude past months from the date selector
|
480 |
+
*
|
481 |
+
* @param bool
|
482 |
+
*
|
483 |
+
*/
|
484 |
+
$show_past_months = apply_filters('wpsbc_calendar_output_month_selector_hide_past_months', true);
|
485 |
+
|
486 |
+
/**
|
487 |
+
* Build the months array
|
488 |
+
*
|
489 |
+
*/
|
490 |
+
|
491 |
+
// The array that will contain all options data
|
492 |
+
$select_options = array();
|
493 |
+
|
494 |
+
// Maximum before time
|
495 |
+
$before_max_month = date('n') + (12 * ceil($months_before_max / 12)) - $months_before_max;
|
496 |
+
$before_max_year = $year - ceil($months_before_max / 12);
|
497 |
+
$time_before_max = mktime(0, 0, 0, $before_max_month, 1, $before_max_year);
|
498 |
+
|
499 |
+
// Maximum after time
|
500 |
+
$after_max_month = (date('n') + $months_after_max - (12 * floor((date('n') + $months_after_max) / 12)));
|
501 |
+
$after_max_year = $year + floor((date('n') + $months_after_max) / 12);
|
502 |
+
$time_after_max = mktime(0, 0, 0, $after_max_month, 1, $after_max_year);
|
503 |
+
|
504 |
+
/**
|
505 |
+
* Add past months
|
506 |
+
*
|
507 |
+
*/
|
508 |
+
$_year = $year;
|
509 |
+
$_month = $month;
|
510 |
+
|
511 |
+
for ($i = 1; $i <= $months_before; $i++) {
|
512 |
+
|
513 |
+
// Exit loop if the max number of months has been reached
|
514 |
+
if ($months_before_max != -1 && mktime(0, 0, 0, $_month, 1, $_year) <= $time_before_max) {
|
515 |
+
break;
|
516 |
+
}
|
517 |
+
|
518 |
+
$_month -= 1;
|
519 |
+
|
520 |
+
if ($_month < 1) {
|
521 |
+
$_month += 12;
|
522 |
+
$_year -= 1;
|
523 |
+
}
|
524 |
+
|
525 |
+
if (in_array($_month, $excluded_months)) {
|
526 |
+
$months_before++;
|
527 |
+
continue;
|
528 |
+
}
|
529 |
+
|
530 |
+
if($show_past_months === false && $_month < current_time('m') && $_year <= current_time('Y')){
|
531 |
+
break;
|
532 |
+
}
|
533 |
+
|
534 |
+
$select_options[] = array(
|
535 |
+
'value' => mktime(0, 0, 0, $_month, 15, $_year),
|
536 |
+
'option' => apply_filters('wpsbc_calendar_output_month_selector_date_format', wpsbc_get_month_name($_month, $this->args['language']) . ' ' . $_year),
|
537 |
+
);
|
538 |
+
|
539 |
+
}
|
540 |
+
|
541 |
+
$select_options = array_reverse($select_options);
|
542 |
+
|
543 |
+
/**
|
544 |
+
* Add given current month
|
545 |
+
*
|
546 |
+
*/
|
547 |
+
$select_options[] = array(
|
548 |
+
'value' => mktime(0, 0, 0, $month, 15, $year),
|
549 |
+
'option' => apply_filters('wpsbc_calendar_output_month_selector_date_format', wpsbc_get_month_name($month, $this->args['language']) . ' ' . $year),
|
550 |
+
);
|
551 |
+
|
552 |
+
/**
|
553 |
+
* Add future months
|
554 |
+
*
|
555 |
+
*/
|
556 |
+
$_year = $year;
|
557 |
+
$_month = $month;
|
558 |
+
|
559 |
+
for ($i = 1; $i <= $months_after; $i++) {
|
560 |
+
|
561 |
+
if ($months_after_max != -1 && mktime(0, 0, 0, $_month, 1, $_year) >= $time_after_max) {
|
562 |
+
break;
|
563 |
+
}
|
564 |
+
|
565 |
+
$_month += 1;
|
566 |
+
|
567 |
+
if ($_month > 12) {
|
568 |
+
$_month -= 12;
|
569 |
+
$_year += 1;
|
570 |
+
}
|
571 |
+
|
572 |
+
if (in_array($_month, $excluded_months)) {
|
573 |
+
$months_after++;
|
574 |
+
continue;
|
575 |
+
}
|
576 |
+
|
577 |
+
$select_options[] = array(
|
578 |
+
'value' => mktime(0, 0, 0, $_month, 15, $_year),
|
579 |
+
'option' => apply_filters('wpsbc_calendar_output_month_selector_date_format', wpsbc_get_month_name($_month, $this->args['language']) . ' ' . $_year),
|
580 |
+
);
|
581 |
+
|
582 |
+
}
|
583 |
+
|
584 |
+
/**
|
585 |
+
* Output select
|
586 |
+
*
|
587 |
+
*/
|
588 |
+
$output .= '<select>';
|
589 |
+
|
590 |
+
foreach ($select_options as $select_option) {
|
591 |
+
$output .= '<option value="' . esc_attr($select_option['value']) . '" ' . selected($select_option['value'], mktime(0, 0, 0, $month, 15, $year), false) . '>' . $select_option['option'] . '</option>';
|
592 |
+
}
|
593 |
+
|
594 |
+
$output .= '</select>';
|
595 |
+
|
596 |
+
$output .= '</div>'; // end .wpsbc-select-container
|
597 |
+
|
598 |
+
return $output;
|
599 |
+
|
600 |
+
}
|
601 |
+
|
602 |
+
/**
|
603 |
+
* Constructs and returns the HTML for the given day of the given month of the given year
|
604 |
+
*
|
605 |
+
* @param int $year
|
606 |
+
* @param int $month
|
607 |
+
* @param int $day
|
608 |
+
*
|
609 |
+
* @return string
|
610 |
+
*
|
611 |
+
*/
|
612 |
+
protected function get_display_day($year, $month, $day)
|
613 |
+
{
|
614 |
+
|
615 |
+
$output = '';
|
616 |
+
|
617 |
+
/**
|
618 |
+
* Get the event for the current day
|
619 |
+
*
|
620 |
+
*/
|
621 |
+
$event = $this->get_event_by_date($year, $month, $day);
|
622 |
+
|
623 |
+
|
624 |
+
/**
|
625 |
+
* Get the legend item for the current day
|
626 |
+
*
|
627 |
+
*/
|
628 |
+
$legend_item = null;
|
629 |
+
|
630 |
+
if (!is_null($event)) {
|
631 |
+
|
632 |
+
foreach ($this->legend_items as $li) {
|
633 |
+
|
634 |
+
if ($event->get('legend_item_id') == $li->get('id')) {
|
635 |
+
$legend_item = $li;
|
636 |
+
}
|
637 |
+
|
638 |
+
}
|
639 |
+
|
640 |
+
}
|
641 |
+
|
642 |
+
if (is_null($legend_item)) {
|
643 |
+
$legend_item = $this->default_legend_item;
|
644 |
+
}
|
645 |
+
|
646 |
+
// Determine if the current day is in the past
|
647 |
+
$is_past = $this->is_date_past($year, $month, $day);
|
648 |
+
|
649 |
+
/**
|
650 |
+
* Set the needed variables for the legend item output
|
651 |
+
*
|
652 |
+
*/
|
653 |
+
if (!empty($day)) {
|
654 |
+
|
655 |
+
$legend_item_id_icon = $legend_item->get('id');
|
656 |
+
$legend_item_type_icon = $legend_item->get('type');
|
657 |
+
|
658 |
+
}
|
659 |
+
|
660 |
+
/**
|
661 |
+
* Putting the day output pieces together
|
662 |
+
*
|
663 |
+
*/
|
664 |
+
$output .= '<div class="wpsbc-date ' . (!empty($legend_item_id_icon) && is_numeric($legend_item_id_icon) ? 'wpsbc-legend-item-' . $legend_item->get('id') : '') . ' ' . (empty($day) ? 'wpsbc-gap' : '') . '" ' . (!empty($day) ? ('data-year="' . esc_attr($year) . '" data-month="' . esc_attr($month) . '" data-day="' . esc_attr($day) . '"') : '') . '>';
|
665 |
+
|
666 |
+
if (!empty($day)) {
|
667 |
+
|
668 |
+
/**
|
669 |
+
* Legend item icon output
|
670 |
+
*
|
671 |
+
*/
|
672 |
+
$output .= wpsbc_get_legend_item_icon($legend_item_id_icon, $legend_item_type_icon);
|
673 |
+
|
674 |
+
}
|
675 |
+
|
676 |
+
$output .= '<div class="wpsbc-date-inner">' . (!empty($day) ? '<span class="wpsbc-date-number">' . $day . '</span>' : '') . '</div>';
|
677 |
+
|
678 |
+
$output .= '</div>';
|
679 |
+
|
680 |
+
return $output;
|
681 |
+
|
682 |
+
}
|
683 |
+
|
684 |
+
|
685 |
+
/**
|
686 |
+
* Constructs and returns the HTML for the calendar's legend
|
687 |
+
*
|
688 |
+
* @return string
|
689 |
+
*
|
690 |
+
*/
|
691 |
+
protected function get_display_legend()
|
692 |
+
{
|
693 |
+
|
694 |
+
$output = '<div class="wpsbc-legend">';
|
695 |
+
|
696 |
+
foreach ($this->legend_items as $legend_item) {
|
697 |
+
|
698 |
+
if ($legend_item->get('is_visible') == 0) {
|
699 |
+
continue;
|
700 |
+
}
|
701 |
+
|
702 |
+
$output .= '<div class="wpsbc-legend-item">';
|
703 |
+
$output .= wpsbc_get_legend_item_icon($legend_item->get('id'), $legend_item->get('type'));
|
704 |
+
$output .= '<span class=wpsbc-legend-item-name>' . $legend_item->get_name($this->args['language']) . '</span>';
|
705 |
+
$output .= '</div>';
|
706 |
+
|
707 |
+
}
|
708 |
+
|
709 |
+
$output .= '</div>';
|
710 |
+
|
711 |
+
return $output;
|
712 |
+
|
713 |
+
}
|
714 |
+
|
715 |
+
/**
|
716 |
+
* Constructs and returns the calendar's custom CSS
|
717 |
+
*
|
718 |
+
* @return string
|
719 |
+
*
|
720 |
+
*/
|
721 |
+
protected function get_custom_css()
|
722 |
+
{
|
723 |
+
|
724 |
+
$output = '<style>';
|
725 |
+
|
726 |
+
// Set the parent calendar class
|
727 |
+
$calendar_parent_class = '.wpsbc-container.wpsbc-calendar-' . (int) $this->calendar->get('id');
|
728 |
+
|
729 |
+
/**
|
730 |
+
* Legend Items CSS
|
731 |
+
*
|
732 |
+
*/
|
733 |
+
foreach ($this->legend_items as $legend_item) {
|
734 |
+
|
735 |
+
// Background colors
|
736 |
+
$colors = $legend_item->get('color');
|
737 |
+
|
738 |
+
$output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:first-of-type { background-color: ' . (!empty($colors[0]) ? esc_attr($colors[0]) : 'transparent') . '; }';
|
739 |
+
$output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:nth-of-type(2) { background-color: ' . (!empty($colors[1]) ? esc_attr($colors[1]) : 'transparent') . '; }';
|
740 |
+
|
741 |
+
$output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:first-of-type svg { fill: ' . (!empty($colors[0]) ? esc_attr($colors[0]) : 'transparent') . '; }';
|
742 |
+
$output .= $calendar_parent_class . ' .wpsbc-legend-item-icon-' . esc_attr($legend_item->get('id')) . ' div:nth-of-type(2) svg { fill: ' . (!empty($colors[1]) ? esc_attr($colors[1]) : 'transparent') . '; }';
|
743 |
+
|
744 |
+
// Text color
|
745 |
+
$color_text = $legend_item->get('color_text');
|
746 |
+
|
747 |
+
if (!empty($color_text)) {
|
748 |
+
$output .= $calendar_parent_class . ' .wpsbc-legend-item-' . esc_attr($legend_item->get('id')) . ' .wpsbc-date-number { color: ' . esc_attr($color_text) . '; }';
|
749 |
+
}
|
750 |
+
|
751 |
+
}
|
752 |
+
|
753 |
+
|
754 |
+
$output .= '</style>';
|
755 |
+
|
756 |
+
return $output;
|
757 |
+
|
758 |
+
}
|
759 |
+
|
760 |
+
/**
|
761 |
+
* Passes through all stored events and searches for the event that matches the given date
|
762 |
+
* If an event is found it is returned, else null is returned
|
763 |
+
*
|
764 |
+
* @param int $year
|
765 |
+
* @param int $month
|
766 |
+
* @param int $day
|
767 |
+
*
|
768 |
+
* @return mixed WPSBC_Event|null
|
769 |
+
*
|
770 |
+
*/
|
771 |
+
protected function get_event_by_date($year, $month, $day)
|
772 |
+
{
|
773 |
+
|
774 |
+
foreach ($this->events as $event) {
|
775 |
+
|
776 |
+
if ($event->get('date_year') == $year && $event->get('date_month') == $month && $event->get('date_day') == $day) {
|
777 |
+
return $event;
|
778 |
+
}
|
779 |
+
|
780 |
+
}
|
781 |
+
|
782 |
+
return null;
|
783 |
+
|
784 |
+
}
|
785 |
+
|
786 |
+
|
787 |
+
|
788 |
+
/**
|
789 |
+
* Determines whether the given date is in the past or not
|
790 |
+
*
|
791 |
+
* @param int $year
|
792 |
+
* @param int $month
|
793 |
+
* @param int $day
|
794 |
+
*
|
795 |
+
* @return bool
|
796 |
+
*
|
797 |
+
*/
|
798 |
+
protected function is_date_past($year, $month, $day)
|
799 |
+
{
|
800 |
+
|
801 |
+
$today = mktime(0, 0, 0, current_time('n'), current_time('j'), current_time('Y'));
|
802 |
+
$date = mktime(0, 0, 0, $month, $day, $year);
|
803 |
+
|
804 |
+
return ($today > $date);
|
805 |
+
|
806 |
+
}
|
807 |
+
|
808 |
+
|
809 |
+
/**
|
810 |
+
* Helper function that prints the calendar
|
811 |
+
*
|
812 |
+
*/
|
813 |
+
public function display()
|
814 |
+
{
|
815 |
+
|
816 |
+
echo $this->get_display();
|
817 |
+
|
818 |
+
}
|
819 |
+
|
820 |
+
}
|
includes/base/calendar/class-calendar.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* The main class for the Calendar
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
class WPSBC_Calendar extends WPSBC_Base_Object {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The Id of the legend item
|
15 |
+
*
|
16 |
+
* @access protected
|
17 |
+
* @var int
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
protected $id;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* The legend item name
|
24 |
+
*
|
25 |
+
* @access protected
|
26 |
+
* @var string
|
27 |
+
*
|
28 |
+
*/
|
29 |
+
protected $name;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The date when the calendar was created
|
33 |
+
*
|
34 |
+
* @access protected
|
35 |
+
* @var string
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
protected $date_created;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The date when the calendar was last modified
|
42 |
+
*
|
43 |
+
* @access protected
|
44 |
+
* @var string
|
45 |
+
*
|
46 |
+
*/
|
47 |
+
protected $date_modified;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* The status of the calendar
|
51 |
+
*
|
52 |
+
* @access protected
|
53 |
+
* @var string
|
54 |
+
*
|
55 |
+
*/
|
56 |
+
protected $status;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* The random ical hash
|
60 |
+
*
|
61 |
+
* @access protected
|
62 |
+
* @var string
|
63 |
+
*
|
64 |
+
*/
|
65 |
+
protected $ical_hash;
|
66 |
+
|
67 |
+
}
|
includes/base/calendar/class-object-db-calendars.php
ADDED
@@ -0,0 +1,157 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class that handles database queries for the Calendars
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
Class WPSBC_Object_DB_Calendars extends WPSBC_Object_DB {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Construct
|
15 |
+
*
|
16 |
+
*/
|
17 |
+
public function __construct() {
|
18 |
+
|
19 |
+
global $wpdb;
|
20 |
+
|
21 |
+
$this->table_name = $wpdb->prefix . 'wpsbc_calendars';
|
22 |
+
$this->primary_key = 'id';
|
23 |
+
$this->context = 'calendar';
|
24 |
+
$this->query_object_type = 'WPSBC_Calendar';
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Return the table columns
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
public function get_columns() {
|
34 |
+
|
35 |
+
return array(
|
36 |
+
'id' => '%d',
|
37 |
+
'name' => '%s',
|
38 |
+
'date_created' => '%s',
|
39 |
+
'date_modified' => '%s',
|
40 |
+
'status' => '%s',
|
41 |
+
'ical_hash' => '%s'
|
42 |
+
);
|
43 |
+
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Returns an array of WPSBC_Calendar objects from the database
|
49 |
+
*
|
50 |
+
* @param array $args
|
51 |
+
* @param bool $count - whether to return just the count for the query or not
|
52 |
+
*
|
53 |
+
* @return mixed array|int
|
54 |
+
*
|
55 |
+
*/
|
56 |
+
public function get_calendars( $args = array(), $count = false ) {
|
57 |
+
|
58 |
+
$defaults = array(
|
59 |
+
'number' => -1,
|
60 |
+
'offset' => 0,
|
61 |
+
'orderby' => 'id',
|
62 |
+
'order' => 'DESC',
|
63 |
+
'include' => array(),
|
64 |
+
'search' => ''
|
65 |
+
);
|
66 |
+
|
67 |
+
$args = wp_parse_args( $args, $defaults );
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Filter the query arguments just before making the db call
|
71 |
+
*
|
72 |
+
* @param array $args
|
73 |
+
*
|
74 |
+
*/
|
75 |
+
$args = apply_filters( 'wpsbc_get_calendars_args', $args );
|
76 |
+
|
77 |
+
// Number args
|
78 |
+
if( $args['number'] < 1 )
|
79 |
+
$args['number'] = 999999;
|
80 |
+
|
81 |
+
// Where clause
|
82 |
+
$where = "WHERE 1=1";
|
83 |
+
|
84 |
+
// Status where clause
|
85 |
+
if( ! empty( $args['status'] ) ) {
|
86 |
+
|
87 |
+
$status = sanitize_text_field( $args['status'] );
|
88 |
+
$where .= " AND status = '{$status}'";
|
89 |
+
|
90 |
+
}
|
91 |
+
|
92 |
+
// iCalendar hash where clause
|
93 |
+
if( ! empty( $args['ical_hash'] ) ) {
|
94 |
+
|
95 |
+
$ical_hash = sanitize_text_field( $args['ical_hash'] );
|
96 |
+
$where .= " AND ical_hash = '{$ical_hash}'";
|
97 |
+
|
98 |
+
}
|
99 |
+
|
100 |
+
// Include where clause
|
101 |
+
if( ! empty( $args['include'] ) ) {
|
102 |
+
|
103 |
+
$include = implode( ',', $args['include'] );
|
104 |
+
$where .= " AND id IN({$include})";
|
105 |
+
|
106 |
+
}
|
107 |
+
|
108 |
+
// Include search
|
109 |
+
if( ! empty( $args['search'] ) ) {
|
110 |
+
|
111 |
+
$search = sanitize_text_field( $args['search'] );
|
112 |
+
$where .= " AND name LIKE '%%{$search}%%'";
|
113 |
+
|
114 |
+
}
|
115 |
+
|
116 |
+
// Orderby
|
117 |
+
$orderby = sanitize_text_field( $args['orderby'] );
|
118 |
+
|
119 |
+
// Order
|
120 |
+
$order = ( 'DESC' === strtoupper( $args['order'] ) ? 'DESC' : 'ASC' );
|
121 |
+
|
122 |
+
$clauses = compact( 'where', 'orderby', 'order', 'count' );
|
123 |
+
|
124 |
+
$results = $this->get_results( $clauses, $args, 'wpsbc_get_calendar' );
|
125 |
+
|
126 |
+
return $results;
|
127 |
+
|
128 |
+
}
|
129 |
+
|
130 |
+
|
131 |
+
/**
|
132 |
+
* Creates and updates the database table for the calendars
|
133 |
+
*
|
134 |
+
*/
|
135 |
+
public function create_table() {
|
136 |
+
|
137 |
+
global $wpdb;
|
138 |
+
|
139 |
+
$table_name = $this->table_name;
|
140 |
+
$charset_collate = $wpdb->get_charset_collate();
|
141 |
+
|
142 |
+
$query = "CREATE TABLE {$table_name} (
|
143 |
+
id bigint(10) NOT NULL AUTO_INCREMENT,
|
144 |
+
name text NOT NULL,
|
145 |
+
date_created datetime NOT NULL,
|
146 |
+
date_modified datetime NOT NULL,
|
147 |
+
status text NOT NULL,
|
148 |
+
ical_hash text NOT NULL,
|
149 |
+
PRIMARY KEY id (id)
|
150 |
+
) {$charset_collate};";
|
151 |
+
|
152 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
153 |
+
dbDelta( $query );
|
154 |
+
|
155 |
+
}
|
156 |
+
|
157 |
+
}
|
includes/base/calendar/class-object-meta-db-calendars.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class that handles database queries for the Calendars
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
Class WPSBC_Object_Meta_DB_Calendars extends WPSBC_Object_Meta_DB {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Construct
|
14 |
+
*
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
|
18 |
+
global $wpdb;
|
19 |
+
|
20 |
+
$this->table_name = $wpdb->prefix . 'wpsbc_calendar_meta';
|
21 |
+
$this->primary_key = 'calendar_id';
|
22 |
+
$this->context = 'calendar';
|
23 |
+
|
24 |
+
add_action( 'plugins_loaded', array( $this, 'register_wpdb_column' ) );
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Register the meta table for the calendars with the $wpdb global
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
public function register_wpdb_column() {
|
34 |
+
|
35 |
+
global $wpdb;
|
36 |
+
|
37 |
+
$meta_table_name = $this->context . 'meta';
|
38 |
+
$wpdb->{$meta_table_name} = $this->table_name;
|
39 |
+
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Return the table columns
|
45 |
+
*
|
46 |
+
*/
|
47 |
+
public function get_columns() {
|
48 |
+
|
49 |
+
return array(
|
50 |
+
'meta_id' => '%d',
|
51 |
+
'calendar_id' => '%d',
|
52 |
+
'meta_key' => '%s',
|
53 |
+
'meta_value' => '%s'
|
54 |
+
);
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Creates and updates the database table for the calendars
|
61 |
+
*
|
62 |
+
*/
|
63 |
+
public function create_table() {
|
64 |
+
|
65 |
+
global $wpdb;
|
66 |
+
|
67 |
+
$table_name = $this->table_name;
|
68 |
+
$charset_collate = $wpdb->get_charset_collate();
|
69 |
+
|
70 |
+
$query = "CREATE TABLE {$table_name} (
|
71 |
+
meta_id bigint(20) NOT NULL AUTO_INCREMENT,
|
72 |
+
calendar_id bigint(20) NOT NULL DEFAULT '0',
|
73 |
+
meta_key varchar(255) DEFAULT NULL,
|
74 |
+
meta_value longtext,
|
75 |
+
PRIMARY KEY (meta_id),
|
76 |
+
KEY calendar_id (calendar_id),
|
77 |
+
KEY meta_key (meta_key(191))
|
78 |
+
) {$charset_collate};";
|
79 |
+
|
80 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
81 |
+
dbDelta( $query );
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
}
|
includes/base/calendar/functions-ajax.php
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Ajax callback to refresh the calendar
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_refresh_calendar() {
|
12 |
+
|
13 |
+
if( empty( $_POST['action'] ) || $_POST['action'] != 'wpsbc_refresh_calendar' ) {
|
14 |
+
echo __( '', 'wp-simple-booking-calendar' );
|
15 |
+
wp_die();
|
16 |
+
}
|
17 |
+
|
18 |
+
if( empty( $_POST['id'] ) ) {
|
19 |
+
wp_die();
|
20 |
+
}
|
21 |
+
|
22 |
+
$calendar_id = absint( $_POST['id'] );
|
23 |
+
$calendar = wpsbc_get_calendar( $calendar_id );
|
24 |
+
$calendar_args = array();
|
25 |
+
|
26 |
+
foreach( $_POST as $key => $val ) {
|
27 |
+
|
28 |
+
if( in_array( $key, array_keys(wpsbc_get_calendar_output_default_args()) ) )
|
29 |
+
$calendar_args[$key] = sanitize_text_field( $val );
|
30 |
+
|
31 |
+
}
|
32 |
+
|
33 |
+
$calendar_outputter = new WPSBC_Calendar_Outputter( $calendar, $calendar_args );
|
34 |
+
|
35 |
+
echo $calendar_outputter->get_display();
|
36 |
+
wp_die();
|
37 |
+
|
38 |
+
}
|
39 |
+
add_action( 'wp_ajax_nopriv_wpsbc_refresh_calendar', 'wpsbc_refresh_calendar' );
|
40 |
+
add_action( 'wp_ajax_wpsbc_refresh_calendar', 'wpsbc_refresh_calendar' );
|
41 |
+
|
includes/base/calendar/functions.php
ADDED
@@ -0,0 +1,290 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if (!defined('ABSPATH')) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Includes the files needed for the Calendars
|
10 |
+
*
|
11 |
+
*/
|
12 |
+
function wpsbc_include_files_calendar()
|
13 |
+
{
|
14 |
+
|
15 |
+
// Get calendar dir path
|
16 |
+
$dir_path = plugin_dir_path(__FILE__);
|
17 |
+
|
18 |
+
// Include other functions files
|
19 |
+
if (file_exists($dir_path . 'functions-ajax.php')) {
|
20 |
+
include $dir_path . 'functions-ajax.php';
|
21 |
+
}
|
22 |
+
|
23 |
+
// Include main Calendar class
|
24 |
+
if (file_exists($dir_path . 'class-calendar.php')) {
|
25 |
+
include $dir_path . 'class-calendar.php';
|
26 |
+
}
|
27 |
+
|
28 |
+
// Include the db layer classes
|
29 |
+
if (file_exists($dir_path . 'class-object-db-calendars.php')) {
|
30 |
+
include $dir_path . 'class-object-db-calendars.php';
|
31 |
+
}
|
32 |
+
|
33 |
+
if (file_exists($dir_path . 'class-object-meta-db-calendars.php')) {
|
34 |
+
include $dir_path . 'class-object-meta-db-calendars.php';
|
35 |
+
}
|
36 |
+
|
37 |
+
// Include calendar outputters
|
38 |
+
if (file_exists($dir_path . 'class-calendar-outputter.php')) {
|
39 |
+
include $dir_path . 'class-calendar-outputter.php';
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
}
|
44 |
+
add_action('wpsbc_include_files', 'wpsbc_include_files_calendar');
|
45 |
+
|
46 |
+
/**
|
47 |
+
* Register the class that handles database queries for the Calendars
|
48 |
+
*
|
49 |
+
* @param array $classes
|
50 |
+
*
|
51 |
+
* @return array
|
52 |
+
*
|
53 |
+
*/
|
54 |
+
function wpsbc_register_database_classes_calendars($classes)
|
55 |
+
{
|
56 |
+
|
57 |
+
$classes['calendars'] = 'WPSBC_Object_DB_Calendars';
|
58 |
+
$classes['calendarmeta'] = 'WPSBC_Object_Meta_DB_Calendars';
|
59 |
+
|
60 |
+
return $classes;
|
61 |
+
|
62 |
+
}
|
63 |
+
add_filter('wpsbc_register_database_classes', 'wpsbc_register_database_classes_calendars');
|
64 |
+
|
65 |
+
/**
|
66 |
+
* Returns an array with WPSBC_Calendar objects from the database
|
67 |
+
*
|
68 |
+
* @param array $args
|
69 |
+
* @param bool $count
|
70 |
+
*
|
71 |
+
* @return array
|
72 |
+
*
|
73 |
+
*/
|
74 |
+
function wpsbc_get_calendars($args = array(), $count = false)
|
75 |
+
{
|
76 |
+
|
77 |
+
$calendars = wp_simple_booking_calendar()->db['calendars']->get_calendars($args, $count);
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Add a filter hook just before returning
|
81 |
+
*
|
82 |
+
* @param array $calendars
|
83 |
+
* @param array $args
|
84 |
+
* @param bool $count
|
85 |
+
*
|
86 |
+
*/
|
87 |
+
return apply_filters('wpsbc_get_calendars', $calendars, $args, $count);
|
88 |
+
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Gets a calendar from the database
|
93 |
+
*
|
94 |
+
* @param mixed int|object - calendar id or object representing the calendar
|
95 |
+
*
|
96 |
+
* @return WPSBC_Calendar|false
|
97 |
+
*
|
98 |
+
*/
|
99 |
+
function wpsbc_get_calendar($calendar)
|
100 |
+
{
|
101 |
+
|
102 |
+
return wp_simple_booking_calendar()->db['calendars']->get_object($calendar);
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Inserts a new calendar into the database
|
108 |
+
*
|
109 |
+
* @param array $data
|
110 |
+
*
|
111 |
+
* @return mixed int|false
|
112 |
+
*
|
113 |
+
*/
|
114 |
+
function wpsbc_insert_calendar($data)
|
115 |
+
{
|
116 |
+
|
117 |
+
return wp_simple_booking_calendar()->db['calendars']->insert($data);
|
118 |
+
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Updates a calendar from the database
|
123 |
+
*
|
124 |
+
* @param int $calendar_id
|
125 |
+
* @param array $data
|
126 |
+
*
|
127 |
+
* @return bool
|
128 |
+
*
|
129 |
+
*/
|
130 |
+
function wpsbc_update_calendar($calendar_id, $data)
|
131 |
+
{
|
132 |
+
|
133 |
+
return wp_simple_booking_calendar()->db['calendars']->update($calendar_id, $data);
|
134 |
+
|
135 |
+
}
|
136 |
+
|
137 |
+
/**
|
138 |
+
* Deletes a calendar from the database
|
139 |
+
*
|
140 |
+
* @param int $calendar_id
|
141 |
+
*
|
142 |
+
* @return bool
|
143 |
+
*
|
144 |
+
*/
|
145 |
+
function wpsbc_delete_calendar($calendar_id)
|
146 |
+
{
|
147 |
+
|
148 |
+
return wp_simple_booking_calendar()->db['calendars']->delete($calendar_id);
|
149 |
+
|
150 |
+
}
|
151 |
+
|
152 |
+
/**
|
153 |
+
* Inserts a new meta entry for the calendar
|
154 |
+
*
|
155 |
+
* @param int $calendar_id
|
156 |
+
* @param string $meta_key
|
157 |
+
* @param string $meta_value
|
158 |
+
* @param bool $unique
|
159 |
+
*
|
160 |
+
* @return mixed int|false
|
161 |
+
*
|
162 |
+
*/
|
163 |
+
function wpsbc_add_calendar_meta($calendar_id, $meta_key, $meta_value, $unique = false)
|
164 |
+
{
|
165 |
+
|
166 |
+
return wp_simple_booking_calendar()->db['calendarmeta']->add($calendar_id, $meta_key, $meta_value, $unique);
|
167 |
+
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Updates a meta entry for the calendar
|
172 |
+
*
|
173 |
+
* @param int $calendar_id
|
174 |
+
* @param string $meta_key
|
175 |
+
* @param string $meta_value
|
176 |
+
* @param bool $prev_value
|
177 |
+
*
|
178 |
+
* @return bool
|
179 |
+
*
|
180 |
+
*/
|
181 |
+
function wpsbc_update_calendar_meta($calendar_id, $meta_key, $meta_value, $prev_value = '')
|
182 |
+
{
|
183 |
+
|
184 |
+
return wp_simple_booking_calendar()->db['calendarmeta']->update($calendar_id, $meta_key, $meta_value, $prev_value);
|
185 |
+
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Returns a meta entry for the calendar
|
190 |
+
*
|
191 |
+
* @param int $calendar_id
|
192 |
+
* @param string $meta_key
|
193 |
+
* @param bool $single
|
194 |
+
*
|
195 |
+
* @return mixed
|
196 |
+
*
|
197 |
+
*/
|
198 |
+
function wpsbc_get_calendar_meta($calendar_id, $meta_key = '', $single = false)
|
199 |
+
{
|
200 |
+
|
201 |
+
return wp_simple_booking_calendar()->db['calendarmeta']->get($calendar_id, $meta_key, $single);
|
202 |
+
|
203 |
+
}
|
204 |
+
|
205 |
+
/**
|
206 |
+
* Removes a meta entry for the calendar
|
207 |
+
*
|
208 |
+
* @param int $calendar_id
|
209 |
+
* @param string $meta_key
|
210 |
+
* @param string $meta_value
|
211 |
+
* @param bool $delete_all
|
212 |
+
*
|
213 |
+
* @return bool
|
214 |
+
*
|
215 |
+
*/
|
216 |
+
function wpsbc_delete_calendar_meta($calendar_id, $meta_key, $meta_value = '', $delete_all = '')
|
217 |
+
{
|
218 |
+
|
219 |
+
return wp_simple_booking_calendar()->db['calendarmeta']->delete($calendar_id, $meta_key, $meta_value, $delete_all);
|
220 |
+
|
221 |
+
}
|
222 |
+
|
223 |
+
/**
|
224 |
+
* Returns the default arguments for the calendar outputter
|
225 |
+
*
|
226 |
+
* @return array
|
227 |
+
*
|
228 |
+
*/
|
229 |
+
function wpsbc_get_calendar_output_default_args()
|
230 |
+
{
|
231 |
+
|
232 |
+
$args = array(
|
233 |
+
'show_title' => 1,
|
234 |
+
'show_legend' => 1,
|
235 |
+
'legend_position' => 'side',
|
236 |
+
'show_button_navigation' => 1,
|
237 |
+
'current_year' => current_time('Y'),
|
238 |
+
'current_month' => current_time('n'),
|
239 |
+
'language' => wpsbc_get_locale(),
|
240 |
+
'min_width' => '200',
|
241 |
+
'max_width' => '380',
|
242 |
+
);
|
243 |
+
|
244 |
+
/**
|
245 |
+
* Filter the args before returning
|
246 |
+
*
|
247 |
+
* @param array $args
|
248 |
+
*
|
249 |
+
*/
|
250 |
+
$args = apply_filters('wpsbc_get_calendar_output_default_args', $args);
|
251 |
+
|
252 |
+
return $args;
|
253 |
+
|
254 |
+
}
|
255 |
+
|
256 |
+
/**
|
257 |
+
* Generates and returns a random 32 character long string
|
258 |
+
*
|
259 |
+
* @return string
|
260 |
+
*
|
261 |
+
*/
|
262 |
+
function wpsbc_generate_ical_hash()
|
263 |
+
{
|
264 |
+
|
265 |
+
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
266 |
+
$chars_length = strlen($chars);
|
267 |
+
$ical_hash = '';
|
268 |
+
|
269 |
+
for ($i = 0; $i < 19; $i++) {
|
270 |
+
|
271 |
+
$ical_hash .= $chars[rand(0, $chars_length - 1)];
|
272 |
+
|
273 |
+
}
|
274 |
+
|
275 |
+
return $ical_hash . uniqid();
|
276 |
+
|
277 |
+
}
|
278 |
+
|
279 |
+
/**
|
280 |
+
* Remove Timezone from Date strings.
|
281 |
+
*
|
282 |
+
* @param string $date
|
283 |
+
*
|
284 |
+
* @return string
|
285 |
+
*
|
286 |
+
*/
|
287 |
+
function wpsbc_remove_timezone_from_date_string($date)
|
288 |
+
{
|
289 |
+
return explode('T', $date)[0];
|
290 |
+
}
|
includes/base/class-shortcodes.php
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if (!defined('ABSPATH')) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
class WPSBC_Shortcodes
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Constructor
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
public function __construct()
|
16 |
+
{
|
17 |
+
|
18 |
+
// Register the single calendar shortcode
|
19 |
+
add_shortcode('wpsbc', array(__CLASS__, 'single_calendar'));
|
20 |
+
|
21 |
+
// Register the old shortcode as well
|
22 |
+
add_shortcode('sbc', array(__CLASS__, 'single_calendar'));
|
23 |
+
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* The callback for the WPSBC single calendar shortcode
|
28 |
+
*
|
29 |
+
* @param array $atts
|
30 |
+
*
|
31 |
+
*/
|
32 |
+
public static function single_calendar($atts)
|
33 |
+
{
|
34 |
+
|
35 |
+
// Shortcode default attributes
|
36 |
+
$default_atts = array(
|
37 |
+
'id' => 1,
|
38 |
+
'title' => 'yes',
|
39 |
+
'legend' => 'yes',
|
40 |
+
'legend_position' => '',
|
41 |
+
'language' => 'auto',
|
42 |
+
);
|
43 |
+
|
44 |
+
// Shortcode attributes
|
45 |
+
$atts = shortcode_atts($default_atts, $atts);
|
46 |
+
|
47 |
+
// Calendar outputter default arguments
|
48 |
+
$default_args = wpsbc_get_calendar_output_default_args();
|
49 |
+
|
50 |
+
// Translating values from the shortcode attributes to the calendar arguments
|
51 |
+
$args = array(
|
52 |
+
'show_title' => (!empty($atts['title']) && $atts['title'] == 'yes' ? 1 : 0),
|
53 |
+
'show_legend' => (!empty($atts['legend']) && $atts['legend'] == 'yes' ? 1 : 0),
|
54 |
+
'legend_position' => $atts['legend_position'],
|
55 |
+
'current_month' => current_time('n'),
|
56 |
+
'current_year' => current_time('Y'),
|
57 |
+
'language' => ($atts['language'] == 'auto' ? wpsbc_get_locale() : $atts['language']),
|
58 |
+
);
|
59 |
+
|
60 |
+
// Remove legend_position if it's empty
|
61 |
+
if (empty($args['legend_position'])) {
|
62 |
+
unset($args['legend_position']);
|
63 |
+
}
|
64 |
+
|
65 |
+
// Calendar arguments
|
66 |
+
$calendar_args = wp_parse_args($args, $default_args);
|
67 |
+
|
68 |
+
// Calendar id
|
69 |
+
$calendar_id = (!empty($atts['id']) ? (int) $atts['id'] : 0);
|
70 |
+
|
71 |
+
// Calendar
|
72 |
+
$calendar = wpsbc_get_calendar($calendar_id);
|
73 |
+
|
74 |
+
if (is_null($calendar)) {
|
75 |
+
|
76 |
+
$output = '<p>' . __('Calendar does not exist.', 'wp-simple-booking-calendar') . '</p>';
|
77 |
+
|
78 |
+
} else {
|
79 |
+
|
80 |
+
// Initialize the calendar outputter
|
81 |
+
$calendar_outputter = new WPSBC_Calendar_Outputter($calendar, $calendar_args);
|
82 |
+
|
83 |
+
$output = $calendar_outputter->get_display();
|
84 |
+
|
85 |
+
}
|
86 |
+
|
87 |
+
return $output;
|
88 |
+
|
89 |
+
}
|
90 |
+
|
91 |
+
}
|
92 |
+
|
93 |
+
// Init shortcodes
|
94 |
+
new WPSBC_Shortcodes();
|
includes/base/class-widget-calendar.php
ADDED
@@ -0,0 +1,349 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if (!defined('ABSPATH')) {
|
5 |
+
exit;
|
6 |
+
}
|
7 |
+
|
8 |
+
class WPSBC_Widget_Calendar extends WP_Widget
|
9 |
+
{
|
10 |
+
|
11 |
+
/**
|
12 |
+
* Constructor
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
public function __construct()
|
16 |
+
{
|
17 |
+
|
18 |
+
$widget_ops = array(
|
19 |
+
'classname' => 'wpsbc_calendar',
|
20 |
+
'description' => __('Insert a WP Simple Booking Calendar', 'wp-simple-booking-calendar'),
|
21 |
+
);
|
22 |
+
|
23 |
+
parent::__construct('wpsbc_calendar', 'WP Simple Booking Calendar', $widget_ops);
|
24 |
+
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Outputs the content of the widget
|
29 |
+
*
|
30 |
+
* @param array $args
|
31 |
+
* @param array $instance
|
32 |
+
*
|
33 |
+
*/
|
34 |
+
public function widget($args, $instance)
|
35 |
+
{
|
36 |
+
|
37 |
+
// Remove the "wpsbc" prefix to have a cleaner code
|
38 |
+
$instance = (!empty($instance) && is_array($instance) ? $instance : array());
|
39 |
+
|
40 |
+
foreach ($instance as $key => $value) {
|
41 |
+
|
42 |
+
$instance[str_replace('wpsbc_', '', $key)] = $value;
|
43 |
+
unset($instance[$key]);
|
44 |
+
|
45 |
+
}
|
46 |
+
|
47 |
+
$calendar = wpsbc_get_calendar(absint($instance['select_calendar']));
|
48 |
+
|
49 |
+
$calendar_args = array(
|
50 |
+
'show_title' => (!empty($instance['show_title']) && $instance['show_title'] == 'yes' ? 1 : 0),
|
51 |
+
'show_legend' => (!empty($instance['show_legend']) && $instance['show_legend'] == 'yes' ? 1 : 0),
|
52 |
+
'legend_position' => (!empty($instance['legend_position']) ? $instance['legend_position'] : 'top'),
|
53 |
+
'language' => (!empty($instance['calendar_language']) ? ($instance['calendar_language'] == 'auto' ? wpsbc_get_locale() : $instance['calendar_language']) : 'en'),
|
54 |
+
);
|
55 |
+
|
56 |
+
echo $args['before_widget'];
|
57 |
+
|
58 |
+
if (is_null($calendar)) {
|
59 |
+
|
60 |
+
echo '<p>' . __('Calendar does not exist.', 'wp-simple-booking-calendar') . '</p>';
|
61 |
+
|
62 |
+
} else {
|
63 |
+
|
64 |
+
$calendar_outputter = new WPSBC_Calendar_Outputter($calendar, $calendar_args);
|
65 |
+
|
66 |
+
echo $calendar_outputter->get_display();
|
67 |
+
}
|
68 |
+
|
69 |
+
echo $args['after_widget'];
|
70 |
+
}
|
71 |
+
|
72 |
+
/**
|
73 |
+
* Outputs the options form on admin
|
74 |
+
*
|
75 |
+
* @param array $instance The widget options
|
76 |
+
*
|
77 |
+
*/
|
78 |
+
public function form($instance)
|
79 |
+
{
|
80 |
+
|
81 |
+
global $wpdb;
|
82 |
+
|
83 |
+
$calendar_id = (!empty($instance['wpsbc_select_calendar']) ? $instance['wpsbc_select_calendar'] : 0);
|
84 |
+
$show_title = (!empty($instance['wpsbc_show_title']) ? $instance['wpsbc_show_title'] : 'yes');
|
85 |
+
$show_legend = (!empty($instance['wpsbc_show_legend']) ? $instance['wpsbc_show_legend'] : 'yes');
|
86 |
+
$legend_position = (!empty($instance['wpsbc_legend_position']) ? $instance['wpsbc_legend_position'] : 'top');
|
87 |
+
$calendar_language = (!empty($instance['wpsbc_calendar_language']) ? $instance['wpsbc_calendar_language'] : 'en');
|
88 |
+
|
89 |
+
$calendars = wpsbc_get_calendars();
|
90 |
+
|
91 |
+
?>
|
92 |
+
|
93 |
+
<!-- Calendar -->
|
94 |
+
<p>
|
95 |
+
<label for="<?php echo $this->get_field_id('wpsbc_select_calendar'); ?>"><?php echo __('Calendar', 'wp-simple-booking-calendar'); ?></label>
|
96 |
+
|
97 |
+
<select name="<?php echo $this->get_field_name('wpsbc_select_calendar'); ?>" id="<?php echo $this->get_field_id('wpsbc_select_calendar'); ?>" class="widefat">
|
98 |
+
<?php foreach ($calendars as $calendar): ?>
|
99 |
+
<option <?php echo ($calendar->get('id') == $calendar_id ? 'selected="selected"' : ''); ?> value="<?php echo $calendar->get('id'); ?>"><?php echo $calendar->get('name'); ?></option>
|
100 |
+
<?php endforeach;?>
|
101 |
+
</select>
|
102 |
+
</p>
|
103 |
+
|
104 |
+
<!-- Show Title -->
|
105 |
+
<p>
|
106 |
+
<label for="<?php echo $this->get_field_id('wpsbc_show_title'); ?>"><?php echo __('Display title', 'wp-simple-booking-calendar'); ?></label>
|
107 |
+
|
108 |
+
<select name="<?php echo $this->get_field_name('wpsbc_show_title'); ?>" id="<?php echo $this->get_field_id('wpsbc_show_title'); ?>" class="widefat">
|
109 |
+
<option value="yes"><?php echo __('Yes', 'wp-simple-booking-calendar'); ?></option>
|
110 |
+
<option value="no" <?php echo ($show_title == 'no' ? 'selected="selected"' : ''); ?>><?php echo __('No', 'wp-simple-booking-calendar'); ?></option>
|
111 |
+
</select>
|
112 |
+
</p>
|
113 |
+
|
114 |
+
<!-- Show Legend -->
|
115 |
+
<p>
|
116 |
+
<label for="<?php echo $this->get_field_id('wpsbc_show_legend'); ?>"><?php echo __('Display legend', 'wp-simple-booking-calendar'); ?></label>
|
117 |
+
|
118 |
+
<select name="<?php echo $this->get_field_name('wpsbc_show_legend'); ?>" id="<?php echo $this->get_field_id('wpsbc_show_legend'); ?>" class="widefat">
|
119 |
+
<option value="yes"><?php echo __('Yes', 'wp-simple-booking-calendar'); ?></option>
|
120 |
+
<option value="no" <?php echo ($show_legend == 'no' ? 'selected="selected"' : ''); ?>><?php echo __('No', 'wp-simple-booking-calendar'); ?></option>
|
121 |
+
</select>
|
122 |
+
</p>
|
123 |
+
|
124 |
+
<!-- Legend Position -->
|
125 |
+
<p>
|
126 |
+
<label for="<?php echo $this->get_field_id('wpsbc_legend_position'); ?>"><?php echo __('Legend Position', 'wp-simple-booking-calendar'); ?></label>
|
127 |
+
|
128 |
+
<select name="<?php echo $this->get_field_name('wpsbc_legend_position'); ?>" id="<?php echo $this->get_field_id('wpsbc_legend_position'); ?>" class="widefat">
|
129 |
+
<option <?php echo ($legend_position == 'side' ? 'selected="selected"' : ''); ?> value="side"><?php echo __('Side', 'wp-simple-booking-calendar'); ?></option>
|
130 |
+
<option <?php echo ($legend_position == 'top' ? 'selected="selected"' : ''); ?> value="top"><?php echo __('Top', 'wp-simple-booking-calendar'); ?></option>
|
131 |
+
<option <?php echo ($legend_position == 'bottom' ? 'selected="selected"' : ''); ?> value="bottom"><?php echo __('Bottom', 'wp-simple-booking-calendar'); ?></option>
|
132 |
+
</select>
|
133 |
+
</p>
|
134 |
+
|
135 |
+
<!-- Calendar Language -->
|
136 |
+
<p>
|
137 |
+
<label for="<?php echo $this->get_field_id('wpsbc_calendar_language'); ?>"><?php echo __('Language', 'wp-simple-booking-calendar'); ?></label>
|
138 |
+
|
139 |
+
<select name="<?php echo $this->get_field_name('wpsbc_calendar_language'); ?>" id="<?php echo $this->get_field_id('wpsbc_calendar_language'); ?>" class="widefat">
|
140 |
+
<?php
|
141 |
+
$settings = get_option('wpsbc_settings', array());
|
142 |
+
$languages = wpsbc_get_languages();
|
143 |
+
$active_languages = (!empty($settings['active_languages']) ? $settings['active_languages'] : array());
|
144 |
+
?>
|
145 |
+
|
146 |
+
<option value="auto"><?php echo __('Auto (let WP choose)', 'wp-simple-booking-calendar'); ?></option>
|
147 |
+
|
148 |
+
<?php foreach ($active_languages as $code): ?>
|
149 |
+
<option value="<?php echo esc_attr($code); ?>" <?php echo ($calendar_language == $code ? 'selected="selected"' : ''); ?>><?php echo (!empty($languages[$code]) ? $languages[$code] : ''); ?></option>
|
150 |
+
<?php endforeach;?>
|
151 |
+
</select>
|
152 |
+
</p>
|
153 |
+
|
154 |
+
<?php
|
155 |
+
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Processing widget options on save
|
160 |
+
*
|
161 |
+
* @param array $new_instance The new options
|
162 |
+
* @param array $old_instance The previous options
|
163 |
+
*
|
164 |
+
* @return array
|
165 |
+
*
|
166 |
+
*/
|
167 |
+
public function update($new_instance, $old_instance)
|
168 |
+
{
|
169 |
+
|
170 |
+
return $new_instance;
|
171 |
+
|
172 |
+
}
|
173 |
+
|
174 |
+
}
|
175 |
+
|
176 |
+
|
177 |
+
// Old widget
|
178 |
+
class WpSimpleBookingCalendar_Widget extends WP_Widget
|
179 |
+
{
|
180 |
+
|
181 |
+
/**
|
182 |
+
* Constructor
|
183 |
+
*
|
184 |
+
*/
|
185 |
+
public function __construct()
|
186 |
+
{
|
187 |
+
|
188 |
+
$widget_ops = array(
|
189 |
+
'classname' => 'widget-sbc',
|
190 |
+
'description' => __('Insert a WP Simple Booking Calendar', 'wp-simple-booking-calendar'),
|
191 |
+
);
|
192 |
+
|
193 |
+
parent::__construct(false, 'WP Simple Booking Calendar - Old Widget', $widget_ops);
|
194 |
+
|
195 |
+
}
|
196 |
+
|
197 |
+
/**
|
198 |
+
* Outputs the content of the widget
|
199 |
+
*
|
200 |
+
* @param array $args
|
201 |
+
* @param array $instance
|
202 |
+
*
|
203 |
+
*/
|
204 |
+
public function widget($args, $instance)
|
205 |
+
{
|
206 |
+
|
207 |
+
// Remove the "wpsbc" prefix to have a cleaner code
|
208 |
+
$instance = (!empty($instance) && is_array($instance) ? $instance : array());
|
209 |
+
|
210 |
+
foreach ($instance as $key => $value) {
|
211 |
+
|
212 |
+
$instance[str_replace('wpsbc_', '', $key)] = $value;
|
213 |
+
unset($instance[$key]);
|
214 |
+
|
215 |
+
}
|
216 |
+
|
217 |
+
$calendar = wpsbc_get_calendar(1);
|
218 |
+
|
219 |
+
$calendar_args = array(
|
220 |
+
'show_title' => (!empty($instance['show_title']) && $instance['show_title'] == 'yes' ? 1 : 0),
|
221 |
+
'show_legend' => (!empty($instance['show_legend']) && $instance['show_legend'] == 'yes' ? 1 : 0),
|
222 |
+
'legend_position' => (!empty($instance['legend_position']) ? $instance['legend_position'] : 'top'),
|
223 |
+
'language' => (!empty($instance['calendar_language']) ? ($instance['calendar_language'] == 'auto' ? wpsbc_get_locale() : $instance['calendar_language']) : 'en'),
|
224 |
+
);
|
225 |
+
|
226 |
+
if (is_null($calendar)) {
|
227 |
+
|
228 |
+
echo '<p>' . __('Calendar does not exist.', 'wp-simple-booking-calendar') . '</p>';
|
229 |
+
|
230 |
+
} else {
|
231 |
+
|
232 |
+
echo $args['before_widget'];
|
233 |
+
|
234 |
+
$calendar_outputter = new WPSBC_Calendar_Outputter($calendar, $calendar_args);
|
235 |
+
|
236 |
+
echo $calendar_outputter->get_display();
|
237 |
+
|
238 |
+
echo $args['after_widget'];
|
239 |
+
}
|
240 |
+
}
|
241 |
+
|
242 |
+
/**
|
243 |
+
* Outputs the options form on admin
|
244 |
+
*
|
245 |
+
* @param array $instance The widget options
|
246 |
+
*
|
247 |
+
*/
|
248 |
+
public function form($instance)
|
249 |
+
{
|
250 |
+
|
251 |
+
global $wpdb;
|
252 |
+
|
253 |
+
$calendar_id = (!empty($instance['wpsbc_select_calendar']) ? $instance['wpsbc_select_calendar'] : 1);
|
254 |
+
$show_title = (!empty($instance['wpsbc_show_title']) ? $instance['wpsbc_show_title'] : 'yes');
|
255 |
+
$show_legend = (!empty($instance['wpsbc_show_legend']) ? $instance['wpsbc_show_legend'] : 'yes');
|
256 |
+
$legend_position = (!empty($instance['wpsbc_legend_position']) ? $instance['wpsbc_legend_position'] : 'top');
|
257 |
+
$calendar_language = (!empty($instance['wpsbc_calendar_language']) ? $instance['wpsbc_calendar_language'] : 'en');
|
258 |
+
|
259 |
+
$calendars = wpsbc_get_calendars();
|
260 |
+
|
261 |
+
?>
|
262 |
+
|
263 |
+
<!-- Calendar -->
|
264 |
+
<p>
|
265 |
+
<label for="<?php echo $this->get_field_id('wpsbc_select_calendar'); ?>"><?php echo __('Calendar', 'wp-simple-booking-calendar'); ?></label>
|
266 |
+
|
267 |
+
<select name="<?php echo $this->get_field_name('wpsbc_select_calendar'); ?>" id="<?php echo $this->get_field_id('wpsbc_select_calendar'); ?>" class="widefat">
|
268 |
+
<?php foreach ($calendars as $calendar): ?>
|
269 |
+
<option <?php echo ($calendar->get('id') == $calendar_id ? 'selected="selected"' : ''); ?> value="<?php echo $calendar->get('id'); ?>"><?php echo $calendar->get('name'); ?></option>
|
270 |
+
<?php endforeach;?>
|
271 |
+
</select>
|
272 |
+
</p>
|
273 |
+
|
274 |
+
<!-- Show Title -->
|
275 |
+
<p>
|
276 |
+
<label for="<?php echo $this->get_field_id('wpsbc_show_title'); ?>"><?php echo __('Display title', 'wp-simple-booking-calendar'); ?></label>
|
277 |
+
|
278 |
+
<select name="<?php echo $this->get_field_name('wpsbc_show_title'); ?>" id="<?php echo $this->get_field_id('wpsbc_show_title'); ?>" class="widefat">
|
279 |
+
<option value="yes"><?php echo __('Yes', 'wp-simple-booking-calendar'); ?></option>
|
280 |
+
<option value="no" <?php echo ($show_title == 'no' ? 'selected="selected"' : ''); ?>><?php echo __('No', 'wp-simple-booking-calendar'); ?></option>
|
281 |
+
</select>
|
282 |
+
</p>
|
283 |
+
|
284 |
+
<!-- Show Legend -->
|
285 |
+
<p>
|
286 |
+
<label for="<?php echo $this->get_field_id('wpsbc_show_legend'); ?>"><?php echo __('Display legend', 'wp-simple-booking-calendar'); ?></label>
|
287 |
+
|
288 |
+
<select name="<?php echo $this->get_field_name('wpsbc_show_legend'); ?>" id="<?php echo $this->get_field_id('wpsbc_show_legend'); ?>" class="widefat">
|
289 |
+
<option value="yes"><?php echo __('Yes', 'wp-simple-booking-calendar'); ?></option>
|
290 |
+
<option value="no" <?php echo ($show_legend == 'no' ? 'selected="selected"' : ''); ?>><?php echo __('No', 'wp-simple-booking-calendar'); ?></option>
|
291 |
+
</select>
|
292 |
+
</p>
|
293 |
+
|
294 |
+
<!-- Legend Position -->
|
295 |
+
<p>
|
296 |
+
<label for="<?php echo $this->get_field_id('wpsbc_legend_position'); ?>"><?php echo __('Legend Position', 'wp-simple-booking-calendar'); ?></label>
|
297 |
+
|
298 |
+
<select name="<?php echo $this->get_field_name('wpsbc_legend_position'); ?>" id="<?php echo $this->get_field_id('wpsbc_legend_position'); ?>" class="widefat">
|
299 |
+
<option <?php echo ($legend_position == 'side' ? 'selected="selected"' : ''); ?> value="side"><?php echo __('Side', 'wp-simple-booking-calendar'); ?></option>
|
300 |
+
<option <?php echo ($legend_position == 'top' ? 'selected="selected"' : ''); ?> value="top"><?php echo __('Top', 'wp-simple-booking-calendar'); ?></option>
|
301 |
+
<option <?php echo ($legend_position == 'bottom' ? 'selected="selected"' : ''); ?> value="bottom"><?php echo __('Bottom', 'wp-simple-booking-calendar'); ?></option>
|
302 |
+
</select>
|
303 |
+
</p>
|
304 |
+
|
305 |
+
<!-- Calendar Language -->
|
306 |
+
<p>
|
307 |
+
<label for="<?php echo $this->get_field_id('wpsbc_calendar_language'); ?>"><?php echo __('Language', 'wp-simple-booking-calendar'); ?></label>
|
308 |
+
|
309 |
+
<select name="<?php echo $this->get_field_name('wpsbc_calendar_language'); ?>" id="<?php echo $this->get_field_id('wpsbc_calendar_language'); ?>" class="widefat">
|
310 |
+
<?php
|
311 |
+
$settings = get_option('wpsbc_settings', array());
|
312 |
+
$languages = wpsbc_get_languages();
|
313 |
+
$active_languages = (!empty($settings['active_languages']) ? $settings['active_languages'] : array());
|
314 |
+
?>
|
315 |
+
|
316 |
+
<option value="auto"><?php echo __('Auto (let WP choose)', 'wp-simple-booking-calendar'); ?></option>
|
317 |
+
|
318 |
+
<?php foreach ($active_languages as $code): ?>
|
319 |
+
<option value="<?php echo esc_attr($code); ?>" <?php echo ($calendar_language == $code ? 'selected="selected"' : ''); ?>><?php echo (!empty($languages[$code]) ? $languages[$code] : ''); ?></option>
|
320 |
+
<?php endforeach;?>
|
321 |
+
</select>
|
322 |
+
</p>
|
323 |
+
|
324 |
+
<?php
|
325 |
+
|
326 |
+
}
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Processing widget options on save
|
330 |
+
*
|
331 |
+
* @param array $new_instance The new options
|
332 |
+
* @param array $old_instance The previous options
|
333 |
+
*
|
334 |
+
* @return array
|
335 |
+
*
|
336 |
+
*/
|
337 |
+
public function update($new_instance, $old_instance)
|
338 |
+
{
|
339 |
+
|
340 |
+
return $new_instance;
|
341 |
+
|
342 |
+
}
|
343 |
+
|
344 |
+
}
|
345 |
+
|
346 |
+
add_action('widgets_init', function () {
|
347 |
+
register_widget('WPSBC_Widget_Calendar');
|
348 |
+
register_widget('WpSimpleBookingCalendar_Widget');
|
349 |
+
});
|
includes/base/event/class-event.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* The main class for the Event
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
class WPSBC_Event extends WPSBC_Base_Object {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The Id of the event
|
15 |
+
*
|
16 |
+
* @access protected
|
17 |
+
* @var int
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
protected $id;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* The year
|
24 |
+
*
|
25 |
+
* @access protected
|
26 |
+
* @var int
|
27 |
+
*
|
28 |
+
*/
|
29 |
+
protected $date_year;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The int number representing the month
|
33 |
+
*
|
34 |
+
* @access protected
|
35 |
+
* @var int
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
protected $date_month;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The int number representing the day
|
42 |
+
*
|
43 |
+
* @access protected
|
44 |
+
* @var int
|
45 |
+
*
|
46 |
+
*/
|
47 |
+
protected $date_day;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* The ID of the calendar in which the event should appear
|
51 |
+
*
|
52 |
+
* @access protected
|
53 |
+
* @var int
|
54 |
+
*
|
55 |
+
*/
|
56 |
+
protected $calendar_id;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* The ID of the legend item attached to the event
|
60 |
+
*
|
61 |
+
* @access protected
|
62 |
+
* @var int
|
63 |
+
*
|
64 |
+
*/
|
65 |
+
protected $legend_item_id;
|
66 |
+
|
67 |
+
/**
|
68 |
+
* The admin only description for the event
|
69 |
+
*
|
70 |
+
* @access protected
|
71 |
+
* @var string
|
72 |
+
*
|
73 |
+
*/
|
74 |
+
protected $description;
|
75 |
+
|
76 |
+
/**
|
77 |
+
* The optional tooltip to show in the calendar
|
78 |
+
*
|
79 |
+
* @access protected
|
80 |
+
* @var string
|
81 |
+
*
|
82 |
+
*/
|
83 |
+
protected $tooltip;
|
84 |
+
|
85 |
+
}
|
includes/base/event/class-object-db-events.php
ADDED
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class that handles database queries for the Events
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
Class WPSBC_Object_DB_Events extends WPSBC_Object_DB {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Construct
|
15 |
+
*
|
16 |
+
*/
|
17 |
+
public function __construct() {
|
18 |
+
|
19 |
+
global $wpdb;
|
20 |
+
|
21 |
+
$this->table_name = $wpdb->prefix . 'wpsbc_events';
|
22 |
+
$this->primary_key = 'id';
|
23 |
+
$this->context = 'event';
|
24 |
+
$this->query_object_type = 'WPSBC_Event';
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Return the table columns
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
public function get_columns() {
|
34 |
+
|
35 |
+
return array(
|
36 |
+
'id' => '%d',
|
37 |
+
'date_year' => '%d',
|
38 |
+
'date_month' => '%d',
|
39 |
+
'date_day' => '%d',
|
40 |
+
'calendar_id' => '%d',
|
41 |
+
'legend_item_id' => '%d',
|
42 |
+
'description' => '%s',
|
43 |
+
'tooltip' => '%s'
|
44 |
+
);
|
45 |
+
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Returns an array of WPSBC_Event objects from the database
|
51 |
+
*
|
52 |
+
* @param array $args
|
53 |
+
* @param bool $count - whether to return just the count for the query or not
|
54 |
+
*
|
55 |
+
* @return mixed array|int
|
56 |
+
*
|
57 |
+
*/
|
58 |
+
public function get_events( $args = array(), $count = false ) {
|
59 |
+
|
60 |
+
$defaults = array(
|
61 |
+
'number' => -1,
|
62 |
+
'offset' => 0,
|
63 |
+
'orderby' => 'id',
|
64 |
+
'order' => 'ASC',
|
65 |
+
'date_year' => array(),
|
66 |
+
'date_month' => array(),
|
67 |
+
'date_day' => array(),
|
68 |
+
'calendar_id' => 0,
|
69 |
+
'legend_item_id' => 0
|
70 |
+
);
|
71 |
+
|
72 |
+
$args = wp_parse_args( $args, $defaults );
|
73 |
+
|
74 |
+
// Number args
|
75 |
+
if( $args['number'] < 1 )
|
76 |
+
$args['number'] = 999999;
|
77 |
+
|
78 |
+
// Where clause
|
79 |
+
$where = '';
|
80 |
+
|
81 |
+
// Calendar ID where clause
|
82 |
+
if( ! empty( $args['calendar_id'] ) ) {
|
83 |
+
|
84 |
+
$calendar_id = absint( $args['calendar_id'] );
|
85 |
+
$where .= "WHERE calendar_id = {$calendar_id}";
|
86 |
+
|
87 |
+
}
|
88 |
+
|
89 |
+
// Legend Item ID where clause
|
90 |
+
if( ! empty( $args['legend_item_id'] ) ) {
|
91 |
+
|
92 |
+
$legend_item_id = absint( $args['legend_item_id'] );
|
93 |
+
$where .= " AND legend_item_id = {$legend_item_id}";
|
94 |
+
|
95 |
+
}
|
96 |
+
|
97 |
+
// Date Year Include
|
98 |
+
if( ! empty( $args['date_year'] ) ) {
|
99 |
+
|
100 |
+
if( is_array( $args['date_year'] ) ) {
|
101 |
+
|
102 |
+
$date_year = implode( ',', array_map( 'absint', $args['date_year'] ) );
|
103 |
+
$where .= " AND date_year IN ( {$date_year} )";
|
104 |
+
|
105 |
+
} else {
|
106 |
+
|
107 |
+
$date_year = absint( $args['date_year'] );
|
108 |
+
$where .= " AND date_year = {$date_year}";
|
109 |
+
|
110 |
+
}
|
111 |
+
|
112 |
+
}
|
113 |
+
|
114 |
+
// Date Month Include
|
115 |
+
if( ! empty( $args['date_month'] ) ) {
|
116 |
+
|
117 |
+
if( is_array( $args['date_month'] ) ) {
|
118 |
+
|
119 |
+
$date_month = implode( ',', array_map( 'absint', $args['date_month'] ) );
|
120 |
+
$where .= " AND date_month IN ( {$date_month} )";
|
121 |
+
|
122 |
+
} else {
|
123 |
+
|
124 |
+
$date_month = absint( $args['date_month'] );
|
125 |
+
$where .= " AND date_month = {$date_month}";
|
126 |
+
|
127 |
+
}
|
128 |
+
|
129 |
+
}
|
130 |
+
|
131 |
+
// Date Month Include
|
132 |
+
if( ! empty( $args['date_day'] ) ) {
|
133 |
+
|
134 |
+
if( is_array( $args['date_day'] ) ) {
|
135 |
+
|
136 |
+
$date_day = implode( ',', array_map( 'absint', $args['date_day'] ) );
|
137 |
+
$where .= " AND date_day IN ( {$date_day} )";
|
138 |
+
|
139 |
+
} else {
|
140 |
+
|
141 |
+
$date_day = absint( $args['date_day'] );
|
142 |
+
$where .= " AND date_day = {$date_day}";
|
143 |
+
|
144 |
+
}
|
145 |
+
|
146 |
+
}
|
147 |
+
|
148 |
+
// Orderby
|
149 |
+
$orderby = sanitize_text_field( $args['orderby'] );
|
150 |
+
|
151 |
+
// Order
|
152 |
+
$order = ( 'DESC' === strtoupper( $args['order'] ) ? 'DESC' : 'ASC' );
|
153 |
+
|
154 |
+
// Merge clauses
|
155 |
+
$clauses = compact( 'where', 'orderby', 'order', 'count' );
|
156 |
+
|
157 |
+
// Get results
|
158 |
+
$results = $this->get_results( $clauses, $args, 'wpsbc_get_event' );
|
159 |
+
|
160 |
+
return $results;
|
161 |
+
|
162 |
+
}
|
163 |
+
|
164 |
+
|
165 |
+
/**
|
166 |
+
* Creates and updates the database table for the legend items
|
167 |
+
*
|
168 |
+
*/
|
169 |
+
public function create_table() {
|
170 |
+
|
171 |
+
global $wpdb;
|
172 |
+
|
173 |
+
$table_name = $this->table_name;
|
174 |
+
$charset_collate = $wpdb->get_charset_collate();
|
175 |
+
|
176 |
+
$query = "CREATE TABLE {$table_name} (
|
177 |
+
id bigint(10) NOT NULL AUTO_INCREMENT,
|
178 |
+
date_year smallint(4) NOT NULL,
|
179 |
+
date_month smallint(2) NOT NULL,
|
180 |
+
date_day smallint(2) NOT NULL,
|
181 |
+
calendar_id bigint(10) NOT NULL,
|
182 |
+
legend_item_id bigint(10) NOT NULL,
|
183 |
+
description longtext NOT NULL,
|
184 |
+
tooltip longtext NOT NULL,
|
185 |
+
PRIMARY KEY id (id)
|
186 |
+
) {$charset_collate};";
|
187 |
+
|
188 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
189 |
+
dbDelta( $query );
|
190 |
+
|
191 |
+
}
|
192 |
+
|
193 |
+
}
|
includes/base/event/class-object-meta-db-events.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class that handles database queries for the Events
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
Class WPSBC_Object_Meta_DB_Events extends WPSBC_Object_Meta_DB {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Construct
|
14 |
+
*
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
|
18 |
+
global $wpdb;
|
19 |
+
|
20 |
+
$this->table_name = $wpdb->prefix . 'wpsbc_event_meta';
|
21 |
+
$this->primary_key = 'event_id';
|
22 |
+
$this->context = 'event';
|
23 |
+
|
24 |
+
add_action( 'plugins_loaded', array( $this, 'register_wpdb_column' ) );
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Register the meta table for the events with the $wpdb global
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
public function register_wpdb_column() {
|
34 |
+
|
35 |
+
global $wpdb;
|
36 |
+
|
37 |
+
$meta_table_name = $this->context . 'meta';
|
38 |
+
$wpdb->{$meta_table_name} = $this->table_name;
|
39 |
+
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Return the table columns
|
45 |
+
*
|
46 |
+
*/
|
47 |
+
public function get_columns() {
|
48 |
+
|
49 |
+
return array(
|
50 |
+
'meta_id' => '%d',
|
51 |
+
'event_id' => '%d',
|
52 |
+
'meta_key' => '%s',
|
53 |
+
'meta_value' => '%s'
|
54 |
+
);
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Creates and updates the database table for the events
|
61 |
+
*
|
62 |
+
*/
|
63 |
+
public function create_table() {
|
64 |
+
|
65 |
+
global $wpdb;
|
66 |
+
|
67 |
+
$table_name = $this->table_name;
|
68 |
+
$charset_collate = $wpdb->get_charset_collate();
|
69 |
+
|
70 |
+
$query = "CREATE TABLE {$table_name} (
|
71 |
+
meta_id bigint(20) NOT NULL AUTO_INCREMENT,
|
72 |
+
event_id bigint(20) NOT NULL DEFAULT '0',
|
73 |
+
meta_key varchar(255) DEFAULT NULL,
|
74 |
+
meta_value longtext,
|
75 |
+
PRIMARY KEY (meta_id),
|
76 |
+
KEY event_id (event_id),
|
77 |
+
KEY meta_key (meta_key(191))
|
78 |
+
) {$charset_collate};";
|
79 |
+
|
80 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
81 |
+
dbDelta( $query );
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
}
|
includes/base/event/functions.php
ADDED
@@ -0,0 +1,189 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Includes the files needed for the Legend items
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_include_files_events() {
|
12 |
+
|
13 |
+
// Get legend dir path
|
14 |
+
$dir_path = plugin_dir_path( __FILE__ );
|
15 |
+
|
16 |
+
// Include main Legend Item class
|
17 |
+
if( file_exists( $dir_path . 'class-event.php' ) )
|
18 |
+
include $dir_path . 'class-event.php';
|
19 |
+
|
20 |
+
// Include the db layer classes
|
21 |
+
if( file_exists( $dir_path . 'class-object-db-events.php' ) )
|
22 |
+
include $dir_path . 'class-object-db-events.php';
|
23 |
+
|
24 |
+
if( file_exists( $dir_path . 'class-object-meta-db-events.php' ) )
|
25 |
+
include $dir_path . 'class-object-meta-db-events.php';
|
26 |
+
|
27 |
+
}
|
28 |
+
add_action( 'wpsbc_include_files', 'wpsbc_include_files_events' );
|
29 |
+
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Register the class that handles database queries for the Events
|
33 |
+
*
|
34 |
+
* @param array $classes
|
35 |
+
*
|
36 |
+
* @return array
|
37 |
+
*
|
38 |
+
*/
|
39 |
+
function wpsbc_register_database_classes_events( $classes ) {
|
40 |
+
|
41 |
+
$classes['events'] = 'WPSBC_Object_DB_Events';
|
42 |
+
$classes['eventmeta'] = 'WPSBC_Object_Meta_DB_Events';
|
43 |
+
|
44 |
+
return $classes;
|
45 |
+
|
46 |
+
}
|
47 |
+
add_filter( 'wpsbc_register_database_classes', 'wpsbc_register_database_classes_events' );
|
48 |
+
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Returns an array with WPSBC_Event objects from the database
|
52 |
+
*
|
53 |
+
* @param array $args
|
54 |
+
* @param bool $count
|
55 |
+
*
|
56 |
+
* @return array
|
57 |
+
*
|
58 |
+
*/
|
59 |
+
function wpsbc_get_events( $args = array(), $count = false ) {
|
60 |
+
|
61 |
+
return wp_simple_booking_calendar()->db['events']->get_events( $args, $count );
|
62 |
+
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Gets an event from the database
|
68 |
+
*
|
69 |
+
* @param mixed int|object - event id or object representing the event
|
70 |
+
*
|
71 |
+
* @return WPSBC_Event|false
|
72 |
+
*
|
73 |
+
*/
|
74 |
+
function wpsbc_get_event( $event ) {
|
75 |
+
|
76 |
+
return wp_simple_booking_calendar()->db['events']->get_object( $event );
|
77 |
+
|
78 |
+
}
|
79 |
+
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Inserts a new event into the database
|
83 |
+
*
|
84 |
+
* @param array $data
|
85 |
+
*
|
86 |
+
* @return mixed int|false
|
87 |
+
*
|
88 |
+
*/
|
89 |
+
function wpsbc_insert_event( $data ) {
|
90 |
+
|
91 |
+
return wp_simple_booking_calendar()->db['events']->insert( $data );
|
92 |
+
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Updates an event from the database
|
97 |
+
*
|
98 |
+
* @param int $event_id
|
99 |
+
* @param array $data
|
100 |
+
*
|
101 |
+
* @return bool
|
102 |
+
*
|
103 |
+
*/
|
104 |
+
function wpsbc_update_event( $event_id, $data ) {
|
105 |
+
|
106 |
+
return wp_simple_booking_calendar()->db['events']->update( $event_id, $data );
|
107 |
+
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Deletes an event from the database
|
112 |
+
*
|
113 |
+
* @param int $event_id
|
114 |
+
*
|
115 |
+
* @return bool
|
116 |
+
*
|
117 |
+
*/
|
118 |
+
function wpsbc_delete_event( $event_id ) {
|
119 |
+
|
120 |
+
return wp_simple_booking_calendar()->db['events']->delete( $event_id );
|
121 |
+
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Inserts a new meta entry for the event
|
126 |
+
*
|
127 |
+
* @param int $event_id
|
128 |
+
* @param string $meta_key
|
129 |
+
* @param string $meta_value
|
130 |
+
* @param bool $unique
|
131 |
+
*
|
132 |
+
* @return mixed int|false
|
133 |
+
*
|
134 |
+
*/
|
135 |
+
function wpsbc_add_event_meta( $event_id, $meta_key, $meta_value, $unique = false ) {
|
136 |
+
|
137 |
+
return wp_simple_booking_calendar()->db['eventmeta']->add( $event_id, $meta_key, $meta_value, $unique );
|
138 |
+
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Updates a meta entry for the event
|
143 |
+
*
|
144 |
+
* @param int $event_id
|
145 |
+
* @param string $meta_key
|
146 |
+
* @param string $meta_value
|
147 |
+
* @param bool $prev_value
|
148 |
+
*
|
149 |
+
* @return bool
|
150 |
+
*
|
151 |
+
*/
|
152 |
+
function wpsbc_update_event_meta( $event_id, $meta_key, $meta_value, $prev_value = '' ) {
|
153 |
+
|
154 |
+
return wp_simple_booking_calendar()->db['eventmeta']->update( $event_id, $meta_key, $meta_value, $prev_value );
|
155 |
+
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Returns a meta entry for the event
|
160 |
+
*
|
161 |
+
* @param int $event_id
|
162 |
+
* @param string $meta_key
|
163 |
+
* @param bool $single
|
164 |
+
*
|
165 |
+
* @return mixed
|
166 |
+
*
|
167 |
+
*/
|
168 |
+
function wpsbc_get_event_meta( $event_id, $meta_key = '', $single = false ) {
|
169 |
+
|
170 |
+
return wp_simple_booking_calendar()->db['eventmeta']->get( $event_id, $meta_key, $single );
|
171 |
+
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Removes a meta entry for the event
|
176 |
+
*
|
177 |
+
* @param int $event_id
|
178 |
+
* @param string $meta_key
|
179 |
+
* @param string $meta_value
|
180 |
+
* @param bool $delete_all
|
181 |
+
*
|
182 |
+
* @return bool
|
183 |
+
*
|
184 |
+
*/
|
185 |
+
function wpsbc_delete_event_meta( $event_id, $meta_key, $meta_value = '', $delete_all = '' ) {
|
186 |
+
|
187 |
+
return wp_simple_booking_calendar()->db['eventmeta']->delete( $event_id, $meta_key, $meta_value, $delete_all );
|
188 |
+
|
189 |
+
}
|
includes/base/functions-languages.php
ADDED
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Returns an array with supported languages
|
9 |
+
*
|
10 |
+
* @return array
|
11 |
+
*
|
12 |
+
*/
|
13 |
+
function wpsbc_get_languages() {
|
14 |
+
|
15 |
+
$languages = array(
|
16 |
+
'en' => 'English',
|
17 |
+
'bg' => 'Bulgarian',
|
18 |
+
'ca' => 'Catalan',
|
19 |
+
'hr' => 'Croatian',
|
20 |
+
'cz' => 'Czech',
|
21 |
+
'da' => 'Danish',
|
22 |
+
'nl' => 'Dutch',
|
23 |
+
'eu' => 'Euskara',
|
24 |
+
'et' => 'Estonian',
|
25 |
+
'fi' => 'Finnish',
|
26 |
+
'fr' => 'French',
|
27 |
+
'gl' => 'Galician',
|
28 |
+
'de' => 'German',
|
29 |
+
'el' => 'Greek',
|
30 |
+
'hu' => 'Hungarian',
|
31 |
+
'it' => 'Italian',
|
32 |
+
'jp' => 'Japanese',
|
33 |
+
'lt' => 'Lithuanian',
|
34 |
+
'no' => 'Norwegian',
|
35 |
+
'pl' => 'Polish',
|
36 |
+
'pt' => 'Portugese',
|
37 |
+
'ro' => 'Romanian',
|
38 |
+
'ru' => 'Russian',
|
39 |
+
'sr' => 'Serbian',
|
40 |
+
'sk' => 'Slovak',
|
41 |
+
'sl' => 'Slovenian',
|
42 |
+
'es' => 'Spanish',
|
43 |
+
'sv' => 'Swedish',
|
44 |
+
'tr' => 'Turkish',
|
45 |
+
'ua' => 'Ukrainian'
|
46 |
+
);
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Filter to modify the languages array just before returning
|
50 |
+
*
|
51 |
+
* @param array $languages
|
52 |
+
*
|
53 |
+
*/
|
54 |
+
$languages = apply_filters( 'wpsbc_get_languages', $languages );
|
55 |
+
|
56 |
+
return $languages;
|
57 |
+
|
58 |
+
}
|
59 |
+
|
60 |
+
|
61 |
+
/**
|
62 |
+
* Returns an array with the first letter of each day of the week in order, starting
|
63 |
+
* from Monday until Sunday
|
64 |
+
*
|
65 |
+
* @param string $language_code
|
66 |
+
*
|
67 |
+
* @return array
|
68 |
+
*
|
69 |
+
*/
|
70 |
+
function wpsbc_get_days_first_letters( $language_code = 'en' ) {
|
71 |
+
|
72 |
+
$days_first_letters = array(
|
73 |
+
'af' => array( 'M','D','W','D','V','S','S' ), /* South Africa */
|
74 |
+
'bg' => array( 'П','В','С','Ч','П','С','Н' ), /* Bulgarian */
|
75 |
+
'ca' => array( 'D','D','D','D','D','D','D' ), /* Catalan */
|
76 |
+
'hr' => array( 'P','U','S','Č','P','S','N' ), /* Croatian */
|
77 |
+
'cz' => array( 'P','Ú','S','Č','P','S','N' ), /* Czech */
|
78 |
+
'cs' => array( 'P','Ú','S','Č','P','S','N' ), /* Czech */
|
79 |
+
'da' => array( 'M','T','O','T','F','L','S' ), /* Danish */
|
80 |
+
'nl' => array( 'M','D','W','D','V','Z','Z' ), /* Dutch */
|
81 |
+
'en' => array( 'M','T','W','T','F','S','S' ), /* English */
|
82 |
+
'eu' => array( 'A','A','A','O','O','L','I' ), /* Euskara */
|
83 |
+
'et' => array( 'E','T','K','N','R','L','P' ), /* Estonian */
|
84 |
+
'fi' => array( 'M','T','K','T','P','L','S' ), /* Finnish */
|
85 |
+
'fr' => array( 'L','M','M','J','V','S','D' ), /* French */
|
86 |
+
'gl' => array( 'L','M','M','X','V','S','D' ), /* Galician */
|
87 |
+
'de' => array( 'M','D','M','D','F','S','S' ), /* German */
|
88 |
+
'el' => array( 'Δ','Τ','Τ','Π','Π','Σ','Κ' ), /* Greek */
|
89 |
+
'hu' => array( 'H','K','S','C','P','S','V' ), /* Hungarian */
|
90 |
+
'it' => array( 'L','M','M','G','V','S','D' ), /* Italian */
|
91 |
+
'jp' => array( '月','火','水','木','金','土','日' ), /* Japanese */
|
92 |
+
'ja' => array( '月','火','水','木','金','土','日' ), /* Japanese */
|
93 |
+
'no' => array( 'M','T','O','T','F','L','S' ), /* Norwegian */
|
94 |
+
'lt' => array( 'P','A','T','K','P','Š','S' ), /* Lithuanian */
|
95 |
+
'nb' => array( 'M','T','O','T','F','L','S' ), /* Norwegian */
|
96 |
+
'pl' => array( 'P','W','S','C','P','S','N' ), /* Polish */
|
97 |
+
'pt' => array( 'S','T','Q','Q','S','S','D' ), /* Portugese */
|
98 |
+
'ro' => array( 'L','M','M','J','V','S','D' ), /* Romanian */
|
99 |
+
'ru' => array( 'П','В','С','Ч','П','С','В' ), /* Russian */
|
100 |
+
'sr' => array( 'P','U','S','Č','P','S','N' ), /* Serbian */
|
101 |
+
'sk' => array( 'P','U','S','Š','P','S','N' ), /* Slovak */
|
102 |
+
'sl' => array( 'P','T','S','Č','P','S','N' ), /* Slovenian */
|
103 |
+
'es' => array( 'L','M','M','J','V','S','D' ), /* Spanish */
|
104 |
+
'sv' => array( 'M','T','O','T','F','L','S' ), /* Swedish */
|
105 |
+
'tr' => array( 'P','S','Ç','P','C','C','P' ), /* Turkish */
|
106 |
+
'uk' => array( 'П','В','С','Ч','П','С','Н' ) /* Ukrainian */
|
107 |
+
);
|
108 |
+
|
109 |
+
return ( ! empty( $days_first_letters[$language_code] ) ? $days_first_letters[$language_code] : $days_first_letters['en'] );
|
110 |
+
|
111 |
+
}
|
112 |
+
|
113 |
+
|
114 |
+
/**
|
115 |
+
* Returns an array with the names of the months
|
116 |
+
*
|
117 |
+
* @param int $month
|
118 |
+
* @param string $language_code
|
119 |
+
*
|
120 |
+
* @return array
|
121 |
+
*
|
122 |
+
*/
|
123 |
+
function wpsbc_get_month_name( $month, $language_code = 'en' ) {
|
124 |
+
|
125 |
+
$month_names = array(
|
126 |
+
|
127 |
+
/* South Africa */
|
128 |
+
'af' => array( 'Januarie', 'Februarie', 'Maart', 'April', 'Mei', 'Junie', 'Julie', 'Augustus', 'September', 'Oktober', 'November', 'Desember' ),
|
129 |
+
|
130 |
+
/* Bulgarian */
|
131 |
+
'bg' => array( 'Януари', 'Февруари', 'Март', 'Април', 'Май', 'Юни', 'Юли', 'Август', 'Септември', 'Октомври', 'Ноември', 'Декември' ),
|
132 |
+
|
133 |
+
/* Catalan */
|
134 |
+
'ca' => array( 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'Juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre' ),
|
135 |
+
|
136 |
+
/* Croatian */
|
137 |
+
'hr' => array( 'Siječanj', 'Veljača', 'Ožujak', 'Travanj', 'Svibanj', 'Lipanj', 'Srpanj', 'Kolovoz', 'Rujan', 'Listopad', 'Studeni', 'Prosinac' ),
|
138 |
+
|
139 |
+
/* Czech */
|
140 |
+
'cz' => array( 'Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec' ),
|
141 |
+
|
142 |
+
/* Czech */
|
143 |
+
'cs' => array( 'Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec' ),
|
144 |
+
|
145 |
+
/* Danish */
|
146 |
+
'da' => array( 'Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December' ),
|
147 |
+
|
148 |
+
/* Dutch */
|
149 |
+
'nl' => array( 'Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December' ),
|
150 |
+
|
151 |
+
/* English */
|
152 |
+
'en' => array( 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ),
|
153 |
+
|
154 |
+
/* Euskara */
|
155 |
+
'eu' => array( 'Urtarrila', 'Otsaila', 'Martxoa', 'Apirila', 'Maiatza', 'Ekaina', 'Uztaila', 'Abuztua', 'Iraila', 'Urria', 'Azaroa', 'Abendua' ),
|
156 |
+
|
157 |
+
/* Estonian */
|
158 |
+
'et' => array( 'Jaanuar', 'Veebruar', 'Märts', 'Aprill', 'Mai', 'Juuni', 'Juuli', 'August', 'September', 'Oktoober', 'November', 'Detsember' ),
|
159 |
+
|
160 |
+
/* Finnish */
|
161 |
+
'fi' => array( 'Tammikuu', 'Helmikuu', 'Maaliskuu', 'Huhtikuu', 'Toukokuu', 'Kesäkuu', 'Heinäkuu', 'Elokuu', 'Syyskuu', 'Lokakuu', 'Marraskuu', 'Joulukuu' ),
|
162 |
+
|
163 |
+
/* French */
|
164 |
+
'fr' => array( 'Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre' ),
|
165 |
+
|
166 |
+
/* Galician */
|
167 |
+
'gl' => array( 'Xaneiro', 'Febreiro', 'Marzo', 'Abril', 'Maio', 'Xuño', 'Xullo', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Decembro' ),
|
168 |
+
|
169 |
+
/* German */
|
170 |
+
'de' => array( 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' ),
|
171 |
+
|
172 |
+
/* Greek */
|
173 |
+
'el' => array( 'Ιανουάριος', 'Φεβρουάριος', 'Μάρτιος', 'Απρίλιος', 'Μάιος', 'Ιούνιος', 'Ιούλιος', 'Αύγουστος', 'Σεπτέμβριος', 'Οκτώβριος', 'Νοέμβριος', 'Δεκέμβριος' ),
|
174 |
+
|
175 |
+
/* Hungarian */
|
176 |
+
'hu' => array( 'Január', 'Február', 'Március', 'Április', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December' ),
|
177 |
+
|
178 |
+
/* Italian */
|
179 |
+
'it' => array( 'Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre' ),
|
180 |
+
|
181 |
+
/* Japanese */
|
182 |
+
'jp' => array( '1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月' ),
|
183 |
+
'ja' => array( '1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月' ),
|
184 |
+
|
185 |
+
/* Lithuanian */
|
186 |
+
'lt' => array( 'Sausis', 'Vasaris', 'Kovas', 'Balandis', 'Gegužis', 'Birželis', 'Liepa', 'Rugpjūtis', 'Rugsėjis', 'Spalis', 'Lapkritis', 'Gruodis' ),
|
187 |
+
|
188 |
+
/* Norwegian */
|
189 |
+
'no' => array( 'Januar', 'Februar', 'Mars', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Desember' ),
|
190 |
+
|
191 |
+
/* Norwegian */
|
192 |
+
'nb' => array( 'Januar', 'Februar', 'Mars', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Desember' ),
|
193 |
+
|
194 |
+
/* Polish */
|
195 |
+
'pl' => array( 'Styczeń', 'Luty', 'Marzec', 'Kwiecień', 'Maj', 'Czerwiec', 'Lipiec', 'Sierpień', 'Wrzesień', 'Październik', 'Listopad', 'Grudzień' ),
|
196 |
+
|
197 |
+
/* Portugese */
|
198 |
+
'pt' => array( 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Septembro', 'Outubro', 'Novembro', 'Dezembro' ),
|
199 |
+
|
200 |
+
/* Romanian */
|
201 |
+
'ro' => array( 'Ianuarie', 'Februarie', 'Martie', 'Aprilie', 'Mai', 'Iunie', 'Iulie', 'August', 'Septembrie', 'Octombrie', 'Noiembrie', 'Decembrie' ),
|
202 |
+
|
203 |
+
/* Russian */
|
204 |
+
'ru' => array( 'Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь' ),
|
205 |
+
|
206 |
+
/* Serbian */
|
207 |
+
'sr' => array( 'Januar', 'Februar', 'Mart', 'April', 'Maj', 'Jun', 'Jul', 'Avgust', 'Septembar', 'Oktobar', 'Novembar', 'Decembar' ),
|
208 |
+
|
209 |
+
/* Slovak */
|
210 |
+
'sk' => array( 'Január', 'Február', 'Marec', 'Apríl', 'Máj', 'Jún', 'Júl', 'August', 'September', 'Október', 'November', 'December' ),
|
211 |
+
|
212 |
+
/* Slovenian */
|
213 |
+
'sl' => array( 'Januar', 'Februar', 'Marec', 'April', 'Maj', 'Junij', 'Julij', 'Avgust', 'September', 'Oktober', 'November', 'December' ),
|
214 |
+
|
215 |
+
/* Spanish */
|
216 |
+
'es' => array( 'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre' ),
|
217 |
+
|
218 |
+
/* Swedish */
|
219 |
+
'sv' => array( 'Januari', 'Februari', 'Mars', 'April', 'Maj', 'Juni', 'Juli', 'Augusti', 'September', 'Oktober', 'November', 'December' ),
|
220 |
+
|
221 |
+
/* Turkish */
|
222 |
+
'tr' => array( 'Ocak', 'Şubat', 'Mart', 'Nisan', 'Mayıs', 'Haziran', 'Temmuz', 'Ağustos', 'Eylül', 'Ekim', 'Kasım', 'Aralık' ),
|
223 |
+
|
224 |
+
/* Ukrainian */
|
225 |
+
'uk' => array( 'Січень', 'Лютий', 'Березень', 'Квітень', 'Травень', 'Червень', 'Липень', 'Серпень', 'Вересень', 'Жовтень', 'Листопад', 'Грудень' )
|
226 |
+
|
227 |
+
);
|
228 |
+
|
229 |
+
return ( ! empty( $month_names[$language_code][$month - 1] ) ? $month_names[$language_code][$month - 1] : $month_names['en'][$month - 1] );
|
230 |
+
|
231 |
+
}
|
includes/base/functions-utils.php
ADDED
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Sanitizes the values of an array recursivelly
|
9 |
+
*
|
10 |
+
* @param array $array
|
11 |
+
*
|
12 |
+
* @return array
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
function _wpsbc_array_sanitize_text_field( $array = array() ) {
|
16 |
+
|
17 |
+
if( empty( $array ) || ! is_array( $array ) )
|
18 |
+
return array();
|
19 |
+
|
20 |
+
foreach( $array as $key => $value ) {
|
21 |
+
|
22 |
+
if( is_array( $value ) )
|
23 |
+
$array[$key] = _wpsbc_array_sanitize_text_field( $value );
|
24 |
+
|
25 |
+
else
|
26 |
+
$array[$key] = sanitize_text_field( $value );
|
27 |
+
|
28 |
+
}
|
29 |
+
|
30 |
+
return $array;
|
31 |
+
|
32 |
+
}
|
33 |
+
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Sanitizes the values of an array recursivelly and allows HTML tags
|
37 |
+
*
|
38 |
+
* @param array $array
|
39 |
+
*
|
40 |
+
* @return array
|
41 |
+
*
|
42 |
+
*/
|
43 |
+
function _wpsbc_array_wp_kses_post( $array = array() ) {
|
44 |
+
|
45 |
+
if( empty( $array ) || ! is_array( $array ) )
|
46 |
+
return array();
|
47 |
+
|
48 |
+
foreach( $array as $key => $value ) {
|
49 |
+
|
50 |
+
if( is_array( $value ) )
|
51 |
+
$array[$key] = _wpsbc_array_wp_kses_post( $value );
|
52 |
+
|
53 |
+
else
|
54 |
+
$array[$key] = wp_kses_post( $value );
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
return $array;
|
59 |
+
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Returns the current locale
|
64 |
+
*
|
65 |
+
* @return string
|
66 |
+
*
|
67 |
+
*/
|
68 |
+
function wpsbc_get_locale() {
|
69 |
+
|
70 |
+
return substr( get_locale(), 0, 2 );
|
71 |
+
|
72 |
+
}
|
includes/base/functions.php
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Includes the Base files
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_include_files_base() {
|
12 |
+
|
13 |
+
// Get legend dir path
|
14 |
+
$dir_path = plugin_dir_path( __FILE__ );
|
15 |
+
|
16 |
+
// Include languages functions
|
17 |
+
if( file_exists( $dir_path . 'functions-languages.php' ) )
|
18 |
+
include $dir_path . 'functions-languages.php';
|
19 |
+
|
20 |
+
// Include utils functions
|
21 |
+
if( file_exists( $dir_path . 'functions-utils.php' ) )
|
22 |
+
include $dir_path . 'functions-utils.php';
|
23 |
+
|
24 |
+
// Include the shortcodes class
|
25 |
+
if( file_exists( $dir_path . 'class-shortcodes.php' ) )
|
26 |
+
include $dir_path . 'class-shortcodes.php';
|
27 |
+
|
28 |
+
// Include the widget class
|
29 |
+
if( file_exists( $dir_path . 'class-widget-calendar.php' ) )
|
30 |
+
include $dir_path . 'class-widget-calendar.php';
|
31 |
+
|
32 |
+
// Include the widget class
|
33 |
+
if( file_exists( $dir_path . 'class-widget-calendar-search.php' ) )
|
34 |
+
include $dir_path . 'class-widget-calendar-search.php';
|
35 |
+
|
36 |
+
}
|
37 |
+
add_action( 'wpsbc_include_files', 'wpsbc_include_files_base' );
|
38 |
+
|
39 |
+
|
40 |
+
/**
|
41 |
+
* Returns an array with the weekdays
|
42 |
+
*
|
43 |
+
* @return array
|
44 |
+
*
|
45 |
+
*/
|
46 |
+
function wpsbc_get_weekdays() {
|
47 |
+
|
48 |
+
$weekdays = array(
|
49 |
+
__( 'Monday', 'wp-simple-booking-calendar' ),
|
50 |
+
__( 'Tuesday', 'wp-simple-booking-calendar' ),
|
51 |
+
__( 'Wednesday', 'wp-simple-booking-calendar' ),
|
52 |
+
__( 'Thursday', 'wp-simple-booking-calendar' ),
|
53 |
+
__( 'Friday', 'wp-simple-booking-calendar' ),
|
54 |
+
__( 'Saturday', 'wp-simple-booking-calendar' ),
|
55 |
+
__( 'Sunday', 'wp-simple-booking-calendar' )
|
56 |
+
);
|
57 |
+
|
58 |
+
return $weekdays;
|
59 |
+
|
60 |
+
}
|
61 |
+
|
62 |
+
/**
|
63 |
+
* Returns true if there are any active languages in settings, false if not.
|
64 |
+
*
|
65 |
+
* @return bool
|
66 |
+
*
|
67 |
+
*/
|
68 |
+
function wpsbc_translations_active()
|
69 |
+
{
|
70 |
+
|
71 |
+
$settings = get_option('wpsbc_settings', array());
|
72 |
+
|
73 |
+
if (!isset($settings['active_languages'])) {
|
74 |
+
return false;
|
75 |
+
}
|
76 |
+
|
77 |
+
if (empty($settings['active_languages'])) {
|
78 |
+
return false;
|
79 |
+
}
|
80 |
+
|
81 |
+
return true;
|
82 |
+
|
83 |
+
}
|
includes/base/legend/class-legend-item.php
ADDED
@@ -0,0 +1,106 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* The main class for the Legend Item
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
class WPSBC_Legend_Item extends WPSBC_Base_Object {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* The Id of the legend item
|
15 |
+
*
|
16 |
+
* @access protected
|
17 |
+
* @var int
|
18 |
+
*
|
19 |
+
*/
|
20 |
+
protected $id;
|
21 |
+
|
22 |
+
/**
|
23 |
+
* The legend item type
|
24 |
+
*
|
25 |
+
* @access protected
|
26 |
+
* @var string
|
27 |
+
*
|
28 |
+
*/
|
29 |
+
protected $type;
|
30 |
+
|
31 |
+
/**
|
32 |
+
* The legend item name
|
33 |
+
*
|
34 |
+
* @access protected
|
35 |
+
* @var string
|
36 |
+
*
|
37 |
+
*/
|
38 |
+
protected $name;
|
39 |
+
|
40 |
+
/**
|
41 |
+
* The legend item background color list
|
42 |
+
*
|
43 |
+
* @access protected
|
44 |
+
* @var array
|
45 |
+
*
|
46 |
+
*/
|
47 |
+
protected $color;
|
48 |
+
|
49 |
+
/**
|
50 |
+
* The legend item text color
|
51 |
+
*
|
52 |
+
* @access protected
|
53 |
+
* @var string
|
54 |
+
*
|
55 |
+
*/
|
56 |
+
protected $color_text;
|
57 |
+
|
58 |
+
/**
|
59 |
+
* Bool value (0/1) to determine if the legend item is the default one
|
60 |
+
* for the legend
|
61 |
+
*
|
62 |
+
* @access protected
|
63 |
+
* @var int
|
64 |
+
*
|
65 |
+
*/
|
66 |
+
protected $is_default;
|
67 |
+
|
68 |
+
/**
|
69 |
+
* Bool value (0/1) to determine if the legend item is visible in the front-end
|
70 |
+
*
|
71 |
+
* @access protected
|
72 |
+
* @var int
|
73 |
+
*
|
74 |
+
*/
|
75 |
+
protected $is_visible;
|
76 |
+
|
77 |
+
/**
|
78 |
+
* The ID of the calendar for which the legend item is available
|
79 |
+
*
|
80 |
+
* @access protected
|
81 |
+
* @var int
|
82 |
+
*
|
83 |
+
*/
|
84 |
+
protected $calendar_id;
|
85 |
+
|
86 |
+
/**
|
87 |
+
* Returns the name property for the current object, or the translation for it
|
88 |
+
* if the the language code is provided and the translation for that language exists
|
89 |
+
*
|
90 |
+
* @param string $language_code
|
91 |
+
*
|
92 |
+
* @return string
|
93 |
+
*
|
94 |
+
*/
|
95 |
+
public function get_name( $language_code = '' ) {
|
96 |
+
|
97 |
+
if( empty( $language_code ) )
|
98 |
+
return $this->name;
|
99 |
+
|
100 |
+
$translation = wpsbc_get_legend_item_meta( $this->id, 'translation_' . $language_code, true );
|
101 |
+
|
102 |
+
return ( ! empty( $translation ) ? $translation : $this->name );
|
103 |
+
|
104 |
+
}
|
105 |
+
|
106 |
+
}
|
includes/base/legend/class-object-db-legend-items.php
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class that handles database queries for the Legend Items
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
Class WPSBC_Object_DB_Legend_Items extends WPSBC_Object_DB {
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Construct
|
15 |
+
*
|
16 |
+
*/
|
17 |
+
public function __construct() {
|
18 |
+
|
19 |
+
global $wpdb;
|
20 |
+
|
21 |
+
$this->table_name = $wpdb->prefix . 'wpsbc_legend_items';
|
22 |
+
$this->primary_key = 'id';
|
23 |
+
$this->context = 'legend_item';
|
24 |
+
$this->query_object_type = 'WPSBC_Legend_Item';
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Return the table columns
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
public function get_columns() {
|
34 |
+
|
35 |
+
return array(
|
36 |
+
'id' => '%d',
|
37 |
+
'type' => '%s',
|
38 |
+
'name' => '%s',
|
39 |
+
'color' => '%s',
|
40 |
+
'color_text' => '%s',
|
41 |
+
'is_default' => '%d',
|
42 |
+
'is_visible' => '%d',
|
43 |
+
'calendar_id' => '%d'
|
44 |
+
);
|
45 |
+
|
46 |
+
}
|
47 |
+
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Returns an array of WPSBC_Legend_Items objects from the database
|
51 |
+
*
|
52 |
+
* @param array $args
|
53 |
+
* @param bool $count - whether to return just the count for the query or not
|
54 |
+
*
|
55 |
+
* @return mixed array|int
|
56 |
+
*
|
57 |
+
*/
|
58 |
+
public function get_legend_items( $args = array(), $count = false ) {
|
59 |
+
|
60 |
+
$defaults = array(
|
61 |
+
'number' => -1,
|
62 |
+
'offset' => 0,
|
63 |
+
'orderby' => 'id',
|
64 |
+
'order' => 'ASC',
|
65 |
+
'calendar_id' => 0
|
66 |
+
);
|
67 |
+
|
68 |
+
$args = wp_parse_args( $args, $defaults );
|
69 |
+
|
70 |
+
// Number args
|
71 |
+
if( $args['number'] < 1 )
|
72 |
+
$args['number'] = 999999;
|
73 |
+
|
74 |
+
// Where clause
|
75 |
+
$where = '';
|
76 |
+
|
77 |
+
// Calendar ID where clause
|
78 |
+
if( ! empty( $args['calendar_id'] ) ) {
|
79 |
+
|
80 |
+
$calendar_id = absint( $args['calendar_id'] );
|
81 |
+
$where .= "WHERE calendar_id = {$calendar_id}";
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
// Is visible where clause
|
86 |
+
if( isset( $args['is_visible'] ) ) {
|
87 |
+
|
88 |
+
$is_visible = ( ! empty( $args['is_visible'] ) ? 1 : 0 );
|
89 |
+
$where .= " AND is_visible = {$is_visible}";
|
90 |
+
|
91 |
+
}
|
92 |
+
|
93 |
+
// Is default where clause
|
94 |
+
if( isset( $args['is_default'] ) ) {
|
95 |
+
|
96 |
+
$is_default = ( ! empty( $args['is_default'] ) ? 1 : 0 );
|
97 |
+
$where .= " AND is_default = {$is_default}";
|
98 |
+
|
99 |
+
}
|
100 |
+
|
101 |
+
$where .= " AND type = 'single'";
|
102 |
+
|
103 |
+
// Orderby
|
104 |
+
$orderby = sanitize_text_field( $args['orderby'] );
|
105 |
+
|
106 |
+
// Order
|
107 |
+
$order = ( 'DESC' === strtoupper( $args['order'] ) ? 'DESC' : 'ASC' );
|
108 |
+
|
109 |
+
$clauses = compact( 'where', 'orderby', 'order', 'count' );
|
110 |
+
|
111 |
+
$results = $this->get_results( $clauses, $args, 'wpsbc_get_legend_item' );
|
112 |
+
|
113 |
+
/**
|
114 |
+
* Filter the legend items results just before returning
|
115 |
+
*
|
116 |
+
* @param array $results
|
117 |
+
* @param array $args
|
118 |
+
* @param bool $count
|
119 |
+
*
|
120 |
+
*/
|
121 |
+
$results = apply_filters( 'wpsbc_get_legend_items', $results, $args, $count );
|
122 |
+
|
123 |
+
return $results;
|
124 |
+
|
125 |
+
}
|
126 |
+
|
127 |
+
|
128 |
+
/**
|
129 |
+
* Creates and updates the database table for the legend items
|
130 |
+
*
|
131 |
+
*/
|
132 |
+
public function create_table() {
|
133 |
+
|
134 |
+
global $wpdb;
|
135 |
+
|
136 |
+
$table_name = $this->table_name;
|
137 |
+
$charset_collate = $wpdb->get_charset_collate();
|
138 |
+
|
139 |
+
$query = "CREATE TABLE {$table_name} (
|
140 |
+
id bigint(10) NOT NULL AUTO_INCREMENT,
|
141 |
+
type varchar(255) NOT NULL,
|
142 |
+
name text NOT NULL,
|
143 |
+
color text NOT NULL,
|
144 |
+
color_text text,
|
145 |
+
is_default tinyint(1) NOT NULL,
|
146 |
+
is_visible tinyint(1) NOT NULL,
|
147 |
+
calendar_id bigint(10) NOT NULL,
|
148 |
+
PRIMARY KEY id (id)
|
149 |
+
) {$charset_collate};";
|
150 |
+
|
151 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
152 |
+
dbDelta( $query );
|
153 |
+
|
154 |
+
}
|
155 |
+
|
156 |
+
}
|
includes/base/legend/class-object-meta-db-legend-items.php
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class that handles database queries for the Legend Items
|
8 |
+
*
|
9 |
+
*/
|
10 |
+
Class WPSBC_Object_Meta_DB_Legend_Items extends WPSBC_Object_Meta_DB {
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Construct
|
14 |
+
*
|
15 |
+
*/
|
16 |
+
public function __construct() {
|
17 |
+
|
18 |
+
global $wpdb;
|
19 |
+
|
20 |
+
$this->table_name = $wpdb->prefix . 'wpsbc_legend_item_meta';
|
21 |
+
$this->primary_key = 'legend_item_id';
|
22 |
+
$this->context = 'legend_item';
|
23 |
+
|
24 |
+
add_action( 'plugins_loaded', array( $this, 'register_wpdb_column' ) );
|
25 |
+
|
26 |
+
}
|
27 |
+
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Register the meta table for the legend items with the $wpdb global
|
31 |
+
*
|
32 |
+
*/
|
33 |
+
public function register_wpdb_column() {
|
34 |
+
|
35 |
+
global $wpdb;
|
36 |
+
|
37 |
+
$meta_table_name = $this->context . 'meta';
|
38 |
+
$wpdb->{$meta_table_name} = $this->table_name;
|
39 |
+
|
40 |
+
}
|
41 |
+
|
42 |
+
|
43 |
+
/**
|
44 |
+
* Return the table columns
|
45 |
+
*
|
46 |
+
*/
|
47 |
+
public function get_columns() {
|
48 |
+
|
49 |
+
return array(
|
50 |
+
'meta_id' => '%d',
|
51 |
+
'legend_item_id' => '%d',
|
52 |
+
'meta_key' => '%s',
|
53 |
+
'meta_value' => '%s'
|
54 |
+
);
|
55 |
+
|
56 |
+
}
|
57 |
+
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Creates and updates the database table for the legend items
|
61 |
+
*
|
62 |
+
*/
|
63 |
+
public function create_table() {
|
64 |
+
|
65 |
+
global $wpdb;
|
66 |
+
|
67 |
+
$table_name = $this->table_name;
|
68 |
+
$charset_collate = $wpdb->get_charset_collate();
|
69 |
+
|
70 |
+
$query = "CREATE TABLE {$table_name} (
|
71 |
+
meta_id bigint(20) NOT NULL AUTO_INCREMENT,
|
72 |
+
legend_item_id bigint(20) NOT NULL DEFAULT '0',
|
73 |
+
meta_key varchar(255) DEFAULT NULL,
|
74 |
+
meta_value longtext,
|
75 |
+
PRIMARY KEY (meta_id),
|
76 |
+
KEY legend_item_id (legend_item_id),
|
77 |
+
KEY meta_key (meta_key(191))
|
78 |
+
) {$charset_collate};";
|
79 |
+
|
80 |
+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
|
81 |
+
dbDelta( $query );
|
82 |
+
|
83 |
+
}
|
84 |
+
|
85 |
+
}
|
includes/base/legend/functions.php
ADDED
@@ -0,0 +1,387 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
// Exit if accessed directly
|
4 |
+
if ( ! defined( 'ABSPATH' ) ) exit;
|
5 |
+
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Includes the files needed for the Legend items
|
9 |
+
*
|
10 |
+
*/
|
11 |
+
function wpsbc_include_files_legend() {
|
12 |
+
|
13 |
+
// Get legend dir path
|
14 |
+
$dir_path = plugin_dir_path( __FILE__ );
|
15 |
+
|
16 |
+
// Include main Legend Item class
|
17 |
+
if( file_exists( $dir_path . 'class-legend-item.php' ) )
|
18 |
+
include $dir_path . 'class-legend-item.php';
|
19 |
+
|
20 |
+
// Include the db layer classes
|
21 |
+
if( file_exists( $dir_path . 'class-object-db-legend-items.php' ) )
|
22 |
+
include $dir_path . 'class-object-db-legend-items.php';
|
23 |
+
|
24 |
+
if( file_exists( $dir_path . 'class-object-meta-db-legend-items.php' ) )
|
25 |
+
include $dir_path . 'class-object-meta-db-legend-items.php';
|
26 |
+
|
27 |
+
}
|
28 |
+
add_action( 'wpsbc_include_files', 'wpsbc_include_files_legend' );
|
29 |
+
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Register the class that handles database queries for the Legend Items
|
33 |
+
*
|
34 |
+
* @param array $classes
|
35 |
+
*
|
36 |
+
* @return array
|
37 |
+
*
|
38 |
+
*/
|
39 |
+
function wpsbc_register_database_classes_legend( $classes ) {
|
40 |
+
|
41 |
+
$classes['legend_items'] = 'WPSBC_Object_DB_Legend_Items';
|
42 |
+
$classes['legend_itemmeta'] = 'WPSBC_Object_Meta_DB_Legend_Items';
|
43 |
+
|
44 |
+
return $classes;
|
45 |
+
|
46 |
+
}
|
47 |
+
add_filter( 'wpsbc_register_database_classes', 'wpsbc_register_database_classes_legend' );
|
48 |
+
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Returns an array with WPSBC_Legend_Items objects from the database
|
52 |
+
*
|
53 |
+
* @param array $args
|
54 |
+
* @param bool $count
|
55 |
+
*
|
56 |
+
* @return array
|
57 |
+
*
|
58 |
+
*/
|
59 |
+
function wpsbc_get_legend_items( $args = array(), $count = false ) {
|
60 |
+
|
61 |
+
return wp_simple_booking_calendar()->db['legend_items']->get_legend_items( $args, $count );
|
62 |
+
|
63 |
+
}
|
64 |
+
|
65 |
+
|
66 |
+
/**
|
67 |
+
* Gets a legend item from the database
|
68 |
+
*
|
69 |
+
* @param int $legend_item_id
|
70 |
+
*
|
71 |
+
* @return WPSBC_Legend_Item|false
|
72 |
+
*
|
73 |
+
*/
|
74 |
+
function wpsbc_get_legend_item( $legend_item_id ) {
|
75 |
+
|
76 |
+
return wp_simple_booking_calendar()->db['legend_items']->get_object( $legend_item_id );
|
77 |
+
|
78 |
+
}
|
79 |
+
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Inserts a new legend item into the database
|
83 |
+
*
|
84 |
+
* @param array $data
|
85 |
+
*
|
86 |
+
* @return mixed int|false
|
87 |
+
*
|
88 |
+
*/
|
89 |
+
function wpsbc_insert_legend_item( $data ) {
|
90 |
+
|
91 |
+
return wp_simple_booking_calendar()->db['legend_items']->insert( $data );
|
92 |
+
|
93 |
+
}
|
94 |
+
|
95 |
+
/**
|
96 |
+
* Updates a legend item from the database
|
97 |
+
*
|
98 |
+
* @param int $legend_item_id
|
99 |
+
* @param array $data
|
100 |
+
*
|
101 |
+
* @return bool
|
102 |
+
*
|
103 |
+
*/
|
104 |
+
function wpsbc_update_legend_item( $legend_item_id, $data ) {
|
105 |
+
|
106 |
+
return wp_simple_booking_calendar()->db['legend_items']->update( $legend_item_id, $data );
|
107 |
+
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Deletes a legend item from the database
|
112 |
+
*
|
113 |
+
* @param int $legend_item_id
|
114 |
+
*
|
115 |
+
* @return bool
|
116 |
+
*
|
117 |
+
*/
|
118 |
+
function wpsbc_delete_legend_item( $legend_item_id ) {
|
119 |
+
|
120 |
+
return wp_simple_booking_calendar()->db['legend_items']->delete( $legend_item_id );
|
121 |
+
|
122 |
+
}
|
123 |
+
|
124 |
+
/**
|
125 |
+
* Inserts a new meta entry for the legend item
|
126 |
+
*
|
127 |
+
* @param int $legend_item_id
|
128 |
+
* @param string $meta_key
|
129 |
+
* @param string $meta_value
|
130 |
+
* @param bool $unique
|
131 |
+
*
|
132 |
+
* @return mixed int|false
|
133 |
+
*
|
134 |
+
*/
|
135 |
+
function wpsbc_add_legend_item_meta( $legend_item_id, $meta_key, $meta_value, $unique = false ) {
|
136 |
+
|
137 |
+
return wp_simple_booking_calendar()->db['legend_itemmeta']->add( $legend_item_id, $meta_key, $meta_value, $unique );
|
138 |
+
|
139 |
+
}
|
140 |
+
|
141 |
+
/**
|
142 |
+
* Updates a meta entry for the legend item
|
143 |
+
*
|
144 |
+
* @param int $legend_item_id
|
145 |
+
* @param string $meta_key
|
146 |
+
* @param string $meta_value
|
147 |
+
* @param bool $prev_value
|
148 |
+
*
|
149 |
+
* @return bool
|
150 |
+
*
|
151 |
+
*/
|
152 |
+
function wpsbc_update_legend_item_meta( $legend_item_id, $meta_key, $meta_value, $prev_value = '' ) {
|
153 |
+
|
154 |
+
return wp_simple_booking_calendar()->db['legend_itemmeta']->update( $legend_item_id, $meta_key, $meta_value, $prev_value );
|
155 |
+
|
156 |
+
}
|
157 |
+
|
158 |
+
/**
|
159 |
+
* Returns a meta entry for the legend item
|
160 |
+
*
|
161 |
+
* @param int $legend_item_id
|
162 |
+
* @param string $meta_key
|
163 |
+
* @param bool $single
|
164 |
+
*
|
165 |
+
* @return mixed
|
166 |
+
*
|
167 |
+
*/
|
168 |
+
function wpsbc_get_legend_item_meta( $legend_item_id, $meta_key = '', $single = false ) {
|
169 |
+
|
170 |
+
return wp_simple_booking_calendar()->db['legend_itemmeta']->get( $legend_item_id, $meta_key, $single );
|
171 |
+
|
172 |
+
}
|
173 |
+
|
174 |
+
/**
|
175 |
+
* Removes a meta entry for the legend item
|
176 |
+
*
|
177 |
+
* @param int $legend_item_id
|
178 |
+
* @param string $meta_key
|
179 |
+
* @param string $meta_value
|
180 |
+
* @param bool $delete_all
|
181 |
+
*
|
182 |
+
* @return bool
|
183 |
+
*
|
184 |
+
*/
|
185 |
+
function wpsbc_delete_legend_item_meta( $legend_item_id, $meta_key, $meta_value = '', $delete_all = '' ) {
|
186 |
+
|
187 |
+
return wp_simple_booking_calendar()->db['legend_itemmeta']->delete( $legend_item_id, $meta_key, $meta_value, $delete_all );
|
188 |
+
|
189 |
+
}
|
190 |
+
|
191 |
+
|
192 |
+
/**
|
193 |
+
* Returns an array with the default legend items
|
194 |
+
*
|
195 |
+
* @return array
|
196 |
+
*
|
197 |
+
*/
|
198 |
+
function wpsbc_get_default_legend_items_data() {
|
199 |
+
|
200 |
+
$legend_items_data = array(
|
201 |
+
array(
|
202 |
+
'name' => __( 'Available', 'wp-simple-booking-calendar' ),
|
203 |
+
'type' => 'single',
|
204 |
+
'color' => array( '#ddffcc' ),
|
205 |
+
'is_visible' => 1,
|
206 |
+
'is_default' => 1,
|
207 |
+
'translations' => array(
|
208 |
+
'en' => 'Available',
|
209 |
+
'bg' => 'Свободен',
|
210 |
+
'ca' => 'Disponible',
|
211 |
+
'hr' => 'Dostupno',
|
212 |
+
'cz' => 'Dostupný',
|
213 |
+
'da' => 'Ledig',
|
214 |
+
'nl' => 'Beschikbaar',
|
215 |
+
'et' => 'Saadaval',
|
216 |
+
'fi' => 'Käytettävissä',
|
217 |
+
'fr' => 'Disponible',
|
218 |
+
'gl' => 'Dispoñible',
|
219 |
+
'de' => 'Verfügbar',
|
220 |
+
'el' => 'Διαθέσιμος',
|
221 |
+
'hu' => 'Elérhető',
|
222 |
+
'it' => 'Disponibile',
|
223 |
+
'jp' => '利用可能',
|
224 |
+
'lt' => 'Yra',
|
225 |
+
'no' => 'Tilgjengelig',
|
226 |
+
'pl' => 'Dostępny',
|
227 |
+
'pt' => 'Disponível',
|
228 |
+
'ro' => 'Disponibil',
|
229 |
+
'ru' => 'Доступный',
|
230 |
+
'sr' => 'Доступан',
|
231 |
+
'sk' => 'Dostupný',
|
232 |
+
'sl' => 'Veljaven',
|
233 |
+
'es' => 'Disponible',
|
234 |
+
'sv' => 'Tillgängliga',
|
235 |
+
'tr' => 'Mevcut',
|
236 |
+
'ua' => 'Доступні',
|
237 |
+
),
|
238 |
+
),
|
239 |
+
array(
|
240 |
+
'name' => __( 'Booked', 'wp-simple-booking-calendar' ),
|
241 |
+
'type' => 'single',
|
242 |
+
'color' => array( '#ffc0bd' ),
|
243 |
+
'is_visible' => 1,
|
244 |
+
'translations' => array(
|
245 |
+
'en' => 'Booked',
|
246 |
+
'bg' => 'Резервирано',
|
247 |
+
'ca' => 'Reservat',
|
248 |
+
'hr' => 'Rezerviran',
|
249 |
+
'cs' => 'Rezervováno',
|
250 |
+
'da' => 'Reserveret',
|
251 |
+
'nl' => 'Geboekt',
|
252 |
+
'et' => 'Broneeritud',
|
253 |
+
'fi' => 'Varattu',
|
254 |
+
'fr' => 'Réservé',
|
255 |
+
'gl' => 'Reservado',
|
256 |
+
'de' => 'Gebucht',
|
257 |
+
'el' => 'Κράτηση',
|
258 |
+
'hu' => 'Foglalt',
|
259 |
+
'it' => 'Riservato',
|
260 |
+
'jp' => '予約済み',
|
261 |
+
'lt' => 'Užsakyta',
|
262 |
+
'no' => 'Bestilt',
|
263 |
+
'pl' => 'Zarezerwowane',
|
264 |
+
'pt' => 'Reservado',
|
265 |
+
'ro' => 'Rezervat',
|
266 |
+
'ru' => 'Бронирования',
|
267 |
+
'sr' => 'Резервисан',
|
268 |
+
'sk' => 'Rezervovaný',
|
269 |
+
'sl' => 'Rezervirano',
|
270 |
+
'es' => 'Reservado',
|
271 |
+
'sv' => 'Bokad',
|
272 |
+
'tr' => 'Rezervasyon',
|
273 |
+
'ua' => 'Забронювали',
|
274 |
+
),
|
275 |
+
),
|
276 |
+
array(
|
277 |
+
'name' => __( 'Changeover', 'wp-simple-booking-calendar' ),
|
278 |
+
'type' => 'single',
|
279 |
+
'color' => array( '#fee2a0' ),
|
280 |
+
'is_visible' => 1,
|
281 |
+
'translations' => array(
|
282 |
+
'en' => 'Changeover',
|
283 |
+
'bg' => 'смяна',
|
284 |
+
'ca' => 'Canvi',
|
285 |
+
'hr' => 'Prebacivanje',
|
286 |
+
'cs' => 'Přechod',
|
287 |
+
'da' => 'Skiftedag',
|
288 |
+
'nl' => 'Omschakeling',
|
289 |
+
'et' => 'Üleminek',
|
290 |
+
'fi' => 'Siirtyminen',
|
291 |
+
'fr' => 'Passage',
|
292 |
+
'gl' => 'Cambio',
|
293 |
+
'de' => 'Umstellung',
|
294 |
+
'el' => 'Εναλλαγή',
|
295 |
+
'hu' => 'Átállás',
|
296 |
+
'it' => 'Passaggio',
|
297 |
+
'jp' => '切り替え',
|
298 |
+
'lt' => 'Euro įvedimas',
|
299 |
+
'no' => 'Ankomst',
|
300 |
+
'pl' => 'Przełączenie',
|
301 |
+
'pt' => 'Mudança',
|
302 |
+
'ro' => 'Schimbare',
|
303 |
+
'ru' => 'переналадка',
|
304 |
+
'sr' => 'Промјена',
|
305 |
+
'sk' => 'Zmena',
|
306 |
+
'sl' => 'Zamenjava',
|
307 |
+
'es' => 'Cambio',
|
308 |
+
'sv' => 'Övergång',
|
309 |
+
'tr' => 'Değiştirme',
|
310 |
+
'ua' => 'Перехід',
|
311 |
+
),
|
312 |
+
),
|
313 |
+
array(
|
314 |
+
'name' => __( 'Changeover 1', 'wp-simple-booking-calendar' ),
|
315 |
+
'type' => 'split',
|
316 |
+
'color' => array( '#ddffcc', '#ffc0bd' ),
|
317 |
+
'is_visible' => 0
|
318 |
+
),
|
319 |
+
array(
|
320 |
+
'name' => __( 'Changeover 2', 'wp-simple-booking-calendar' ),
|
321 |
+
'type' => 'split',
|
322 |
+
'color' => array( '#ffc0bd', '#ddffcc' ),
|
323 |
+
'is_visible' => 0
|
324 |
+
)
|
325 |
+
);
|
326 |
+
|
327 |
+
return $legend_items_data;
|
328 |
+
|
329 |
+
}
|
330 |
+
|
331 |
+
|
332 |
+
/**
|
333 |
+
* Modifies the order of the legend items when being called through the DB Legend Items object
|
334 |
+
* to match the order saved in the calendar meta table under the "legend_items_sort_order" key
|
335 |
+
*
|
336 |
+
* @param array $results
|
337 |
+
* @param array $args
|
338 |
+
* @param bool $count
|
339 |
+
*
|
340 |
+
* @return array
|
341 |
+
*
|
342 |
+
*/
|
343 |
+
function wpsbc_get_legend_items_filter_by_order( $results, $args, $count = false ) {
|
344 |
+
|
345 |
+
if( true === $count )
|
346 |
+
return $results;
|
347 |
+
|
348 |
+
if( empty( $args['calendar_id'] ) )
|
349 |
+
return $results;
|
350 |
+
|
351 |
+
$legend_items_sort_order = wpsbc_get_calendar_meta( $args['calendar_id'], 'legend_items_sort_order', true );
|
352 |
+
|
353 |
+
|
354 |
+
if( empty( $legend_items_sort_order ) || ! is_array( $legend_items_sort_order ) )
|
355 |
+
return $results;
|
356 |
+
|
357 |
+
// New results array
|
358 |
+
$new_results = array();
|
359 |
+
|
360 |
+
// Go through each legend item id in the order list and place the legend item object
|
361 |
+
// with the corresponding id in the new results array
|
362 |
+
foreach( $legend_items_sort_order as $legend_item_id ) {
|
363 |
+
|
364 |
+
foreach( $results as $legend_item ) {
|
365 |
+
|
366 |
+
if( $legend_item->get('id') == $legend_item_id )
|
367 |
+
$new_results[$legend_item_id] = $legend_item;
|
368 |
+
|
369 |
+
}
|
370 |
+
|
371 |
+
}
|
372 |
+
|
373 |
+
// Go through each results and add to the new results array the legend item objects
|
374 |
+
// that did not have the id in the legend items sort order
|
375 |
+
foreach( $results as $legend_item ) {
|
376 |
+
|
377 |
+
if( ! in_array( $legend_item->get('id'), array_keys( $new_results ) ) )
|
378 |
+
$new_results[$legend_item->get('id')] = $legend_item;
|
379 |
+
|
380 |
+
}
|
381 |
+
|
382 |
+
$results = array_values( $new_results );
|
383 |
+
|
384 |
+
return $results;
|
385 |
+
|
386 |
+
}
|
387 |
+
add_filter( 'wpsbc_get_legend_items', 'wpsbc_get_legend_items_filter_by_order', 10, 3 );
|
includes/libs/iCal/iCalcreator.php
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* A PHP implementation of rfc2445/rfc5545.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22.1
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/**
|
29 |
+
* iCalcreator.php
|
30 |
+
*
|
31 |
+
* iCalcreator (class) files includes
|
32 |
+
*
|
33 |
+
* @package icalcreator
|
34 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
35 |
+
* @since 2.22.1 - 2015-06-06
|
36 |
+
*/
|
37 |
+
/*********************************************************************************/
|
38 |
+
/**
|
39 |
+
* Do NOT remove or change version!!
|
40 |
+
*/
|
41 |
+
|
42 |
+
// ini_set('display_errors', 0);
|
43 |
+
// ini_set('display_errors', 'Off');
|
44 |
+
define( 'ICALCREATOR_VERSION', 'iCalcreator 2.22.1' );
|
45 |
+
/*********************************************************************************/
|
46 |
+
if( !defined( 'ICALCREATOR_LIB_DIR' ))
|
47 |
+
define( 'ICALCREATOR_LIB_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR );
|
48 |
+
/**
|
49 |
+
* iCalLoader
|
50 |
+
*
|
51 |
+
* load iCalcreator src and util classes
|
52 |
+
*
|
53 |
+
* @param string $class
|
54 |
+
* @return void
|
55 |
+
*/
|
56 |
+
function iCalLoader( $class ) {
|
57 |
+
$file = ICALCREATOR_LIB_DIR . $class . '.class.php';
|
58 |
+
if( file_exists( $file ))
|
59 |
+
include $file;
|
60 |
+
}
|
61 |
+
spl_autoload_register( 'iCalLoader' );
|
62 |
+
/**
|
63 |
+
* iCalcreator add-on functionality functions
|
64 |
+
*/
|
65 |
+
include ICALCREATOR_LIB_DIR . 'iCal.XML.inc.php';
|
66 |
+
include ICALCREATOR_LIB_DIR . 'iCal.vCard.inc.php';
|
67 |
+
include ICALCREATOR_LIB_DIR . 'iCal.tz.inc.php';
|
includes/libs/iCal/lib/calendarComponent.class.php
ADDED
@@ -0,0 +1,4661 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* abstract class for calendar components
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.2.11 - 2015-03-31
|
34 |
+
*/
|
35 |
+
class calendarComponent extends iCalBase {
|
36 |
+
/** @var array component property UID value */
|
37 |
+
protected $uid;
|
38 |
+
/** @var array component property DTSTAMP value */
|
39 |
+
protected $dtstamp;
|
40 |
+
/** @var string component type */
|
41 |
+
public $objName;
|
42 |
+
/**
|
43 |
+
* constructor for calendar component object
|
44 |
+
*
|
45 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
46 |
+
* @since 2.9.6 - 2011-05-17
|
47 |
+
* @uses calendarComponent::$objName
|
48 |
+
* @uses calendarComponent::$timezonetype
|
49 |
+
* @uses calendarComponent::$uid
|
50 |
+
* @uses calendarComponent::$dtstamp
|
51 |
+
* @uses calendarComponent::$language
|
52 |
+
* @uses calendarComponent::$nl
|
53 |
+
* @uses calendarComponent::$unique_id
|
54 |
+
* @uses calendarComponent::$format
|
55 |
+
* @uses calendarComponent::$dtzid
|
56 |
+
* @uses calendarComponent::$allowEmpty
|
57 |
+
* @uses calendarComponent::$xcaldecl
|
58 |
+
* @uses calendarComponent::_createFormat()
|
59 |
+
* @uses calendarComponent::_makeDtstamp()
|
60 |
+
*/
|
61 |
+
function component() {
|
62 |
+
$this->objName = ( isset( $this->timezonetype )) ?
|
63 |
+
strtolower( $this->timezonetype ) : get_class ( $this );
|
64 |
+
$this->uid = array();
|
65 |
+
$this->dtstamp = array();
|
66 |
+
|
67 |
+
$this->language = null;
|
68 |
+
$this->nl = null;
|
69 |
+
$this->unique_id = null;
|
70 |
+
$this->format = null;
|
71 |
+
$this->dtzid = null;
|
72 |
+
$this->allowEmpty = TRUE;
|
73 |
+
$this->xcaldecl = array();
|
74 |
+
|
75 |
+
$this->_createFormat();
|
76 |
+
$this->_makeDtstamp();
|
77 |
+
}
|
78 |
+
/*********************************************************************************/
|
79 |
+
/**
|
80 |
+
* Property Name: ACTION
|
81 |
+
*/
|
82 |
+
/**
|
83 |
+
* creates formatted output for calendar component property action
|
84 |
+
*
|
85 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
86 |
+
* @since 2.4.8 - 2008-10-22
|
87 |
+
* @uses calendarComponent::$action
|
88 |
+
* @uses calendarComponent::getConfig()
|
89 |
+
* @uses calendarComponent::_createElement()
|
90 |
+
* @uses calendarComponent::_createParams()
|
91 |
+
* @uses calendarComponent::_createElement()
|
92 |
+
* @return string
|
93 |
+
*/
|
94 |
+
function createAction() {
|
95 |
+
if( empty( $this->action )) return FALSE;
|
96 |
+
if( empty( $this->action['value'] ))
|
97 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'ACTION' ) : FALSE;
|
98 |
+
$attributes = $this->_createParams( $this->action['params'] );
|
99 |
+
return $this->_createElement( 'ACTION', $attributes, $this->action['value'] );
|
100 |
+
}
|
101 |
+
/**
|
102 |
+
* set calendar component property action
|
103 |
+
*
|
104 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
105 |
+
* @since 2.16.21 - 2013-06-23
|
106 |
+
* @param string $value "AUDIO" / "DISPLAY" / "EMAIL" / "PROCEDURE"
|
107 |
+
* @param mixed $params
|
108 |
+
* @uses calendarComponent::getConfig()
|
109 |
+
* @uses calendarComponent::$action
|
110 |
+
* @uses calendarComponent::$action
|
111 |
+
* @uses iCalUtilityFunctions::_setParams()
|
112 |
+
* @return bool
|
113 |
+
*/
|
114 |
+
function setAction( $value, $params=FALSE ) {
|
115 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
116 |
+
$this->action = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
117 |
+
return TRUE;
|
118 |
+
}
|
119 |
+
/*********************************************************************************/
|
120 |
+
/**
|
121 |
+
* Property Name: ATTACH
|
122 |
+
*/
|
123 |
+
/**
|
124 |
+
* creates formatted output for calendar component property attach
|
125 |
+
*
|
126 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
127 |
+
* @since 2.11.16 - 2012-02-04
|
128 |
+
* @uses calendarComponent::$attach
|
129 |
+
* @uses calendarComponent::_createParams()
|
130 |
+
* @uses calendarComponent::$format
|
131 |
+
* @uses calendarComponent::$intAttrDelimiter
|
132 |
+
* @uses calendarComponent::$attributeDelimiter
|
133 |
+
* @uses calendarComponent::$valueInit
|
134 |
+
* @uses calendarComponent::$nl
|
135 |
+
* @uses calendarComponent::_createElement()
|
136 |
+
* @return string
|
137 |
+
*/
|
138 |
+
function createAttach() {
|
139 |
+
if( empty( $this->attach )) return FALSE;
|
140 |
+
$output = null;
|
141 |
+
foreach( $this->attach as $attachPart ) {
|
142 |
+
if( !empty( $attachPart['value'] )) {
|
143 |
+
$attributes = $this->_createParams( $attachPart['params'] );
|
144 |
+
if(( 'xcal' != $this->format ) && isset( $attachPart['params']['VALUE'] ) && ( 'BINARY' == $attachPart['params']['VALUE'] )) {
|
145 |
+
$attributes = str_replace( $this->intAttrDelimiter, $this->attributeDelimiter, $attributes );
|
146 |
+
$str = 'ATTACH'.$attributes.$this->valueInit.$attachPart['value'];
|
147 |
+
$output = substr( $str, 0, 75 ).$this->nl;
|
148 |
+
$str = substr( $str, 75 );
|
149 |
+
$output .= ' '.chunk_split( $str, 74, $this->nl.' ' );
|
150 |
+
if( ' ' == substr( $output, -1 ))
|
151 |
+
$output = rtrim( $output );
|
152 |
+
if( $this->nl != substr( $output, ( 0 - strlen( $this->nl ))))
|
153 |
+
$output .= $this->nl;
|
154 |
+
return $output;
|
155 |
+
}
|
156 |
+
$output .= $this->_createElement( 'ATTACH', $attributes, $attachPart['value'] );
|
157 |
+
}
|
158 |
+
elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'ATTACH' );
|
159 |
+
}
|
160 |
+
return $output;
|
161 |
+
}
|
162 |
+
/**
|
163 |
+
* set calendar component property attach
|
164 |
+
*
|
165 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
166 |
+
* @since 2.16.21 - 2013-06-23
|
167 |
+
* @param string $value
|
168 |
+
* @param array $params
|
169 |
+
* @param integer $index
|
170 |
+
* @uses calendarComponent::$attach
|
171 |
+
* @uses calendarComponent::getConfig()
|
172 |
+
* @uses iCalUtilityFunctions::_setMval()
|
173 |
+
* @return bool
|
174 |
+
*/
|
175 |
+
function setAttach( $value, $params=FALSE, $index=FALSE ) {
|
176 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
177 |
+
iCalUtilityFunctions::_setMval( $this->attach, $value, $params, FALSE, $index );
|
178 |
+
return TRUE;
|
179 |
+
}
|
180 |
+
/*********************************************************************************/
|
181 |
+
/**
|
182 |
+
* Property Name: ATTENDEE
|
183 |
+
*/
|
184 |
+
/**
|
185 |
+
* creates formatted output for calendar component property attendee
|
186 |
+
*
|
187 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
188 |
+
* @since 2.11.12 - 2012-01-31
|
189 |
+
* @uses calendarComponent::$attendee
|
190 |
+
* @uses calendarComponent::getConfig()
|
191 |
+
* @uses calendarComponent::_createElement()
|
192 |
+
* @uses calendarComponent::$intAttrDelimiter
|
193 |
+
* @return string
|
194 |
+
*/
|
195 |
+
function createAttendee() {
|
196 |
+
if( empty( $this->attendee )) return FALSE;
|
197 |
+
$output = null;
|
198 |
+
foreach( $this->attendee as $attendeePart ) { // start foreach 1
|
199 |
+
if( empty( $attendeePart['value'] )) {
|
200 |
+
if( $this->getConfig( 'allowEmpty' ))
|
201 |
+
$output .= $this->_createElement( 'ATTENDEE' );
|
202 |
+
continue;
|
203 |
+
}
|
204 |
+
$attendee1 = $attendee2 = null;
|
205 |
+
foreach( $attendeePart as $paramlabel => $paramvalue ) { // start foreach 2
|
206 |
+
if( 'value' == $paramlabel )
|
207 |
+
$attendee2 .= $paramvalue;
|
208 |
+
elseif(( 'params' == $paramlabel ) && ( is_array( $paramvalue ))) { // start elseif
|
209 |
+
$mParams = array( 'MEMBER', 'DELEGATED-TO', 'DELEGATED-FROM' );
|
210 |
+
foreach( $paramvalue as $pKey => $pValue ) { // fix (opt) quotes
|
211 |
+
if( is_array( $pValue ) || in_array( $pKey, $mParams ))
|
212 |
+
continue;
|
213 |
+
if(( FALSE !== strpos( $pValue, ':' )) ||
|
214 |
+
( FALSE !== strpos( $pValue, ';' )) ||
|
215 |
+
( FALSE !== strpos( $pValue, ',' )))
|
216 |
+
$paramvalue[$pKey] = '"'.$pValue.'"';
|
217 |
+
}
|
218 |
+
// set attenddee parameters in rfc2445 order
|
219 |
+
if( isset( $paramvalue['CUTYPE'] ))
|
220 |
+
$attendee1 .= $this->intAttrDelimiter.'CUTYPE='.$paramvalue['CUTYPE'];
|
221 |
+
if( isset( $paramvalue['MEMBER'] )) {
|
222 |
+
$attendee1 .= $this->intAttrDelimiter.'MEMBER=';
|
223 |
+
foreach( $paramvalue['MEMBER'] as $cix => $opv )
|
224 |
+
$attendee1 .= ( $cix ) ? ',"'.$opv.'"' : '"'.$opv.'"' ;
|
225 |
+
}
|
226 |
+
if( isset( $paramvalue['ROLE'] ))
|
227 |
+
$attendee1 .= $this->intAttrDelimiter.'ROLE='.$paramvalue['ROLE'];
|
228 |
+
if( isset( $paramvalue['PARTSTAT'] ))
|
229 |
+
$attendee1 .= $this->intAttrDelimiter.'PARTSTAT='.$paramvalue['PARTSTAT'];
|
230 |
+
if( isset( $paramvalue['RSVP'] ))
|
231 |
+
$attendee1 .= $this->intAttrDelimiter.'RSVP='.$paramvalue['RSVP'];
|
232 |
+
if( isset( $paramvalue['DELEGATED-TO'] )) {
|
233 |
+
$attendee1 .= $this->intAttrDelimiter.'DELEGATED-TO=';
|
234 |
+
foreach( $paramvalue['DELEGATED-TO'] as $cix => $opv )
|
235 |
+
$attendee1 .= ( $cix ) ? ',"'.$opv.'"' : '"'.$opv.'"' ;
|
236 |
+
}
|
237 |
+
if( isset( $paramvalue['DELEGATED-FROM'] )) {
|
238 |
+
$attendee1 .= $this->intAttrDelimiter.'DELEGATED-FROM=';
|
239 |
+
foreach( $paramvalue['DELEGATED-FROM'] as $cix => $opv )
|
240 |
+
$attendee1 .= ( $cix ) ? ',"'.$opv.'"' : '"'.$opv.'"' ;
|
241 |
+
}
|
242 |
+
if( isset( $paramvalue['SENT-BY'] ))
|
243 |
+
$attendee1 .= $this->intAttrDelimiter.'SENT-BY='.$paramvalue['SENT-BY'];
|
244 |
+
if( isset( $paramvalue['CN'] ))
|
245 |
+
$attendee1 .= $this->intAttrDelimiter.'CN='.$paramvalue['CN'];
|
246 |
+
if( isset( $paramvalue['DIR'] )) {
|
247 |
+
$delim = ( FALSE === strpos( $paramvalue['DIR'], '"' )) ? '"' : '';
|
248 |
+
$attendee1 .= $this->intAttrDelimiter.'DIR='.$delim.$paramvalue['DIR'].$delim;
|
249 |
+
}
|
250 |
+
if( isset( $paramvalue['LANGUAGE'] ))
|
251 |
+
$attendee1 .= $this->intAttrDelimiter.'LANGUAGE='.$paramvalue['LANGUAGE'];
|
252 |
+
$xparams = array();
|
253 |
+
foreach( $paramvalue as $optparamlabel => $optparamvalue ) { // start foreach 3
|
254 |
+
if( ctype_digit( (string) $optparamlabel )) {
|
255 |
+
$xparams[] = $optparamvalue;
|
256 |
+
continue;
|
257 |
+
}
|
258 |
+
if( !in_array( $optparamlabel, array( 'CUTYPE', 'MEMBER', 'ROLE', 'PARTSTAT', 'RSVP', 'DELEGATED-TO', 'DELEGATED-FROM', 'SENT-BY', 'CN', 'DIR', 'LANGUAGE' )))
|
259 |
+
$xparams[$optparamlabel] = $optparamvalue;
|
260 |
+
} // end foreach 3
|
261 |
+
ksort( $xparams, SORT_STRING );
|
262 |
+
foreach( $xparams as $paramKey => $paramValue ) {
|
263 |
+
if( ctype_digit( (string) $paramKey ))
|
264 |
+
$attendee1 .= $this->intAttrDelimiter.$paramValue;
|
265 |
+
else
|
266 |
+
$attendee1 .= $this->intAttrDelimiter."$paramKey=$paramValue";
|
267 |
+
} // end foreach 3
|
268 |
+
} // end elseif(( 'params' == $paramlabel ) && ( is_array( $paramvalue )))
|
269 |
+
} // end foreach 2
|
270 |
+
$output .= $this->_createElement( 'ATTENDEE', $attendee1, $attendee2 );
|
271 |
+
} // end foreach 1
|
272 |
+
return $output;
|
273 |
+
}
|
274 |
+
/**
|
275 |
+
* set calendar component property attach
|
276 |
+
*
|
277 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
278 |
+
* @since 2.18.13 - 2013-09-22
|
279 |
+
* @param string $value
|
280 |
+
* @param array $params
|
281 |
+
* @param integer $index
|
282 |
+
* @uses calendarComponent::getConfig()
|
283 |
+
* @uses calendarComponent::$objName
|
284 |
+
* @uses iCalUtilityFunctions::_existRem()
|
285 |
+
* @uses iCalUtilityFunctions::_setMval()
|
286 |
+
* @return bool
|
287 |
+
*/
|
288 |
+
function setAttendee( $value, $params=FALSE, $index=FALSE ) {
|
289 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
290 |
+
// ftp://, http://, mailto:, file://, gopher://, news:, nntp://, telnet://, wais://, prospero:// may exist.. . also in params
|
291 |
+
if( !empty( $value )) {
|
292 |
+
if( FALSE === ( $pos = strpos( substr( $value, 0, 9 ), ':' )))
|
293 |
+
$value = 'MAILTO:'.$value;
|
294 |
+
elseif( !empty( $value ))
|
295 |
+
$value = strtolower( substr( $value, 0, $pos )).substr( $value, $pos );
|
296 |
+
$value = str_replace( 'mailto:', 'MAILTO:', $value );
|
297 |
+
}
|
298 |
+
$params2 = array();
|
299 |
+
if( is_array($params )) {
|
300 |
+
$optarrays = array();
|
301 |
+
$params = array_change_key_case( $params, CASE_UPPER );
|
302 |
+
foreach( $params as $optparamlabel => $optparamvalue ) {
|
303 |
+
if(( 'X-' != substr( $optparamlabel, 0, 2 )) && (( 'vfreebusy' == $this->objName ) || ( 'valarm' == $this->objName )))
|
304 |
+
continue;
|
305 |
+
switch( $optparamlabel ) {
|
306 |
+
case 'MEMBER':
|
307 |
+
case 'DELEGATED-TO':
|
308 |
+
case 'DELEGATED-FROM':
|
309 |
+
if( !is_array( $optparamvalue ))
|
310 |
+
$optparamvalue = array( $optparamvalue );
|
311 |
+
foreach( $optparamvalue as $part ) {
|
312 |
+
$part = trim( $part );
|
313 |
+
if(( '"' == substr( $part, 0, 1 )) &&
|
314 |
+
( '"' == substr( $part, -1 )))
|
315 |
+
$part = substr( $part, 1, ( strlen( $part ) - 2 ));
|
316 |
+
if( 'mailto:' != strtolower( substr( $part, 0, 7 )))
|
317 |
+
$part = "MAILTO:$part";
|
318 |
+
else
|
319 |
+
$part = 'MAILTO:'.substr( $part, 7 );
|
320 |
+
$optarrays[$optparamlabel][] = $part;
|
321 |
+
}
|
322 |
+
break;
|
323 |
+
default:
|
324 |
+
if(( '"' == substr( $optparamvalue, 0, 1 )) &&
|
325 |
+
( '"' == substr( $optparamvalue, -1 )))
|
326 |
+
$optparamvalue = substr( $optparamvalue, 1, ( strlen( $optparamvalue ) - 2 ));
|
327 |
+
if( 'SENT-BY' == $optparamlabel ) {
|
328 |
+
if( 'mailto:' != strtolower( substr( $optparamvalue, 0, 7 )))
|
329 |
+
$optparamvalue = "MAILTO:$optparamvalue";
|
330 |
+
else
|
331 |
+
$optparamvalue = 'MAILTO:'.substr( $optparamvalue, 7 );
|
332 |
+
}
|
333 |
+
$params2[$optparamlabel] = $optparamvalue;
|
334 |
+
break;
|
335 |
+
} // end switch( $optparamlabel.. .
|
336 |
+
} // end foreach( $optparam.. .
|
337 |
+
foreach( $optarrays as $optparamlabel => $optparams )
|
338 |
+
$params2[$optparamlabel] = $optparams;
|
339 |
+
}
|
340 |
+
// remove defaults
|
341 |
+
iCalUtilityFunctions::_existRem( $params2, 'CUTYPE', 'INDIVIDUAL' );
|
342 |
+
iCalUtilityFunctions::_existRem( $params2, 'PARTSTAT', 'NEEDS-ACTION' );
|
343 |
+
iCalUtilityFunctions::_existRem( $params2, 'ROLE', 'REQ-PARTICIPANT' );
|
344 |
+
iCalUtilityFunctions::_existRem( $params2, 'RSVP', 'FALSE' );
|
345 |
+
// check language setting
|
346 |
+
if( isset( $params2['CN' ] )) {
|
347 |
+
$lang = $this->getConfig( 'language' );
|
348 |
+
if( !isset( $params2['LANGUAGE' ] ) && !empty( $lang ))
|
349 |
+
$params2['LANGUAGE' ] = $lang;
|
350 |
+
}
|
351 |
+
iCalUtilityFunctions::_setMval( $this->attendee, $value, $params2, FALSE, $index );
|
352 |
+
return TRUE;
|
353 |
+
}
|
354 |
+
/*********************************************************************************/
|
355 |
+
/**
|
356 |
+
* Property Name: CATEGORIES
|
357 |
+
*/
|
358 |
+
/**
|
359 |
+
* creates formatted output for calendar component property categories
|
360 |
+
*
|
361 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
362 |
+
* @since 2.16.2 - 2012-12-18
|
363 |
+
* @uses calendarComponent::$categories
|
364 |
+
* @uses calendarComponent::_createElement()
|
365 |
+
* @uses calendarComponent::_createParams()
|
366 |
+
* @uses iCalUtilityFunctions::_strrep()
|
367 |
+
* @uses calendarComponent::$format
|
368 |
+
* @uses calendarComponent::$nl
|
369 |
+
* @return string
|
370 |
+
*/
|
371 |
+
function createCategories() {
|
372 |
+
if( empty( $this->categories )) return FALSE;
|
373 |
+
$output = null;
|
374 |
+
foreach( $this->categories as $category ) {
|
375 |
+
if( empty( $category['value'] )) {
|
376 |
+
if ( $this->getConfig( 'allowEmpty' ))
|
377 |
+
$output .= $this->_createElement( 'CATEGORIES' );
|
378 |
+
continue;
|
379 |
+
}
|
380 |
+
$attributes = $this->_createParams( $category['params'], array( 'LANGUAGE' ));
|
381 |
+
if( is_array( $category['value'] )) {
|
382 |
+
foreach( $category['value'] as $cix => $categoryPart )
|
383 |
+
$category['value'][$cix] = iCalUtilityFunctions::_strrep( $categoryPart, $this->format, $this->nl );
|
384 |
+
$content = implode( ',', $category['value'] );
|
385 |
+
}
|
386 |
+
else
|
387 |
+
$content = iCalUtilityFunctions::_strrep( $category['value'], $this->format, $this->nl );
|
388 |
+
$output .= $this->_createElement( 'CATEGORIES', $attributes, $content );
|
389 |
+
}
|
390 |
+
return $output;
|
391 |
+
}
|
392 |
+
/**
|
393 |
+
* set calendar component property categories
|
394 |
+
*
|
395 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
396 |
+
* @since 2.16.21 - 2013-06-23
|
397 |
+
* @param mixed $value
|
398 |
+
* @param array $params
|
399 |
+
* @param integer $index
|
400 |
+
* @uses calendarComponent::getConfig()
|
401 |
+
* @uses calendarComponent::$categories
|
402 |
+
* @uses iCalUtilityFunctions::_setMval()
|
403 |
+
* @return bool
|
404 |
+
*/
|
405 |
+
function setCategories( $value, $params=FALSE, $index=FALSE ) {
|
406 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
407 |
+
iCalUtilityFunctions::_setMval( $this->categories, $value, $params, FALSE, $index );
|
408 |
+
return TRUE;
|
409 |
+
}
|
410 |
+
/*********************************************************************************/
|
411 |
+
/**
|
412 |
+
* Property Name: CLASS
|
413 |
+
*/
|
414 |
+
/**
|
415 |
+
* creates formatted output for calendar component property class
|
416 |
+
*
|
417 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
418 |
+
* @since 0.9.7 - 2006-11-20
|
419 |
+
* @uses calendarComponent::$class
|
420 |
+
* @uses calendarComponent::getConfig()
|
421 |
+
* @uses calendarComponent::_createElement()
|
422 |
+
* @uses calendarComponent::_createParams()
|
423 |
+
* @return string
|
424 |
+
*/
|
425 |
+
function createClass() {
|
426 |
+
if( empty( $this->class )) return FALSE;
|
427 |
+
if( empty( $this->class['value'] ))
|
428 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'CLASS' ) : FALSE;
|
429 |
+
$attributes = $this->_createParams( $this->class['params'] );
|
430 |
+
return $this->_createElement( 'CLASS', $attributes, $this->class['value'] );
|
431 |
+
}
|
432 |
+
/**
|
433 |
+
* set calendar component property class
|
434 |
+
*
|
435 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
436 |
+
* @since 2.16.21 - 2013-06-23
|
437 |
+
* @param string $value "PUBLIC" / "PRIVATE" / "CONFIDENTIAL" / iana-token / x-name
|
438 |
+
* @param array $params optional
|
439 |
+
* @uses calendarComponent::getConfig()
|
440 |
+
* @uses calendarComponent::$class
|
441 |
+
* @uses iCalUtilityFunctions::_setParams()
|
442 |
+
* @return bool
|
443 |
+
*/
|
444 |
+
function setClass( $value, $params=FALSE ) {
|
445 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
446 |
+
$this->class = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
447 |
+
return TRUE;
|
448 |
+
}
|
449 |
+
/*********************************************************************************/
|
450 |
+
/**
|
451 |
+
* Property Name: COMMENT
|
452 |
+
*/
|
453 |
+
/**
|
454 |
+
* creates formatted output for calendar component property comment
|
455 |
+
*
|
456 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
457 |
+
* @since 2.16.2 - 2012-12-18
|
458 |
+
* @uses calendarComponent::$comment
|
459 |
+
* @uses calendarComponent::getConfig()
|
460 |
+
* @uses calendarComponent::_createElement()
|
461 |
+
* @uses calendarComponent::_createParams()
|
462 |
+
* @uses iCalUtilityFunctions::_strrep()
|
463 |
+
* @uses calendarComponent::$format
|
464 |
+
* @uses calendarComponent::$nl
|
465 |
+
* @return string
|
466 |
+
*/
|
467 |
+
function createComment() {
|
468 |
+
if( empty( $this->comment )) return FALSE;
|
469 |
+
$output = null;
|
470 |
+
foreach( $this->comment as $commentPart ) {
|
471 |
+
if( empty( $commentPart['value'] )) {
|
472 |
+
if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'COMMENT' );
|
473 |
+
continue;
|
474 |
+
}
|
475 |
+
$attributes = $this->_createParams( $commentPart['params'], array( 'ALTREP', 'LANGUAGE' ));
|
476 |
+
$content = iCalUtilityFunctions::_strrep( $commentPart['value'], $this->format, $this->nl );
|
477 |
+
$output .= $this->_createElement( 'COMMENT', $attributes, $content );
|
478 |
+
}
|
479 |
+
return $output;
|
480 |
+
}
|
481 |
+
/**
|
482 |
+
* set calendar component property comment
|
483 |
+
*
|
484 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
485 |
+
* @since 2.16.21 - 2013-06-23
|
486 |
+
* @param string $value
|
487 |
+
* @param array $params
|
488 |
+
* @param integer $index
|
489 |
+
* @uses calendarComponent::getConfig()
|
490 |
+
* @uses iCalUtilityFunctions::_setMval()
|
491 |
+
* @uses calendarComponent::$comment
|
492 |
+
* @return bool
|
493 |
+
*/
|
494 |
+
function setComment( $value, $params=FALSE, $index=FALSE ) {
|
495 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
496 |
+
iCalUtilityFunctions::_setMval( $this->comment, $value, $params, FALSE, $index );
|
497 |
+
return TRUE;
|
498 |
+
}
|
499 |
+
/*********************************************************************************/
|
500 |
+
/**
|
501 |
+
* Property Name: COMPLETED
|
502 |
+
*/
|
503 |
+
/**
|
504 |
+
* creates formatted output for calendar component property completed
|
505 |
+
*
|
506 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
507 |
+
* @since 2.4.8 - 2008-10-22
|
508 |
+
* @return string
|
509 |
+
* @uses calendarComponent::$completed
|
510 |
+
* @uses calendarComponent::getConfig()
|
511 |
+
* @uses calendarComponent::_createElement()
|
512 |
+
* @uses iCalUtilityFunctions::_date2strdate();
|
513 |
+
* @uses calendarComponent::_createParams()
|
514 |
+
*/
|
515 |
+
function createCompleted( ) {
|
516 |
+
if( empty( $this->completed )) return FALSE;
|
517 |
+
if( !isset( $this->completed['value']['year'] ) &&
|
518 |
+
!isset( $this->completed['value']['month'] ) &&
|
519 |
+
!isset( $this->completed['value']['day'] ) &&
|
520 |
+
!isset( $this->completed['value']['hour'] ) &&
|
521 |
+
!isset( $this->completed['value']['min'] ) &&
|
522 |
+
!isset( $this->completed['value']['sec'] ))
|
523 |
+
if( $this->getConfig( 'allowEmpty' ))
|
524 |
+
return $this->_createElement( 'COMPLETED' );
|
525 |
+
else return FALSE;
|
526 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->completed['value'], 7 );
|
527 |
+
$attributes = $this->_createParams( $this->completed['params'] );
|
528 |
+
return $this->_createElement( 'COMPLETED', $attributes, $formatted );
|
529 |
+
}
|
530 |
+
/**
|
531 |
+
* set calendar component property completed
|
532 |
+
*
|
533 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
534 |
+
* @since 2.16.21 - 2013-06-23
|
535 |
+
* @param mixed $year
|
536 |
+
* @param mixed $month
|
537 |
+
* @param int $day
|
538 |
+
* @param int $hour
|
539 |
+
* @param int $min
|
540 |
+
* @param int $sec
|
541 |
+
* @param array $params
|
542 |
+
* @uses calendarComponent::getConfig()
|
543 |
+
* @uses iCalUtilityFunctions::_setParams()
|
544 |
+
* @uses calendarComponent::$completed
|
545 |
+
* @uses iCalUtilityFunctions::_setDate2()
|
546 |
+
* @return bool
|
547 |
+
*/
|
548 |
+
function setCompleted( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
|
549 |
+
if( empty( $year )) {
|
550 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
551 |
+
$this->completed = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
|
552 |
+
return TRUE;
|
553 |
+
}
|
554 |
+
else
|
555 |
+
return FALSE;
|
556 |
+
}
|
557 |
+
$this->completed = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
|
558 |
+
return TRUE;
|
559 |
+
}
|
560 |
+
/*********************************************************************************/
|
561 |
+
/**
|
562 |
+
* Property Name: CONTACT
|
563 |
+
*/
|
564 |
+
/**
|
565 |
+
* creates formatted output for calendar component property contact
|
566 |
+
*
|
567 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
568 |
+
* @since 2.16.2 - 2012-12-18
|
569 |
+
* @uses calendarComponent::$contact
|
570 |
+
* @uses calendarComponent::_createParams()
|
571 |
+
* @uses iCalUtilityFunctions::_strrep()
|
572 |
+
* @uses calendarComponent::getConfig()
|
573 |
+
* @uses calendarComponent::_createElement()
|
574 |
+
* @return string
|
575 |
+
*/
|
576 |
+
function createContact() {
|
577 |
+
if( empty( $this->contact )) return FALSE;
|
578 |
+
$output = null;
|
579 |
+
foreach( $this->contact as $contact ) {
|
580 |
+
if( !empty( $contact['value'] )) {
|
581 |
+
$attributes = $this->_createParams( $contact['params'], array( 'ALTREP', 'LANGUAGE' ));
|
582 |
+
$content = iCalUtilityFunctions::_strrep( $contact['value'], $this->format, $this->nl );
|
583 |
+
$output .= $this->_createElement( 'CONTACT', $attributes, $content );
|
584 |
+
}
|
585 |
+
elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'CONTACT' );
|
586 |
+
}
|
587 |
+
return $output;
|
588 |
+
}
|
589 |
+
/**
|
590 |
+
* set calendar component property contact
|
591 |
+
*
|
592 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
593 |
+
* @since 2.16.21 - 2013-06-23
|
594 |
+
* @param string $value
|
595 |
+
* @param array $params
|
596 |
+
* @param integer $index
|
597 |
+
* @uses calendarComponent::getConfig()
|
598 |
+
* @uses iCalUtilityFunctions::_setMval()
|
599 |
+
* @uses calendarComponent::$contact
|
600 |
+
* @return bool
|
601 |
+
*/
|
602 |
+
function setContact( $value, $params=FALSE, $index=FALSE ) {
|
603 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
604 |
+
iCalUtilityFunctions::_setMval( $this->contact, $value, $params, FALSE, $index );
|
605 |
+
return TRUE;
|
606 |
+
}
|
607 |
+
/*********************************************************************************/
|
608 |
+
/**
|
609 |
+
* Property Name: CREATED
|
610 |
+
*/
|
611 |
+
/**
|
612 |
+
* creates formatted output for calendar component property created
|
613 |
+
*
|
614 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
615 |
+
* @since 2.4.8 - 2008-10-21
|
616 |
+
* @uses calendarComponent::$created
|
617 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
618 |
+
* @uses calendarComponent::_createParams()
|
619 |
+
* @uses calendarComponent::_createElement()
|
620 |
+
* @return string
|
621 |
+
*/
|
622 |
+
function createCreated() {
|
623 |
+
if( empty( $this->created )) return FALSE;
|
624 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->created['value'], 7 );
|
625 |
+
$attributes = $this->_createParams( $this->created['params'] );
|
626 |
+
return $this->_createElement( 'CREATED', $attributes, $formatted );
|
627 |
+
}
|
628 |
+
/**
|
629 |
+
* set calendar component property created
|
630 |
+
*
|
631 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
632 |
+
* @since 2.19.5 - 2014-03-29
|
633 |
+
* @param mixed $year
|
634 |
+
* @param mixed $month
|
635 |
+
* @param int $day
|
636 |
+
* @param int $hour
|
637 |
+
* @param int $min
|
638 |
+
* @param int $sec
|
639 |
+
* @param mixed $params
|
640 |
+
* @uses calendarComponent::$created
|
641 |
+
* @uses iCalUtilityFunctions::_setDate2()
|
642 |
+
* @return bool
|
643 |
+
*/
|
644 |
+
function setCreated( $year=FALSE, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
|
645 |
+
if( !isset( $year ))
|
646 |
+
$year = gmdate( 'Ymd\THis' );
|
647 |
+
$this->created = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
|
648 |
+
return TRUE;
|
649 |
+
}
|
650 |
+
/*********************************************************************************/
|
651 |
+
/**
|
652 |
+
* Property Name: DESCRIPTION
|
653 |
+
*/
|
654 |
+
/**
|
655 |
+
* creates formatted output for calendar component property description
|
656 |
+
*
|
657 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
658 |
+
* @since 2.16.2 - 2012-12-18
|
659 |
+
* @uses calendarComponent::$description
|
660 |
+
* @uses calendarComponent::_createParams()
|
661 |
+
* @uses iCalUtilityFunctions::_strrep()
|
662 |
+
* @uses calendarComponent::_createElement()
|
663 |
+
* @uses calendarComponent::getConfig()
|
664 |
+
* @return string
|
665 |
+
*/
|
666 |
+
function createDescription() {
|
667 |
+
if( empty( $this->description )) return FALSE;
|
668 |
+
$output = null;
|
669 |
+
foreach( $this->description as $description ) {
|
670 |
+
if( !empty( $description['value'] )) {
|
671 |
+
$attributes = $this->_createParams( $description['params'], array( 'ALTREP', 'LANGUAGE' ));
|
672 |
+
$content = iCalUtilityFunctions::_strrep( $description['value'], $this->format, $this->nl );
|
673 |
+
$output .= $this->_createElement( 'DESCRIPTION', $attributes, $content );
|
674 |
+
}
|
675 |
+
elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'DESCRIPTION' );
|
676 |
+
}
|
677 |
+
return $output;
|
678 |
+
}
|
679 |
+
/**
|
680 |
+
* set calendar component property description
|
681 |
+
*
|
682 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
683 |
+
* @since 2.16.21 - 2013-06-23
|
684 |
+
* @param string $value
|
685 |
+
* @param array $params
|
686 |
+
* @param integer $index
|
687 |
+
* @uses calendarComponent::getConfig()
|
688 |
+
* @uses calendarComponent::$objName
|
689 |
+
* @uses iCalUtilityFunctions::_setMval()
|
690 |
+
* @uses calendarComponent::$description
|
691 |
+
* @return bool
|
692 |
+
*/
|
693 |
+
function setDescription( $value, $params=FALSE, $index=FALSE ) {
|
694 |
+
if( empty( $value )) { if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE; }
|
695 |
+
if( 'vjournal' != $this->objName )
|
696 |
+
$index = 1;
|
697 |
+
iCalUtilityFunctions::_setMval( $this->description, $value, $params, FALSE, $index );
|
698 |
+
return TRUE;
|
699 |
+
}
|
700 |
+
/*********************************************************************************/
|
701 |
+
/**
|
702 |
+
* Property Name: DTEND
|
703 |
+
*/
|
704 |
+
/**
|
705 |
+
* creates formatted output for calendar component property dtend
|
706 |
+
*
|
707 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
708 |
+
* @since 2.14.4 - 2012-09-26
|
709 |
+
* @uses calendarComponent::$dtend
|
710 |
+
* @uses calendarComponent::getConfig()
|
711 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
712 |
+
* @uses calendarComponent::_createParams()
|
713 |
+
* @uses calendarComponent::_createElement()
|
714 |
+
* @return string
|
715 |
+
*/
|
716 |
+
function createDtend() {
|
717 |
+
if( empty( $this->dtend )) return FALSE;
|
718 |
+
if( !isset( $this->dtend['value']['year'] ) &&
|
719 |
+
!isset( $this->dtend['value']['month'] ) &&
|
720 |
+
!isset( $this->dtend['value']['day'] ) &&
|
721 |
+
!isset( $this->dtend['value']['hour'] ) &&
|
722 |
+
!isset( $this->dtend['value']['min'] ) &&
|
723 |
+
!isset( $this->dtend['value']['sec'] ))
|
724 |
+
if( $this->getConfig( 'allowEmpty' ))
|
725 |
+
return $this->_createElement( 'DTEND' );
|
726 |
+
else return FALSE;
|
727 |
+
$parno = ( isset( $this->dtend['params']['VALUE'] ) && ( 'DATE' == $this->dtend['params']['VALUE'] )) ? 3 : null;
|
728 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->dtend['value'], $parno );
|
729 |
+
$attributes = $this->_createParams( $this->dtend['params'] );
|
730 |
+
return $this->_createElement( 'DTEND', $attributes, $formatted );
|
731 |
+
}
|
732 |
+
/**
|
733 |
+
* set calendar component property dtend
|
734 |
+
*
|
735 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
736 |
+
* @since 2.16.21 - 2013-06-23
|
737 |
+
* @param mixed $year
|
738 |
+
* @param mixed $month
|
739 |
+
* @param int $day
|
740 |
+
* @param int $hour
|
741 |
+
* @param int $min
|
742 |
+
* @param int $sec
|
743 |
+
* @param string $tz
|
744 |
+
* @param array $params
|
745 |
+
* @uses calendarComponent::getConfig()
|
746 |
+
* @uses calendarComponent::$dtend
|
747 |
+
* @uses iCalUtilityFunctions::_setParams()
|
748 |
+
* @uses iCalUtilityFunctions::_setDate()
|
749 |
+
* @return bool
|
750 |
+
*/
|
751 |
+
function setDtend( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
|
752 |
+
if( empty( $year )) {
|
753 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
754 |
+
$this->dtend = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
|
755 |
+
return TRUE;
|
756 |
+
}
|
757 |
+
else
|
758 |
+
return FALSE;
|
759 |
+
}
|
760 |
+
$this->dtend = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
|
761 |
+
return TRUE;
|
762 |
+
}
|
763 |
+
/*********************************************************************************/
|
764 |
+
/**
|
765 |
+
* Property Name: DTSTAMP
|
766 |
+
*/
|
767 |
+
/**
|
768 |
+
* creates formatted output for calendar component property dtstamp
|
769 |
+
*
|
770 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
771 |
+
* @since 2.4.4 - 2008-03-07
|
772 |
+
* @uses calendarComponent::$dtstamp
|
773 |
+
* @uses calendarComponent::_makeDtstamp()
|
774 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
775 |
+
* @uses calendarComponent::_createParams()
|
776 |
+
* @uses calendarComponent::_createElement()
|
777 |
+
* @return string
|
778 |
+
*/
|
779 |
+
function createDtstamp() {
|
780 |
+
if( !isset( $this->dtstamp['value']['year'] ) &&
|
781 |
+
!isset( $this->dtstamp['value']['month'] ) &&
|
782 |
+
!isset( $this->dtstamp['value']['day'] ) &&
|
783 |
+
!isset( $this->dtstamp['value']['hour'] ) &&
|
784 |
+
!isset( $this->dtstamp['value']['min'] ) &&
|
785 |
+
!isset( $this->dtstamp['value']['sec'] ))
|
786 |
+
$this->_makeDtstamp();
|
787 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->dtstamp['value'], 7 );
|
788 |
+
$attributes = $this->_createParams( $this->dtstamp['params'] );
|
789 |
+
return $this->_createElement( 'DTSTAMP', $attributes, $formatted );
|
790 |
+
}
|
791 |
+
/**
|
792 |
+
* computes datestamp for calendar component object instance dtstamp
|
793 |
+
*
|
794 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
795 |
+
* @since 2.21.11 - 2015-03-21
|
796 |
+
* @uses iCalUtilityFunctions::$fmt
|
797 |
+
* @uses calendarComponent::$dtstamp
|
798 |
+
* @return void
|
799 |
+
*/
|
800 |
+
function _makeDtstamp() {
|
801 |
+
$d = gmdate( iCalUtilityFunctions::$fmt['YmdHis3'], time());
|
802 |
+
$date = explode( '-', $d );
|
803 |
+
$this->dtstamp['value'] = array( 'year' => $date[0], 'month' => $date[1], 'day' => $date[2], 'hour' => $date[3], 'min' => $date[4], 'sec' => $date[5], 'tz' => 'Z' );
|
804 |
+
$this->dtstamp['params'] = null;
|
805 |
+
}
|
806 |
+
/**
|
807 |
+
* set calendar component property dtstamp
|
808 |
+
*
|
809 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
810 |
+
* @since 2.4.8 - 2008-10-23
|
811 |
+
* @param mixed $year
|
812 |
+
* @param mixed $month
|
813 |
+
* @param int $day
|
814 |
+
* @param int $hour
|
815 |
+
* @param int $min
|
816 |
+
* @param int $sec
|
817 |
+
* @param array $params
|
818 |
+
* @uses calendarComponent::_makeDtstamp()
|
819 |
+
* @uses calendarComponent::$dtstamp
|
820 |
+
* @uses iCalUtilityFunctions::_setDate2()
|
821 |
+
* @return TRUE
|
822 |
+
*/
|
823 |
+
function setDtstamp( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
|
824 |
+
if( empty( $year ))
|
825 |
+
$this->_makeDtstamp();
|
826 |
+
else
|
827 |
+
$this->dtstamp = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
|
828 |
+
return TRUE;
|
829 |
+
}
|
830 |
+
/*********************************************************************************/
|
831 |
+
/**
|
832 |
+
* Property Name: DTSTART
|
833 |
+
*/
|
834 |
+
/**
|
835 |
+
* creates formatted output for calendar component property dtstart
|
836 |
+
*
|
837 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
838 |
+
* @since 2.14.4 - 2012-09-26
|
839 |
+
* @uses calendarComponent::$dtstart
|
840 |
+
* @uses calendarComponent::getConfig()
|
841 |
+
* @uses calendarComponent::_createElement()
|
842 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
843 |
+
* @uses calendarComponent::_createParams()
|
844 |
+
* @return string
|
845 |
+
*/
|
846 |
+
function createDtstart() {
|
847 |
+
if( empty( $this->dtstart )) return FALSE;
|
848 |
+
if( !isset( $this->dtstart['value']['year'] ) &&
|
849 |
+
!isset( $this->dtstart['value']['month'] ) &&
|
850 |
+
!isset( $this->dtstart['value']['day'] ) &&
|
851 |
+
!isset( $this->dtstart['value']['hour'] ) &&
|
852 |
+
!isset( $this->dtstart['value']['min'] ) &&
|
853 |
+
!isset( $this->dtstart['value']['sec'] )) {
|
854 |
+
if( $this->getConfig( 'allowEmpty' ))
|
855 |
+
return $this->_createElement( 'DTSTART' );
|
856 |
+
else return FALSE;
|
857 |
+
}
|
858 |
+
if( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' )))
|
859 |
+
unset( $this->dtstart['value']['tz'], $this->dtstart['params']['TZID'] );
|
860 |
+
$parno = ( isset( $this->dtstart['params']['VALUE'] ) && ( 'DATE' == $this->dtstart['params']['VALUE'] )) ? 3 : null;
|
861 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->dtstart['value'], $parno );
|
862 |
+
$attributes = $this->_createParams( $this->dtstart['params'] );
|
863 |
+
return $this->_createElement( 'DTSTART', $attributes, $formatted );
|
864 |
+
}
|
865 |
+
/**
|
866 |
+
* set calendar component property dtstart
|
867 |
+
*
|
868 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
869 |
+
* @since 2.16.21 - 2013-06-23
|
870 |
+
* @param mixed $year
|
871 |
+
* @param mixed $month
|
872 |
+
* @param int $day
|
873 |
+
* @param int $hour
|
874 |
+
* @param int $min
|
875 |
+
* @param int $sec
|
876 |
+
* @param string $tz
|
877 |
+
* @param array $params
|
878 |
+
* @uses calendarComponent::getConfig()
|
879 |
+
* @uses iCalUtilityFunctions::_setParams()
|
880 |
+
* @uses calendarComponent::$dtstart
|
881 |
+
* @uses iCalUtilityFunctions::_setDate()
|
882 |
+
* @return bool
|
883 |
+
*/
|
884 |
+
function setDtstart( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
|
885 |
+
if( empty( $year )) {
|
886 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
887 |
+
$this->dtstart = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
|
888 |
+
return TRUE;
|
889 |
+
}
|
890 |
+
else
|
891 |
+
return FALSE;
|
892 |
+
}
|
893 |
+
$this->dtstart = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, 'dtstart', $this->objName, $this->getConfig( 'TZID' ));
|
894 |
+
return TRUE;
|
895 |
+
}
|
896 |
+
/*********************************************************************************/
|
897 |
+
/**
|
898 |
+
* Property Name: DUE
|
899 |
+
*/
|
900 |
+
/**
|
901 |
+
* creates formatted output for calendar component property due
|
902 |
+
*
|
903 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
904 |
+
* @since 2.14.4 - 2012-09-26
|
905 |
+
* @uses calendarComponent::$due
|
906 |
+
* @uses calendarComponent::getConfig()
|
907 |
+
* @uses calendarComponent::_createElement()
|
908 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
909 |
+
* @uses calendarComponent::_createParams()
|
910 |
+
* @return string
|
911 |
+
*/
|
912 |
+
function createDue() {
|
913 |
+
if( empty( $this->due )) return FALSE;
|
914 |
+
if( !isset( $this->due['value']['year'] ) &&
|
915 |
+
!isset( $this->due['value']['month'] ) &&
|
916 |
+
!isset( $this->due['value']['day'] ) &&
|
917 |
+
!isset( $this->due['value']['hour'] ) &&
|
918 |
+
!isset( $this->due['value']['min'] ) &&
|
919 |
+
!isset( $this->due['value']['sec'] )) {
|
920 |
+
if( $this->getConfig( 'allowEmpty' ))
|
921 |
+
return $this->_createElement( 'DUE' );
|
922 |
+
else
|
923 |
+
return FALSE;
|
924 |
+
}
|
925 |
+
$parno = ( isset( $this->due['params']['VALUE'] ) && ( 'DATE' == $this->due['params']['VALUE'] )) ? 3 : null;
|
926 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->due['value'], $parno );
|
927 |
+
$attributes = $this->_createParams( $this->due['params'] );
|
928 |
+
return $this->_createElement( 'DUE', $attributes, $formatted );
|
929 |
+
}
|
930 |
+
/**
|
931 |
+
* set calendar component property due
|
932 |
+
*
|
933 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
934 |
+
* @since 2.16.21 - 2013-06-23
|
935 |
+
* @param mixed $year
|
936 |
+
* @param mixed $month
|
937 |
+
* @param int $day
|
938 |
+
* @param int $hour
|
939 |
+
* @param int $min
|
940 |
+
* @param int $sec
|
941 |
+
* @param string $tz
|
942 |
+
* @param array $params
|
943 |
+
* @uses calendarComponent::getConfig()
|
944 |
+
* @uses calendarComponent::$due
|
945 |
+
* @uses iCalUtilityFunctions::_setParams()
|
946 |
+
* @uses iCalUtilityFunctions::_setDate()
|
947 |
+
* @return bool
|
948 |
+
*/
|
949 |
+
function setDue( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
|
950 |
+
if( empty( $year )) {
|
951 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
952 |
+
$this->due = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ));
|
953 |
+
return TRUE;
|
954 |
+
}
|
955 |
+
else
|
956 |
+
return FALSE;
|
957 |
+
}
|
958 |
+
$this->due = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
|
959 |
+
return TRUE;
|
960 |
+
}
|
961 |
+
/*********************************************************************************/
|
962 |
+
/**
|
963 |
+
* Property Name: DURATION
|
964 |
+
*/
|
965 |
+
/**
|
966 |
+
* creates formatted output for calendar component property duration
|
967 |
+
*
|
968 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
969 |
+
* @since 2.16.21 - 2013-05-25
|
970 |
+
* @uses calendarComponent::$duration
|
971 |
+
* @uses calendarComponent::getConfig()
|
972 |
+
* @uses calendarComponent::_createElement()
|
973 |
+
* @uses calendarComponent::_createParams()
|
974 |
+
* @uses iCalUtilityFunctions::_duration2str()
|
975 |
+
* @return string
|
976 |
+
*/
|
977 |
+
function createDuration() {
|
978 |
+
if( empty( $this->duration )) return FALSE;
|
979 |
+
if( !isset( $this->duration['value']['week'] ) &&
|
980 |
+
!isset( $this->duration['value']['day'] ) &&
|
981 |
+
!isset( $this->duration['value']['hour'] ) &&
|
982 |
+
!isset( $this->duration['value']['min'] ) &&
|
983 |
+
!isset( $this->duration['value']['sec'] ))
|
984 |
+
if( $this->getConfig( 'allowEmpty' ))
|
985 |
+
return $this->_createElement( 'DURATION' );
|
986 |
+
else return FALSE;
|
987 |
+
$attributes = $this->_createParams( $this->duration['params'] );
|
988 |
+
return $this->_createElement( 'DURATION', $attributes, iCalUtilityFunctions::_duration2str( $this->duration['value'] ));
|
989 |
+
}
|
990 |
+
/**
|
991 |
+
* set calendar component property duration
|
992 |
+
*
|
993 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
994 |
+
* @since 2.16.21 - 2013-05-25
|
995 |
+
* @param mixed $week
|
996 |
+
* @param mixed $day
|
997 |
+
* @param int $hour
|
998 |
+
* @param int $min
|
999 |
+
* @param int $sec
|
1000 |
+
* @param array $params
|
1001 |
+
* @uses calendarComponent::getConfig()
|
1002 |
+
* @uses calendarComponent::$duration
|
1003 |
+
* @uses iCalUtilityFunctions::_duration2arr()
|
1004 |
+
* @uses iCalUtilityFunctions::_durationStr2arr()
|
1005 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1006 |
+
* @uses iCalUtilityFunctions::_duration2arr()
|
1007 |
+
* @return bool
|
1008 |
+
*/
|
1009 |
+
function setDuration( $week, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
|
1010 |
+
if( empty( $week ) && empty( $day ) && empty( $hour ) && empty( $min ) && empty( $sec )) {
|
1011 |
+
if( $this->getConfig( 'allowEmpty' ))
|
1012 |
+
$week = $day = null;
|
1013 |
+
else
|
1014 |
+
return FALSE;
|
1015 |
+
}
|
1016 |
+
if( is_array( $week ) && ( 1 <= count( $week )))
|
1017 |
+
$this->duration = array( 'value' => iCalUtilityFunctions::_duration2arr( $week ), 'params' => iCalUtilityFunctions::_setParams( $day ));
|
1018 |
+
elseif( is_string( $week ) && ( 3 <= strlen( trim( $week )))) {
|
1019 |
+
$week = trim( $week );
|
1020 |
+
if( in_array( substr( $week, 0, 1 ), array( '+', '-' )))
|
1021 |
+
$week = substr( $week, 1 );
|
1022 |
+
$this->duration = array( 'value' => iCalUtilityFunctions::_durationStr2arr( $week ), 'params' => iCalUtilityFunctions::_setParams( $day ));
|
1023 |
+
}
|
1024 |
+
else
|
1025 |
+
$this->duration = array( 'value' => iCalUtilityFunctions::_duration2arr( array( 'week' => $week, 'day' => $day, 'hour' => $hour, 'min' => $min, 'sec' => $sec ))
|
1026 |
+
, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
1027 |
+
return TRUE;
|
1028 |
+
}
|
1029 |
+
/*********************************************************************************/
|
1030 |
+
/**
|
1031 |
+
* Property Name: EXDATE
|
1032 |
+
*/
|
1033 |
+
/**
|
1034 |
+
* creates formatted output for calendar component property exdate
|
1035 |
+
*
|
1036 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1037 |
+
* @since 2.16.5 - 2012-12-28
|
1038 |
+
* @uses calendarComponent::$exdate
|
1039 |
+
* @uses calendarComponent::getConfig()
|
1040 |
+
* @uses calendarComponent::_createElement()
|
1041 |
+
* @uses iCalUtilityFunctions::_sortExdate1()
|
1042 |
+
* @uses iCalUtilityFunctions::_sortExdate2()
|
1043 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
1044 |
+
* @uses calendarComponent::_createParams()
|
1045 |
+
* @return string
|
1046 |
+
*/
|
1047 |
+
function createExdate() {
|
1048 |
+
if( empty( $this->exdate )) return FALSE;
|
1049 |
+
$output = null;
|
1050 |
+
$exdates = array();
|
1051 |
+
foreach( $this->exdate as $theExdate ) {
|
1052 |
+
if( empty( $theExdate['value'] )) {
|
1053 |
+
if( $this->getConfig( 'allowEmpty' ))
|
1054 |
+
$output .= $this->_createElement( 'EXDATE' );
|
1055 |
+
continue;
|
1056 |
+
}
|
1057 |
+
if( 1 < count( $theExdate['value'] ))
|
1058 |
+
usort( $theExdate['value'], array( 'iCalUtilityFunctions', '_sortExdate1' ));
|
1059 |
+
$exdates[] = $theExdate;
|
1060 |
+
}
|
1061 |
+
if( 1 < count( $exdates ))
|
1062 |
+
usort( $exdates, array( 'iCalUtilityFunctions', '_sortExdate2' ));
|
1063 |
+
foreach( $exdates as $theExdate ) {
|
1064 |
+
$content = $attributes = null;
|
1065 |
+
foreach( $theExdate['value'] as $eix => $exdatePart ) {
|
1066 |
+
$parno = count( $exdatePart );
|
1067 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $exdatePart, $parno );
|
1068 |
+
if( isset( $theExdate['params']['TZID'] ))
|
1069 |
+
$formatted = str_replace( 'Z', '', $formatted);
|
1070 |
+
if( 0 < $eix ) {
|
1071 |
+
if( isset( $theExdate['value'][0]['tz'] )) {
|
1072 |
+
if( ctype_digit( substr( $theExdate['value'][0]['tz'], -4 )) ||
|
1073 |
+
( 'Z' == $theExdate['value'][0]['tz'] )) {
|
1074 |
+
if( 'Z' != substr( $formatted, -1 ))
|
1075 |
+
$formatted .= 'Z';
|
1076 |
+
}
|
1077 |
+
else
|
1078 |
+
$formatted = str_replace( 'Z', '', $formatted );
|
1079 |
+
}
|
1080 |
+
else
|
1081 |
+
$formatted = str_replace( 'Z', '', $formatted );
|
1082 |
+
} // end if( 0 < $eix )
|
1083 |
+
$content .= ( 0 < $eix ) ? ','.$formatted : $formatted;
|
1084 |
+
} // end foreach( $theExdate['value'] as $eix => $exdatePart )
|
1085 |
+
$attributes .= $this->_createParams( $theExdate['params'] );
|
1086 |
+
$output .= $this->_createElement( 'EXDATE', $attributes, $content );
|
1087 |
+
} // end foreach( $exdates as $theExdate )
|
1088 |
+
return $output;
|
1089 |
+
}
|
1090 |
+
/**
|
1091 |
+
* set calendar component property exdate
|
1092 |
+
*
|
1093 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1094 |
+
* @since 2.21.11 - 2015-03-10
|
1095 |
+
* @param array $exdates
|
1096 |
+
* @param array $params
|
1097 |
+
* @param integer $index
|
1098 |
+
* @uses calendarComponent::getConfig()
|
1099 |
+
* @uses iCalUtilityFunctions::_setMval()
|
1100 |
+
* @uses calendarComponent::$exdate
|
1101 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1102 |
+
* @uses iCalUtilityFunctions::_chkdatecfg()
|
1103 |
+
* @uses iCalUtilityFunctions::_existRem()
|
1104 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
1105 |
+
* @uses iCalUtilityFunctions::_isArrayTimestampDate()
|
1106 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
1107 |
+
* @uses iCalUtilityFunctions::_timestamp2date()
|
1108 |
+
* @uses iCalUtilityFunctions::_chkDateArr()
|
1109 |
+
* @uses iCalUtilityFunctions::$fmt
|
1110 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
1111 |
+
* @return bool
|
1112 |
+
*/
|
1113 |
+
function setExdate( $exdates, $params=FALSE, $index=FALSE ) {
|
1114 |
+
if( empty( $exdates )) {
|
1115 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
1116 |
+
iCalUtilityFunctions::_setMval( $this->exdate, '', $params, FALSE, $index );
|
1117 |
+
return TRUE;
|
1118 |
+
}
|
1119 |
+
else
|
1120 |
+
return FALSE;
|
1121 |
+
}
|
1122 |
+
$input = array( 'params' => iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' )));
|
1123 |
+
$toZ = ( isset( $input['params']['TZID'] ) && in_array( strtoupper( $input['params']['TZID'] ), array( 'GMT', 'UTC', 'Z' ))) ? TRUE : FALSE;
|
1124 |
+
/* ev. check 1:st date and save ev. timezone **/
|
1125 |
+
iCalUtilityFunctions::_chkdatecfg( reset( $exdates ), $parno, $input['params'] );
|
1126 |
+
iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME' ); // remove default parameter
|
1127 |
+
foreach( $exdates as $eix => $theExdate ) {
|
1128 |
+
iCalUtilityFunctions::_strDate2arr( $theExdate );
|
1129 |
+
if( iCalUtilityFunctions::_isArrayTimestampDate( $theExdate )) {
|
1130 |
+
if( isset( $theExdate['tz'] ) && !iCalUtilityFunctions::_isOffset( $theExdate['tz'] )) {
|
1131 |
+
if( isset( $input['params']['TZID'] ))
|
1132 |
+
$theExdate['tz'] = $input['params']['TZID'];
|
1133 |
+
else
|
1134 |
+
$input['params']['TZID'] = $theExdate['tz'];
|
1135 |
+
}
|
1136 |
+
$exdatea = iCalUtilityFunctions::_timestamp2date( $theExdate, $parno );
|
1137 |
+
}
|
1138 |
+
elseif( is_array( $theExdate )) {
|
1139 |
+
$d = iCalUtilityFunctions::_chkDateArr( $theExdate, $parno );
|
1140 |
+
if( isset( $d['tz'] ) && ( 'Z' != $d['tz'] ) && iCalUtilityFunctions::_isOffset( $d['tz'] )) {
|
1141 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $d['tz'] );
|
1142 |
+
$exdatea = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1143 |
+
unset( $exdatea['unparsedtext'] );
|
1144 |
+
}
|
1145 |
+
else
|
1146 |
+
$exdatea = $d;
|
1147 |
+
}
|
1148 |
+
elseif( 8 <= strlen( trim( $theExdate ))) { // ex. 2006-08-03 10:12:18
|
1149 |
+
$exdatea = iCalUtilityFunctions::_strdate2date( $theExdate, $parno );
|
1150 |
+
unset( $exdatea['unparsedtext'] );
|
1151 |
+
}
|
1152 |
+
if( 3 == $parno )
|
1153 |
+
unset( $exdatea['hour'], $exdatea['min'], $exdatea['sec'], $exdatea['tz'] );
|
1154 |
+
elseif( isset( $exdatea['tz'] ))
|
1155 |
+
$exdatea['tz'] = (string) $exdatea['tz'];
|
1156 |
+
if( isset( $input['params']['TZID'] ) ||
|
1157 |
+
( isset( $exdatea['tz'] ) && !iCalUtilityFunctions::_isOffset( $exdatea['tz'] )) ||
|
1158 |
+
( isset( $input['value'][0] ) && ( !isset( $input['value'][0]['tz'] ))) ||
|
1159 |
+
( isset( $input['value'][0]['tz'] ) && !iCalUtilityFunctions::_isOffset( $input['value'][0]['tz'] )))
|
1160 |
+
unset( $exdatea['tz'] );
|
1161 |
+
if( $toZ ) // time zone Z
|
1162 |
+
$exdatea['tz'] = 'Z';
|
1163 |
+
$input['value'][] = $exdatea;
|
1164 |
+
}
|
1165 |
+
if( 0 >= count( $input['value'] ))
|
1166 |
+
return FALSE;
|
1167 |
+
if( 3 == $parno ) {
|
1168 |
+
$input['params']['VALUE'] = 'DATE';
|
1169 |
+
unset( $input['params']['TZID'] );
|
1170 |
+
}
|
1171 |
+
if( $toZ ) // time zone Z
|
1172 |
+
unset( $input['params']['TZID'] );
|
1173 |
+
iCalUtilityFunctions::_setMval( $this->exdate, $input['value'], $input['params'], FALSE, $index );
|
1174 |
+
return TRUE;
|
1175 |
+
}
|
1176 |
+
/*********************************************************************************/
|
1177 |
+
/**
|
1178 |
+
* Property Name: EXRULE
|
1179 |
+
*/
|
1180 |
+
/**
|
1181 |
+
* creates formatted output for calendar component property exrule
|
1182 |
+
*
|
1183 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1184 |
+
* @since 2.4.8 - 2008-10-22
|
1185 |
+
* @uses calendarComponent::$exrule
|
1186 |
+
* @uses calendarComponent::_format_recur()
|
1187 |
+
* @return string
|
1188 |
+
*/
|
1189 |
+
function createExrule() {
|
1190 |
+
if( empty( $this->exrule )) return FALSE;
|
1191 |
+
return $this->_format_recur( 'EXRULE', $this->exrule );
|
1192 |
+
}
|
1193 |
+
/**
|
1194 |
+
* set calendar component property exdate
|
1195 |
+
*
|
1196 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1197 |
+
* @since 2.16.21 - 2013-06-23
|
1198 |
+
* @param array $exruleset
|
1199 |
+
* @param array $params
|
1200 |
+
* @param integer $index
|
1201 |
+
* @uses calendarComponent::getConfig()
|
1202 |
+
* @uses iCalUtilityFunctions::_setMval()
|
1203 |
+
* @uses calendarComponent::$exrule
|
1204 |
+
* @uses iCalUtilityFunctions::_setRexrule()
|
1205 |
+
* @return bool
|
1206 |
+
*/
|
1207 |
+
function setExrule( $exruleset, $params=FALSE, $index=FALSE ) {
|
1208 |
+
if( empty( $exruleset )) if( $this->getConfig( 'allowEmpty' )) $exruleset = ''; else return FALSE;
|
1209 |
+
iCalUtilityFunctions::_setMval( $this->exrule, iCalUtilityFunctions::_setRexrule( $exruleset ), $params, FALSE, $index );
|
1210 |
+
return TRUE;
|
1211 |
+
}
|
1212 |
+
/*********************************************************************************/
|
1213 |
+
/**
|
1214 |
+
* Property Name: FREEBUSY
|
1215 |
+
*/
|
1216 |
+
/**
|
1217 |
+
* creates formatted output for calendar component property freebusy
|
1218 |
+
*
|
1219 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1220 |
+
* @since 2.16.27 - 2013-07-05
|
1221 |
+
* @uses calendarComponent::$freebusy
|
1222 |
+
* @uses calendarComponent::getConfig()
|
1223 |
+
* @uses calendarComponent::_createElement()
|
1224 |
+
* @uses calendarComponent::$intAttrDelimiter
|
1225 |
+
* @uses calendarComponent::_createParams()
|
1226 |
+
* @uses iCalUtilityFunctions::_sortRdate1()
|
1227 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
1228 |
+
* @uses iCalUtilityFunctions::_duration2str()
|
1229 |
+
* @return string
|
1230 |
+
*/
|
1231 |
+
function createFreebusy() {
|
1232 |
+
if( empty( $this->freebusy )) return FALSE;
|
1233 |
+
$output = null;
|
1234 |
+
foreach( $this->freebusy as $freebusyPart ) {
|
1235 |
+
if( empty( $freebusyPart['value'] ) || (( 1 == count( $freebusyPart['value'] )) && isset( $freebusyPart['value']['fbtype'] ))) {
|
1236 |
+
if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'FREEBUSY' );
|
1237 |
+
continue;
|
1238 |
+
}
|
1239 |
+
$attributes = $content = null;
|
1240 |
+
if( isset( $freebusyPart['value']['fbtype'] )) {
|
1241 |
+
$attributes .= $this->intAttrDelimiter.'FBTYPE='.$freebusyPart['value']['fbtype'];
|
1242 |
+
unset( $freebusyPart['value']['fbtype'] );
|
1243 |
+
$freebusyPart['value'] = array_values( $freebusyPart['value'] );
|
1244 |
+
}
|
1245 |
+
else
|
1246 |
+
$attributes .= $this->intAttrDelimiter.'FBTYPE=BUSY';
|
1247 |
+
$attributes .= $this->_createParams( $freebusyPart['params'] );
|
1248 |
+
$fno = 1;
|
1249 |
+
$cnt = count( $freebusyPart['value']);
|
1250 |
+
if( 1 < $cnt )
|
1251 |
+
usort( $freebusyPart['value'], array( 'iCalUtilityFunctions', '_sortRdate1' ));
|
1252 |
+
foreach( $freebusyPart['value'] as $periodix => $freebusyPeriod ) {
|
1253 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $freebusyPeriod[0] );
|
1254 |
+
$content .= $formatted;
|
1255 |
+
$content .= '/';
|
1256 |
+
$cnt2 = count( $freebusyPeriod[1]);
|
1257 |
+
if( array_key_exists( 'year', $freebusyPeriod[1] )) // date-time
|
1258 |
+
$cnt2 = 7;
|
1259 |
+
elseif( array_key_exists( 'week', $freebusyPeriod[1] )) // duration
|
1260 |
+
$cnt2 = 5;
|
1261 |
+
if(( 7 == $cnt2 ) && // period= -> date-time
|
1262 |
+
isset( $freebusyPeriod[1]['year'] ) &&
|
1263 |
+
isset( $freebusyPeriod[1]['month'] ) &&
|
1264 |
+
isset( $freebusyPeriod[1]['day'] )) {
|
1265 |
+
$content .= iCalUtilityFunctions::_date2strdate( $freebusyPeriod[1] );
|
1266 |
+
}
|
1267 |
+
else { // period= -> dur-time
|
1268 |
+
$content .= iCalUtilityFunctions::_duration2str( $freebusyPeriod[1] );
|
1269 |
+
}
|
1270 |
+
if( $fno < $cnt )
|
1271 |
+
$content .= ',';
|
1272 |
+
$fno++;
|
1273 |
+
}
|
1274 |
+
$output .= $this->_createElement( 'FREEBUSY', $attributes, $content );
|
1275 |
+
}
|
1276 |
+
return $output;
|
1277 |
+
}
|
1278 |
+
/**
|
1279 |
+
* set calendar component property freebusy
|
1280 |
+
*
|
1281 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1282 |
+
* @since 2.16.21 - 2013-06-23
|
1283 |
+
* @param string $fbType
|
1284 |
+
* @param array $fbValues
|
1285 |
+
* @param array $params
|
1286 |
+
* @param integer $index
|
1287 |
+
* @uses calendarComponent::getConfig()
|
1288 |
+
* @uses calendarComponent::$freebusy
|
1289 |
+
* @uses iCalUtilityFunctions::_isArrayDate()
|
1290 |
+
* @uses iCalUtilityFunctions::_setMval()
|
1291 |
+
* @uses iCalUtilityFunctions::_chkDateArr()
|
1292 |
+
* @uses iCalUtilityFunctions::_isArrayTimestampDate()
|
1293 |
+
* @uses iCalUtilityFunctions::_timestamp2date()
|
1294 |
+
* @uses iCalUtilityFunctions::_duration2arr()
|
1295 |
+
* @uses iCalUtilityFunctions::_durationStr2arr()
|
1296 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
1297 |
+
* @return bool
|
1298 |
+
*/
|
1299 |
+
function setFreebusy( $fbType, $fbValues, $params=FALSE, $index=FALSE ) {
|
1300 |
+
if( empty( $fbValues )) {
|
1301 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
1302 |
+
iCalUtilityFunctions::_setMval( $this->freebusy, '', $params, FALSE, $index );
|
1303 |
+
return TRUE;
|
1304 |
+
}
|
1305 |
+
else
|
1306 |
+
return FALSE;
|
1307 |
+
}
|
1308 |
+
$fbType = strtoupper( $fbType );
|
1309 |
+
if(( !in_array( $fbType, array( 'FREE', 'BUSY', 'BUSY-UNAVAILABLE', 'BUSY-TENTATIVE' ))) &&
|
1310 |
+
( 'X-' != substr( $fbType, 0, 2 )))
|
1311 |
+
$fbType = 'BUSY';
|
1312 |
+
$input = array( 'fbtype' => $fbType );
|
1313 |
+
foreach( $fbValues as $fbPeriod ) { // periods => period
|
1314 |
+
if( empty( $fbPeriod ))
|
1315 |
+
continue;
|
1316 |
+
$freebusyPeriod = array();
|
1317 |
+
foreach( $fbPeriod as $fbMember ) { // pairs => singlepart
|
1318 |
+
$freebusyPairMember = array();
|
1319 |
+
if( is_array( $fbMember )) {
|
1320 |
+
if( iCalUtilityFunctions::_isArrayDate( $fbMember )) { // date-time value
|
1321 |
+
$freebusyPairMember = iCalUtilityFunctions::_chkDateArr( $fbMember, 7 );
|
1322 |
+
$freebusyPairMember['tz'] = 'Z';
|
1323 |
+
}
|
1324 |
+
elseif( iCalUtilityFunctions::_isArrayTimestampDate( $fbMember )) { // timestamp value
|
1325 |
+
$freebusyPairMember = iCalUtilityFunctions::_timestamp2date( $fbMember['timestamp'], 7 );
|
1326 |
+
$freebusyPairMember['tz'] = 'Z';
|
1327 |
+
}
|
1328 |
+
else { // array format duration
|
1329 |
+
$freebusyPairMember = iCalUtilityFunctions::_duration2arr( $fbMember );
|
1330 |
+
}
|
1331 |
+
}
|
1332 |
+
elseif(( 3 <= strlen( trim( $fbMember ))) && // string format duration
|
1333 |
+
( in_array( $fbMember{0}, array( 'P', '+', '-' )))) {
|
1334 |
+
if( 'P' != $fbMember{0} )
|
1335 |
+
$fbmember = substr( $fbMember, 1 );
|
1336 |
+
$freebusyPairMember = iCalUtilityFunctions::_durationStr2arr( $fbMember );
|
1337 |
+
}
|
1338 |
+
elseif( 8 <= strlen( trim( $fbMember ))) { // text date ex. 2006-08-03 10:12:18
|
1339 |
+
$freebusyPairMember = iCalUtilityFunctions::_strdate2date( $fbMember, 7 );
|
1340 |
+
unset( $freebusyPairMember['unparsedtext'] );
|
1341 |
+
$freebusyPairMember['tz'] = 'Z';
|
1342 |
+
}
|
1343 |
+
$freebusyPeriod[] = $freebusyPairMember;
|
1344 |
+
}
|
1345 |
+
$input[] = $freebusyPeriod;
|
1346 |
+
}
|
1347 |
+
iCalUtilityFunctions::_setMval( $this->freebusy, $input, $params, FALSE, $index );
|
1348 |
+
return TRUE;
|
1349 |
+
}
|
1350 |
+
/*********************************************************************************/
|
1351 |
+
/**
|
1352 |
+
* Property Name: GEO
|
1353 |
+
*/
|
1354 |
+
/**
|
1355 |
+
* creates formatted output for calendar component property geo
|
1356 |
+
*
|
1357 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1358 |
+
* @since 2.18.10 - 2013-09-03
|
1359 |
+
* @uses calendarComponent::$geo
|
1360 |
+
* @uses calendarComponent::getConfig()
|
1361 |
+
* @uses calendarComponent::_createElement()
|
1362 |
+
* @uses calendarComponent::_createParams()
|
1363 |
+
* @uses iCalUtilityFunctions::_geo2str2()
|
1364 |
+
* @uses iCalUtilityFunctions::$geoLongFmt
|
1365 |
+
* @uses iCalUtilityFunctions::$geoLatFmt
|
1366 |
+
* @return string
|
1367 |
+
*/
|
1368 |
+
function createGeo() {
|
1369 |
+
if( empty( $this->geo )) return FALSE;
|
1370 |
+
if( empty( $this->geo['value'] ))
|
1371 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'GEO' ) : FALSE;
|
1372 |
+
return $this->_createElement( 'GEO', $this->_createParams( $this->geo['params'] ),
|
1373 |
+
iCalUtilityFunctions::_geo2str2( $this->geo['value']['latitude'], iCalUtilityFunctions::$geoLatFmt ).
|
1374 |
+
';'.iCalUtilityFunctions::_geo2str2( $this->geo['value']['longitude'], iCalUtilityFunctions::$geoLongFmt ));
|
1375 |
+
}
|
1376 |
+
/**
|
1377 |
+
* set calendar component property geo
|
1378 |
+
*
|
1379 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1380 |
+
* @since 2.18.10 - 2013-09-03
|
1381 |
+
* @param mixed $latitude
|
1382 |
+
* @param mixed $longitude
|
1383 |
+
* @param array $params
|
1384 |
+
* @uses calendarComponent::$geo
|
1385 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1386 |
+
* @uses calendarComponent::getConfig()
|
1387 |
+
* @return bool
|
1388 |
+
*/
|
1389 |
+
function setGeo( $latitude, $longitude, $params=FALSE ) {
|
1390 |
+
if( isset( $latitude ) && isset( $longitude )) {
|
1391 |
+
if( !is_array( $this->geo )) $this->geo = array();
|
1392 |
+
$this->geo['value']['latitude'] = floatval( $latitude );
|
1393 |
+
$this->geo['value']['longitude'] = floatval( $longitude );
|
1394 |
+
$this->geo['params'] = iCalUtilityFunctions::_setParams( $params );
|
1395 |
+
}
|
1396 |
+
elseif( $this->getConfig( 'allowEmpty' ))
|
1397 |
+
$this->geo = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $params ) );
|
1398 |
+
else
|
1399 |
+
return FALSE;
|
1400 |
+
return TRUE;
|
1401 |
+
}
|
1402 |
+
/*********************************************************************************/
|
1403 |
+
/**
|
1404 |
+
* Property Name: LAST-MODIFIED
|
1405 |
+
*/
|
1406 |
+
/**
|
1407 |
+
* creates formatted output for calendar component property last-modified
|
1408 |
+
*
|
1409 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1410 |
+
* @since 2.4.8 - 2008-10-21
|
1411 |
+
* @uses calendarComponent::$lastmodified
|
1412 |
+
* @uses calendarComponent::_createParams()
|
1413 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
1414 |
+
* @uses calendarComponent::_createElement()
|
1415 |
+
* @return string
|
1416 |
+
*/
|
1417 |
+
function createLastModified() {
|
1418 |
+
if( empty( $this->lastmodified )) return FALSE;
|
1419 |
+
$attributes = $this->_createParams( $this->lastmodified['params'] );
|
1420 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->lastmodified['value'], 7 );
|
1421 |
+
return $this->_createElement( 'LAST-MODIFIED', $attributes, $formatted );
|
1422 |
+
}
|
1423 |
+
/**
|
1424 |
+
* set calendar component property completed
|
1425 |
+
*
|
1426 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1427 |
+
* @since 2.19.5 - 2014-03-29
|
1428 |
+
* @param mixed $year optional
|
1429 |
+
* @param mixed $month optional
|
1430 |
+
* @param int $day optional
|
1431 |
+
* @param int $hour optional
|
1432 |
+
* @param int $min optional
|
1433 |
+
* @param int $sec optional
|
1434 |
+
* @param array $params optional
|
1435 |
+
* @uses calendarComponent::$lastmodified
|
1436 |
+
* @uses iCalUtilityFunctions::_setDate2()
|
1437 |
+
* @return boll
|
1438 |
+
*/
|
1439 |
+
function setLastModified( $year=FALSE, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
|
1440 |
+
if( empty( $year ))
|
1441 |
+
$year = gmdate( 'Ymd\THis' );
|
1442 |
+
$this->lastmodified = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
|
1443 |
+
return TRUE;
|
1444 |
+
}
|
1445 |
+
/*********************************************************************************/
|
1446 |
+
/**
|
1447 |
+
* Property Name: LOCATION
|
1448 |
+
*/
|
1449 |
+
/**
|
1450 |
+
* creates formatted output for calendar component property location
|
1451 |
+
*
|
1452 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1453 |
+
* @since 2.16.2 - 2012-12-18
|
1454 |
+
* @uses calendarComponent::$location
|
1455 |
+
* @uses calendarComponent::getConfig()
|
1456 |
+
* @uses calendarComponent::_createElement()
|
1457 |
+
* @uses calendarComponent::_createParams()
|
1458 |
+
* @uses iCalUtilityFunctions::_strrep()
|
1459 |
+
* @return string
|
1460 |
+
*/
|
1461 |
+
function createLocation() {
|
1462 |
+
if( empty( $this->location )) return FALSE;
|
1463 |
+
if( empty( $this->location['value'] ))
|
1464 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'LOCATION' ) : FALSE;
|
1465 |
+
$attributes = $this->_createParams( $this->location['params'], array( 'ALTREP', 'LANGUAGE' ));
|
1466 |
+
$content = iCalUtilityFunctions::_strrep( $this->location['value'], $this->format, $this->nl );
|
1467 |
+
return $this->_createElement( 'LOCATION', $attributes, $content );
|
1468 |
+
}
|
1469 |
+
/**
|
1470 |
+
* set calendar component property location
|
1471 |
+
'
|
1472 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1473 |
+
* @since 2.16.21 - 2013-06-23
|
1474 |
+
* @param string $value
|
1475 |
+
* @param array $params
|
1476 |
+
* @uses calendarComponent::$location
|
1477 |
+
* @uses calendarComponent::getConfig()
|
1478 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1479 |
+
* @return bool
|
1480 |
+
*/
|
1481 |
+
function setLocation( $value, $params=FALSE ) {
|
1482 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
1483 |
+
$this->location = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
1484 |
+
return TRUE;
|
1485 |
+
}
|
1486 |
+
/*********************************************************************************/
|
1487 |
+
/**
|
1488 |
+
* Property Name: ORGANIZER
|
1489 |
+
*/
|
1490 |
+
/**
|
1491 |
+
* creates formatted output for calendar component property organizer
|
1492 |
+
*
|
1493 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1494 |
+
* @since 2.6.33 - 2010-12-17
|
1495 |
+
* @uses calendarComponent::$organizer
|
1496 |
+
* @uses calendarComponent::getConfig()
|
1497 |
+
* @uses calendarComponent::_createElement()
|
1498 |
+
* @uses calendarComponent::_createParams()
|
1499 |
+
* @return string
|
1500 |
+
*/
|
1501 |
+
function createOrganizer() {
|
1502 |
+
if( empty( $this->organizer )) return FALSE;
|
1503 |
+
if( empty( $this->organizer['value'] ))
|
1504 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'ORGANIZER' ) : FALSE;
|
1505 |
+
$attributes = $this->_createParams( $this->organizer['params']
|
1506 |
+
, array( 'CN', 'DIR', 'SENT-BY', 'LANGUAGE' ));
|
1507 |
+
return $this->_createElement( 'ORGANIZER', $attributes, $this->organizer['value'] );
|
1508 |
+
}
|
1509 |
+
/**
|
1510 |
+
* set calendar component property organizer
|
1511 |
+
*
|
1512 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1513 |
+
* @since 2.16.21 - 2013-06-23
|
1514 |
+
* @param string $value
|
1515 |
+
* @param array $params
|
1516 |
+
* @uses calendarComponent::getConfig()
|
1517 |
+
* @uses calendarComponent::$organizer
|
1518 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1519 |
+
* @return bool
|
1520 |
+
*/
|
1521 |
+
function setOrganizer( $value, $params=FALSE ) {
|
1522 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
1523 |
+
if( !empty( $value )) {
|
1524 |
+
if( FALSE === ( $pos = strpos( substr( $value, 0, 9 ), ':' )))
|
1525 |
+
$value = 'MAILTO:'.$value;
|
1526 |
+
elseif( !empty( $value ))
|
1527 |
+
$value = strtolower( substr( $value, 0, $pos )).substr( $value, $pos );
|
1528 |
+
$value = str_replace( 'mailto:', 'MAILTO:', $value );
|
1529 |
+
}
|
1530 |
+
$this->organizer = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
1531 |
+
if( isset( $this->organizer['params']['SENT-BY'] )){
|
1532 |
+
if( 'mailto:' !== strtolower( substr( $this->organizer['params']['SENT-BY'], 0, 7 )))
|
1533 |
+
$this->organizer['params']['SENT-BY'] = 'MAILTO:'.$this->organizer['params']['SENT-BY'];
|
1534 |
+
else
|
1535 |
+
$this->organizer['params']['SENT-BY'] = 'MAILTO:'.substr( $this->organizer['params']['SENT-BY'], 7 );
|
1536 |
+
}
|
1537 |
+
return TRUE;
|
1538 |
+
}
|
1539 |
+
/*********************************************************************************/
|
1540 |
+
/**
|
1541 |
+
* Property Name: PERCENT-COMPLETE
|
1542 |
+
*/
|
1543 |
+
/**
|
1544 |
+
* creates formatted output for calendar component property percent-complete
|
1545 |
+
*
|
1546 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1547 |
+
* @since 2.9.3 - 2011-05-14
|
1548 |
+
* @uses calendarComponent::$percentcomplete
|
1549 |
+
* @uses calendarComponent::getConfig()
|
1550 |
+
* @uses calendarComponent::_createElement()
|
1551 |
+
* @uses calendarComponent::_createParams()
|
1552 |
+
* @return string
|
1553 |
+
*/
|
1554 |
+
function createPercentComplete() {
|
1555 |
+
if( !isset($this->percentcomplete) || ( empty( $this->percentcomplete ) && !is_numeric( $this->percentcomplete ))) return FALSE;
|
1556 |
+
if( !isset( $this->percentcomplete['value'] ) || ( empty( $this->percentcomplete['value'] ) && !is_numeric( $this->percentcomplete['value'] )))
|
1557 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'PERCENT-COMPLETE' ) : FALSE;
|
1558 |
+
$attributes = $this->_createParams( $this->percentcomplete['params'] );
|
1559 |
+
return $this->_createElement( 'PERCENT-COMPLETE', $attributes, $this->percentcomplete['value'] );
|
1560 |
+
}
|
1561 |
+
/**
|
1562 |
+
* set calendar component property percent-complete
|
1563 |
+
*
|
1564 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1565 |
+
* @since 2.16.21 - 2013-06-23
|
1566 |
+
* @param int $value
|
1567 |
+
* @param array $params
|
1568 |
+
* @uses calendarComponent::$percentcomplete
|
1569 |
+
* @uses calendarComponent::getConfig()
|
1570 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1571 |
+
* @return bool
|
1572 |
+
*/
|
1573 |
+
function setPercentComplete( $value, $params=FALSE ) {
|
1574 |
+
if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
1575 |
+
$this->percentcomplete = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
1576 |
+
return TRUE;
|
1577 |
+
}
|
1578 |
+
/*********************************************************************************/
|
1579 |
+
/**
|
1580 |
+
* Property Name: PRIORITY
|
1581 |
+
*/
|
1582 |
+
/**
|
1583 |
+
* creates formatted output for calendar component property priority
|
1584 |
+
*
|
1585 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1586 |
+
* @since 2.9.3 - 2011-05-14
|
1587 |
+
* @uses calendarComponent::$priority
|
1588 |
+
* @uses calendarComponent::getConfig()
|
1589 |
+
* @uses calendarComponent::_createElement()
|
1590 |
+
* @uses calendarComponent::_createParams()
|
1591 |
+
* @return string
|
1592 |
+
*/
|
1593 |
+
function createPriority() {
|
1594 |
+
if( !isset($this->priority) || ( empty( $this->priority ) && !is_numeric( $this->priority ))) return FALSE;
|
1595 |
+
if( !isset( $this->priority['value'] ) || ( empty( $this->priority['value'] ) && !is_numeric( $this->priority['value'] )))
|
1596 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'PRIORITY' ) : FALSE;
|
1597 |
+
$attributes = $this->_createParams( $this->priority['params'] );
|
1598 |
+
return $this->_createElement( 'PRIORITY', $attributes, $this->priority['value'] );
|
1599 |
+
}
|
1600 |
+
/**
|
1601 |
+
* set calendar component property priority
|
1602 |
+
*
|
1603 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1604 |
+
* @since 2.16.21 - 2013-06-23
|
1605 |
+
* @param int $value
|
1606 |
+
* @param array $params
|
1607 |
+
* @uses calendarComponent::getConfig()
|
1608 |
+
* @uses calendarComponent::$priority
|
1609 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1610 |
+
* @return bool
|
1611 |
+
*/
|
1612 |
+
function setPriority( $value, $params=FALSE ) {
|
1613 |
+
if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
1614 |
+
$this->priority = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
1615 |
+
return TRUE;
|
1616 |
+
}
|
1617 |
+
/*********************************************************************************/
|
1618 |
+
/**
|
1619 |
+
* Property Name: RDATE
|
1620 |
+
*/
|
1621 |
+
/**
|
1622 |
+
* creates formatted output for calendar component property rdate
|
1623 |
+
*
|
1624 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1625 |
+
* @since 2.16.9 - 2013-01-09
|
1626 |
+
* @uses calendarComponent::$rdate
|
1627 |
+
* @uses calendarComponent::$objName
|
1628 |
+
* @uses calendarComponent::getConfig()
|
1629 |
+
* @uses calendarComponent::_createElement()
|
1630 |
+
* @uses iCalUtilityFunctions::_sortRdate1()
|
1631 |
+
* @uses iCalUtilityFunctions::_sortRdate2()
|
1632 |
+
* @uses calendarComponent::_createParams()
|
1633 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
1634 |
+
* @return string
|
1635 |
+
*/
|
1636 |
+
function createRdate() {
|
1637 |
+
if( empty( $this->rdate )) return FALSE;
|
1638 |
+
$utctime = ( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' ))) ? TRUE : FALSE;
|
1639 |
+
$output = null;
|
1640 |
+
$rdates = array();
|
1641 |
+
foreach( $this->rdate as $rpix => $theRdate ) {
|
1642 |
+
if( empty( $theRdate['value'] )) {
|
1643 |
+
if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'RDATE' );
|
1644 |
+
continue;
|
1645 |
+
}
|
1646 |
+
if( $utctime )
|
1647 |
+
unset( $theRdate['params']['TZID'] );
|
1648 |
+
if( 1 < count( $theRdate['value'] ))
|
1649 |
+
usort( $theRdate['value'], array( 'iCalUtilityFunctions', '_sortRdate1' ));
|
1650 |
+
$rdates[] = $theRdate;
|
1651 |
+
}
|
1652 |
+
if( 1 < count( $rdates ))
|
1653 |
+
usort( $rdates, array( 'iCalUtilityFunctions', '_sortRdate2' ));
|
1654 |
+
foreach( $rdates as $rpix => $theRdate ) {
|
1655 |
+
$attributes = $this->_createParams( $theRdate['params'] );
|
1656 |
+
$cnt = count( $theRdate['value'] );
|
1657 |
+
$content = null;
|
1658 |
+
$rno = 1;
|
1659 |
+
foreach( $theRdate['value'] as $rix => $rdatePart ) {
|
1660 |
+
$contentPart = null;
|
1661 |
+
if( is_array( $rdatePart ) &&
|
1662 |
+
isset( $theRdate['params']['VALUE'] ) && ( 'PERIOD' == $theRdate['params']['VALUE'] )) { // PERIOD
|
1663 |
+
if( $utctime )
|
1664 |
+
unset( $rdatePart[0]['tz'] );
|
1665 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $rdatePart[0] ); // PERIOD part 1
|
1666 |
+
if( $utctime || !empty( $theRdate['params']['TZID'] ))
|
1667 |
+
$formatted = str_replace( 'Z', '', $formatted);
|
1668 |
+
$contentPart .= $formatted;
|
1669 |
+
$contentPart .= '/';
|
1670 |
+
$cnt2 = count( $rdatePart[1]);
|
1671 |
+
if( array_key_exists( 'year', $rdatePart[1] )) {
|
1672 |
+
if( array_key_exists( 'hour', $rdatePart[1] ))
|
1673 |
+
$cnt2 = 7; // date-time
|
1674 |
+
else
|
1675 |
+
$cnt2 = 3; // date
|
1676 |
+
}
|
1677 |
+
elseif( array_key_exists( 'week', $rdatePart[1] )) // duration
|
1678 |
+
$cnt2 = 5;
|
1679 |
+
if(( 7 == $cnt2 ) && // period= -> date-time
|
1680 |
+
isset( $rdatePart[1]['year'] ) &&
|
1681 |
+
isset( $rdatePart[1]['month'] ) &&
|
1682 |
+
isset( $rdatePart[1]['day'] )) {
|
1683 |
+
if( $utctime )
|
1684 |
+
unset( $rdatePart[1]['tz'] );
|
1685 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $rdatePart[1] ); // PERIOD part 2
|
1686 |
+
if( $utctime || !empty( $theRdate['params']['TZID'] ))
|
1687 |
+
$formatted = str_replace( 'Z', '', $formatted );
|
1688 |
+
$contentPart .= $formatted;
|
1689 |
+
}
|
1690 |
+
else { // period= -> dur-time
|
1691 |
+
$contentPart .= iCalUtilityFunctions::_duration2str( $rdatePart[1] );
|
1692 |
+
}
|
1693 |
+
} // PERIOD end
|
1694 |
+
else { // SINGLE date start
|
1695 |
+
if( $utctime )
|
1696 |
+
unset( $rdatePart['tz'] );
|
1697 |
+
$parno = ( isset( $theRdate['params']['VALUE'] ) && ( 'DATE' == isset( $theRdate['params']['VALUE'] ))) ? 3 : null;
|
1698 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $rdatePart, $parno );
|
1699 |
+
if( $utctime || !empty( $theRdate['params']['TZID'] ))
|
1700 |
+
$formatted = str_replace( 'Z', '', $formatted);
|
1701 |
+
$contentPart .= $formatted;
|
1702 |
+
}
|
1703 |
+
$content .= $contentPart;
|
1704 |
+
if( $rno < $cnt )
|
1705 |
+
$content .= ',';
|
1706 |
+
$rno++;
|
1707 |
+
}
|
1708 |
+
$output .= $this->_createElement( 'RDATE', $attributes, $content );
|
1709 |
+
}
|
1710 |
+
return $output;
|
1711 |
+
}
|
1712 |
+
/**
|
1713 |
+
* set calendar component property rdate
|
1714 |
+
*
|
1715 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1716 |
+
* @since 2.21.11 - 2015-03-10
|
1717 |
+
* @param array $rdates
|
1718 |
+
* @param array $params
|
1719 |
+
* @param integer $index
|
1720 |
+
* @uses calendarComponent::getConfig()
|
1721 |
+
* @uses iCalUtilityFunctions::_setMval()
|
1722 |
+
* @uses calendarComponent::$rdate
|
1723 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1724 |
+
* @uses calendarComponent::$objName
|
1725 |
+
* @uses iCalUtilityFunctions::_isArrayDate()
|
1726 |
+
* @uses iCalUtilityFunctions::_chkdatecfg()
|
1727 |
+
* @uses iCalUtilityFunctions::_existRem()
|
1728 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
1729 |
+
* @uses iCalUtilityFunctions::_isArrayTimestampDate()
|
1730 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
1731 |
+
* @uses iCalUtilityFunctions::_timestamp2date()
|
1732 |
+
* @uses iCalUtilityFunctions::_chkDateArr()
|
1733 |
+
* @uses iCalUtilityFunctions::$fmt
|
1734 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
1735 |
+
* @uses iCalUtilityFunctions::_duration2arr()
|
1736 |
+
* @uses iCalUtilityFunctions::_durationStr2arr()
|
1737 |
+
* @return bool
|
1738 |
+
*/
|
1739 |
+
function setRdate( $rdates, $params=FALSE, $index=FALSE ) {
|
1740 |
+
if( empty( $rdates )) {
|
1741 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
1742 |
+
iCalUtilityFunctions::_setMval( $this->rdate, '', $params, FALSE, $index );
|
1743 |
+
return TRUE;
|
1744 |
+
}
|
1745 |
+
else
|
1746 |
+
return FALSE;
|
1747 |
+
}
|
1748 |
+
$input = array( 'params' => iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' )));
|
1749 |
+
if( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' ))) {
|
1750 |
+
unset( $input['params']['TZID'] );
|
1751 |
+
$input['params']['VALUE'] = 'DATE-TIME';
|
1752 |
+
}
|
1753 |
+
$zArr = array( 'GMT', 'UTC', 'Z' );
|
1754 |
+
$toZ = ( isset( $params['TZID'] ) && in_array( strtoupper( $params['TZID'] ), $zArr )) ? TRUE : FALSE;
|
1755 |
+
/* check if PERIOD, if not set */
|
1756 |
+
if((!isset( $input['params']['VALUE'] ) || !in_array( $input['params']['VALUE'], array( 'DATE', 'PERIOD' ))) &&
|
1757 |
+
isset( $rdates[0] ) && is_array( $rdates[0] ) && ( 2 == count( $rdates[0] )) &&
|
1758 |
+
isset( $rdates[0][0] ) && isset( $rdates[0][1] ) && !isset( $rdates[0]['timestamp'] ) &&
|
1759 |
+
(( is_array( $rdates[0][0] ) && ( isset( $rdates[0][0]['timestamp'] ) ||
|
1760 |
+
iCalUtilityFunctions::_isArrayDate( $rdates[0][0] ))) ||
|
1761 |
+
( is_string( $rdates[0][0] ) && ( 8 <= strlen( trim( $rdates[0][0] ))))) &&
|
1762 |
+
( is_array( $rdates[0][1] ) || ( is_string( $rdates[0][1] ) && ( 3 <= strlen( trim( $rdates[0][1] ))))))
|
1763 |
+
$input['params']['VALUE'] = 'PERIOD';
|
1764 |
+
/* check 1:st date, upd. $parno (opt) and save ev. timezone **/
|
1765 |
+
$date = reset( $rdates );
|
1766 |
+
if( isset( $input['params']['VALUE'] ) && ( 'PERIOD' == $input['params']['VALUE'] )) // PERIOD
|
1767 |
+
$date = reset( $date );
|
1768 |
+
iCalUtilityFunctions::_chkdatecfg( $date, $parno, $input['params'] );
|
1769 |
+
iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME' ); // remove default
|
1770 |
+
foreach( $rdates as $rpix => $theRdate ) {
|
1771 |
+
$inputa = null;
|
1772 |
+
iCalUtilityFunctions::_strDate2arr( $theRdate );
|
1773 |
+
if( is_array( $theRdate )) {
|
1774 |
+
if( isset( $input['params']['VALUE'] ) && ( 'PERIOD' == $input['params']['VALUE'] )) { // PERIOD
|
1775 |
+
foreach( $theRdate as $rix => $rPeriod ) {
|
1776 |
+
iCalUtilityFunctions::_strDate2arr( $theRdate );
|
1777 |
+
if( is_array( $rPeriod )) {
|
1778 |
+
if( iCalUtilityFunctions::_isArrayTimestampDate( $rPeriod )) { // timestamp
|
1779 |
+
if( isset( $rPeriod['tz'] ) && !iCalUtilityFunctions::_isOffset( $rPeriod['tz'] )) {
|
1780 |
+
if( isset( $input['params']['TZID'] ))
|
1781 |
+
$rPeriod['tz'] = $input['params']['TZID'];
|
1782 |
+
else
|
1783 |
+
$input['params']['TZID'] = $rPeriod['tz'];
|
1784 |
+
}
|
1785 |
+
$inputab = iCalUtilityFunctions::_timestamp2date( $rPeriod, $parno );
|
1786 |
+
}
|
1787 |
+
elseif( iCalUtilityFunctions::_isArrayDate( $rPeriod )) {
|
1788 |
+
$d = ( 3 < count ( $rPeriod )) ? iCalUtilityFunctions::_chkDateArr( $rPeriod, $parno ) : iCalUtilityFunctions::_chkDateArr( $rPeriod, 6 );
|
1789 |
+
if( isset( $d['tz'] ) && ( 'Z' != $d['tz'] ) && iCalUtilityFunctions::_isOffset( $d['tz'] )) {
|
1790 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $d['tz'] );
|
1791 |
+
$inputab = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1792 |
+
unset( $inputab['unparsedtext'] );
|
1793 |
+
}
|
1794 |
+
else
|
1795 |
+
$inputab = $d;
|
1796 |
+
}
|
1797 |
+
elseif (( 1 == count( $rPeriod )) && ( 8 <= strlen( reset( $rPeriod )))) { // text-date
|
1798 |
+
$inputab = iCalUtilityFunctions::_strdate2date( reset( $rPeriod ), $parno );
|
1799 |
+
unset( $inputab['unparsedtext'] );
|
1800 |
+
}
|
1801 |
+
else // array format duration
|
1802 |
+
$inputab = iCalUtilityFunctions::_duration2arr( $rPeriod );
|
1803 |
+
}
|
1804 |
+
elseif(( 3 <= strlen( trim( $rPeriod ))) && // string format duration
|
1805 |
+
( in_array( $rPeriod[0], array( 'P', '+', '-' )))) {
|
1806 |
+
if( 'P' != $rPeriod[0] )
|
1807 |
+
$rPeriod = substr( $rPeriod, 1 );
|
1808 |
+
$inputab = iCalUtilityFunctions::_durationStr2arr( $rPeriod );
|
1809 |
+
}
|
1810 |
+
elseif( 8 <= strlen( trim( $rPeriod ))) { // text date ex. 2006-08-03 10:12:18
|
1811 |
+
$inputab = iCalUtilityFunctions::_strdate2date( $rPeriod, $parno );
|
1812 |
+
unset( $inputab['unparsedtext'] );
|
1813 |
+
}
|
1814 |
+
if(( 0 == $rpix ) && ( 0 == $rix )) {
|
1815 |
+
if( isset( $inputab['tz'] ) && in_array( strtoupper( $inputab['tz'] ), $zArr )) {
|
1816 |
+
$inputab['tz'] = 'Z';
|
1817 |
+
$toZ = TRUE;
|
1818 |
+
}
|
1819 |
+
}
|
1820 |
+
else {
|
1821 |
+
if( isset( $inputa[0]['tz'] ) && ( 'Z' == $inputa[0]['tz'] ) && isset( $inputab['year'] ))
|
1822 |
+
$inputab['tz'] = 'Z';
|
1823 |
+
else
|
1824 |
+
unset( $inputab['tz'] );
|
1825 |
+
}
|
1826 |
+
if( $toZ && isset( $inputab['year'] ) )
|
1827 |
+
$inputab['tz'] = 'Z';
|
1828 |
+
$inputa[] = $inputab;
|
1829 |
+
}
|
1830 |
+
} // PERIOD end
|
1831 |
+
elseif ( iCalUtilityFunctions::_isArrayTimestampDate( $theRdate )) { // timestamp
|
1832 |
+
if( isset( $theRdate['tz'] ) && !iCalUtilityFunctions::_isOffset( $theRdate['tz'] )) {
|
1833 |
+
if( isset( $input['params']['TZID'] ))
|
1834 |
+
$theRdate['tz'] = $input['params']['TZID'];
|
1835 |
+
else
|
1836 |
+
$input['params']['TZID'] = $theRdate['tz'];
|
1837 |
+
}
|
1838 |
+
$inputa = iCalUtilityFunctions::_timestamp2date( $theRdate, $parno );
|
1839 |
+
}
|
1840 |
+
else { // date[-time]
|
1841 |
+
$inputa = iCalUtilityFunctions::_chkDateArr( $theRdate, $parno );
|
1842 |
+
if( isset( $inputa['tz'] ) && ( 'Z' != $inputa['tz'] ) && iCalUtilityFunctions::_isOffset( $inputa['tz'] )) {
|
1843 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $inputa['year'], (int) $inputa['month'], (int) $inputa['day'], (int) $inputa['hour'], (int) $inputa['min'], (int) $inputa['sec'], $inputa['tz'] );
|
1844 |
+
$inputa = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1845 |
+
unset( $inputa['unparsedtext'] );
|
1846 |
+
}
|
1847 |
+
}
|
1848 |
+
}
|
1849 |
+
elseif( 8 <= strlen( trim( $theRdate ))) { // text date ex. 2006-08-03 10:12:18
|
1850 |
+
$inputa = iCalUtilityFunctions::_strdate2date( $theRdate, $parno );
|
1851 |
+
unset( $inputa['unparsedtext'] );
|
1852 |
+
if( $toZ )
|
1853 |
+
$inputa['tz'] = 'Z';
|
1854 |
+
}
|
1855 |
+
if( !isset( $input['params']['VALUE'] ) || ( 'PERIOD' != $input['params']['VALUE'] )) { // no PERIOD
|
1856 |
+
if(( 0 == $rpix ) && !$toZ )
|
1857 |
+
$toZ = ( isset( $inputa['tz'] ) && in_array( strtoupper( $inputa['tz'] ), $zArr )) ? TRUE : FALSE;
|
1858 |
+
if( $toZ )
|
1859 |
+
$inputa['tz'] = 'Z';
|
1860 |
+
if( 3 == $parno )
|
1861 |
+
unset( $inputa['hour'], $inputa['min'], $inputa['sec'], $inputa['tz'] );
|
1862 |
+
elseif( isset( $inputa['tz'] ))
|
1863 |
+
$inputa['tz'] = (string) $inputa['tz'];
|
1864 |
+
if( isset( $input['params']['TZID'] ) || ( isset( $input['value'][0] ) && ( !isset( $input['value'][0]['tz'] ))))
|
1865 |
+
if( !$toZ )
|
1866 |
+
unset( $inputa['tz'] );
|
1867 |
+
}
|
1868 |
+
$input['value'][] = $inputa;
|
1869 |
+
}
|
1870 |
+
if( 3 == $parno ) {
|
1871 |
+
$input['params']['VALUE'] = 'DATE';
|
1872 |
+
unset( $input['params']['TZID'] );
|
1873 |
+
}
|
1874 |
+
if( $toZ )
|
1875 |
+
unset( $input['params']['TZID'] );
|
1876 |
+
iCalUtilityFunctions::_setMval( $this->rdate, $input['value'], $input['params'], FALSE, $index );
|
1877 |
+
return TRUE;
|
1878 |
+
}
|
1879 |
+
/*********************************************************************************/
|
1880 |
+
/**
|
1881 |
+
* Property Name: RECURRENCE-ID
|
1882 |
+
*/
|
1883 |
+
/**
|
1884 |
+
* creates formatted output for calendar component property recurrence-id
|
1885 |
+
*
|
1886 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1887 |
+
* @since 2.14.4 - 2012-09-26
|
1888 |
+
* @uses calendarComponent::$recurrenceid
|
1889 |
+
* @uses calendarComponent::getConfig()
|
1890 |
+
* @uses calendarComponent::_createElement()
|
1891 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
1892 |
+
* @uses calendarComponent::_createParams()
|
1893 |
+
* @return string
|
1894 |
+
*/
|
1895 |
+
function createRecurrenceid() {
|
1896 |
+
if( empty( $this->recurrenceid )) return FALSE;
|
1897 |
+
if( empty( $this->recurrenceid['value'] ))
|
1898 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'RECURRENCE-ID' ) : FALSE;
|
1899 |
+
$parno = ( isset( $this->recurrenceid['params']['VALUE'] ) && ( 'DATE' == $this->recurrenceid['params']['VALUE'] )) ? 3 : null;
|
1900 |
+
$formatted = iCalUtilityFunctions::_date2strdate( $this->recurrenceid['value'], $parno );
|
1901 |
+
$attributes = $this->_createParams( $this->recurrenceid['params'] );
|
1902 |
+
return $this->_createElement( 'RECURRENCE-ID', $attributes, $formatted );
|
1903 |
+
}
|
1904 |
+
/**
|
1905 |
+
* set calendar component property recurrence-id
|
1906 |
+
*
|
1907 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1908 |
+
* @since 2.16.21 - 2013-06-23
|
1909 |
+
* @param mixed $year
|
1910 |
+
* @param mixed $month
|
1911 |
+
* @param int $day
|
1912 |
+
* @param int $hour
|
1913 |
+
* @param int $min
|
1914 |
+
* @param int $sec
|
1915 |
+
* @param string $tz
|
1916 |
+
* @param array $params
|
1917 |
+
* @uses calendarComponent::getConfig()
|
1918 |
+
* @uses calendarComponent::$recurrenceid
|
1919 |
+
* @uses iCalUtilityFunctions::_setDate()
|
1920 |
+
* @return bool
|
1921 |
+
*/
|
1922 |
+
function setRecurrenceid( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
|
1923 |
+
if( empty( $year )) {
|
1924 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
1925 |
+
$this->recurrenceid = array( 'value' => '', 'params' => null );
|
1926 |
+
return TRUE;
|
1927 |
+
}
|
1928 |
+
else
|
1929 |
+
return FALSE;
|
1930 |
+
}
|
1931 |
+
$this->recurrenceid = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
|
1932 |
+
return TRUE;
|
1933 |
+
}
|
1934 |
+
/*********************************************************************************/
|
1935 |
+
/**
|
1936 |
+
* Property Name: RELATED-TO
|
1937 |
+
*/
|
1938 |
+
/**
|
1939 |
+
* creates formatted output for calendar component property related-to
|
1940 |
+
*
|
1941 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1942 |
+
* @since 2.16.21 - 2013-05-25
|
1943 |
+
* @uses calendarComponent::$relatedto
|
1944 |
+
* @uses calendarComponent::_createElement()
|
1945 |
+
* @uses calendarComponent::_createParams()
|
1946 |
+
* @uses iCalUtilityFunctions::_strrep()
|
1947 |
+
* @uses calendarComponent::getConfig()
|
1948 |
+
* @return string
|
1949 |
+
*/
|
1950 |
+
function createRelatedTo() {
|
1951 |
+
if( empty( $this->relatedto )) return FALSE;
|
1952 |
+
$output = null;
|
1953 |
+
foreach( $this->relatedto as $relation ) {
|
1954 |
+
if( !empty( $relation['value'] ))
|
1955 |
+
$output .= $this->_createElement( 'RELATED-TO', $this->_createParams( $relation['params'] ), iCalUtilityFunctions::_strrep( $relation['value'], $this->format, $this->nl ));
|
1956 |
+
elseif( $this->getConfig( 'allowEmpty' ))
|
1957 |
+
$output .= $this->_createElement( 'RELATED-TO' );
|
1958 |
+
}
|
1959 |
+
return $output;
|
1960 |
+
}
|
1961 |
+
/**
|
1962 |
+
* set calendar component property related-to
|
1963 |
+
*
|
1964 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1965 |
+
* @since 2.16.21 - 2013-06-23
|
1966 |
+
* @param string $value
|
1967 |
+
* @param array $params
|
1968 |
+
* @param int $index
|
1969 |
+
* @uses calendarComponent::getConfig()
|
1970 |
+
* @uses iCalUtilityFunctions::_existRem()
|
1971 |
+
* @uses iCalUtilityFunctions::_setMval()
|
1972 |
+
* @return bool
|
1973 |
+
*/
|
1974 |
+
function setRelatedTo( $value, $params=FALSE, $index=FALSE ) {
|
1975 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
1976 |
+
iCalUtilityFunctions::_existRem( $params, 'RELTYPE', 'PARENT', TRUE ); // remove default
|
1977 |
+
iCalUtilityFunctions::_setMval( $this->relatedto, $value, $params, FALSE, $index );
|
1978 |
+
return TRUE;
|
1979 |
+
}
|
1980 |
+
/*********************************************************************************/
|
1981 |
+
/**
|
1982 |
+
* Property Name: REPEAT
|
1983 |
+
*/
|
1984 |
+
/**
|
1985 |
+
* creates formatted output for calendar component property repeat
|
1986 |
+
*
|
1987 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1988 |
+
* @since 2.9.3 - 2011-05-14
|
1989 |
+
* @uses calendarComponent::$repeat
|
1990 |
+
* @uses calendarComponent::getConfig()
|
1991 |
+
* @uses calendarComponent::_createElement()
|
1992 |
+
* @uses calendarComponent::_createParams()
|
1993 |
+
* @return string
|
1994 |
+
*/
|
1995 |
+
function createRepeat() {
|
1996 |
+
if( !isset( $this->repeat ) || ( empty( $this->repeat ) && !is_numeric( $this->repeat ))) return FALSE;
|
1997 |
+
if( !isset( $this->repeat['value']) || ( empty( $this->repeat['value'] ) && !is_numeric( $this->repeat['value'] )))
|
1998 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'REPEAT' ) : FALSE;
|
1999 |
+
$attributes = $this->_createParams( $this->repeat['params'] );
|
2000 |
+
return $this->_createElement( 'REPEAT', $attributes, $this->repeat['value'] );
|
2001 |
+
}
|
2002 |
+
/**
|
2003 |
+
* set calendar component property repeat
|
2004 |
+
*
|
2005 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2006 |
+
* @since 2.16.21 - 2013-06-23
|
2007 |
+
* @param string $value
|
2008 |
+
* @param array $params
|
2009 |
+
* @uses calendarComponent::getConfig()
|
2010 |
+
* @uses calendarComponent::$repeat
|
2011 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2012 |
+
* @return void
|
2013 |
+
*/
|
2014 |
+
function setRepeat( $value, $params=FALSE ) {
|
2015 |
+
if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2016 |
+
$this->repeat = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2017 |
+
return TRUE;
|
2018 |
+
}
|
2019 |
+
/*********************************************************************************/
|
2020 |
+
/**
|
2021 |
+
* Property Name: REQUEST-STATUS
|
2022 |
+
*/
|
2023 |
+
/**
|
2024 |
+
* creates formatted output for calendar component property request-status
|
2025 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2026 |
+
* @since 2.16.2 - 2012-12-18
|
2027 |
+
* @uses calendarComponent::$requeststatus
|
2028 |
+
* @uses calendarComponent::getConfig()
|
2029 |
+
* @uses calendarComponent::_createElement()
|
2030 |
+
* @uses calendarComponent::_createParams()
|
2031 |
+
* @uses iCalUtilityFunctions::_strrep()
|
2032 |
+
* @return string
|
2033 |
+
*/
|
2034 |
+
function createRequestStatus() {
|
2035 |
+
if( empty( $this->requeststatus )) return FALSE;
|
2036 |
+
$output = null;
|
2037 |
+
foreach( $this->requeststatus as $rstat ) {
|
2038 |
+
if( empty( $rstat['value']['statcode'] )) {
|
2039 |
+
if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'REQUEST-STATUS' );
|
2040 |
+
continue;
|
2041 |
+
}
|
2042 |
+
$attributes = $this->_createParams( $rstat['params'], array( 'LANGUAGE' ));
|
2043 |
+
$content = number_format( (float) $rstat['value']['statcode'], 2, '.', '');
|
2044 |
+
$content .= ';'.iCalUtilityFunctions::_strrep( $rstat['value']['text'], $this->format, $this->nl );
|
2045 |
+
if( isset( $rstat['value']['extdata'] ))
|
2046 |
+
$content .= ';'.iCalUtilityFunctions::_strrep( $rstat['value']['extdata'], $this->format, $this->nl );
|
2047 |
+
$output .= $this->_createElement( 'REQUEST-STATUS', $attributes, $content );
|
2048 |
+
}
|
2049 |
+
return $output;
|
2050 |
+
}
|
2051 |
+
/**
|
2052 |
+
* set calendar component property request-status
|
2053 |
+
*
|
2054 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2055 |
+
* @since 2.16.21 - 2013-06-23
|
2056 |
+
* @param float $statcode
|
2057 |
+
* @param string $text
|
2058 |
+
* @param string $extdata
|
2059 |
+
* @param array $params
|
2060 |
+
* @param integer $index
|
2061 |
+
* @uses calendarComponent::getConfig()
|
2062 |
+
* @uses calendarComponent::$requeststatus
|
2063 |
+
* @uses iCalUtilityFunctions::_setMval()
|
2064 |
+
* @return bool
|
2065 |
+
*/
|
2066 |
+
function setRequestStatus( $statcode, $text, $extdata=FALSE, $params=FALSE, $index=FALSE ) {
|
2067 |
+
if( empty( $statcode ) || empty( $text )) if( $this->getConfig( 'allowEmpty' )) $statcode = $text = ''; else return FALSE;
|
2068 |
+
$input = array( 'statcode' => $statcode, 'text' => $text );
|
2069 |
+
if( $extdata )
|
2070 |
+
$input['extdata'] = $extdata;
|
2071 |
+
iCalUtilityFunctions::_setMval( $this->requeststatus, $input, $params, FALSE, $index );
|
2072 |
+
return TRUE;
|
2073 |
+
}
|
2074 |
+
/*********************************************************************************/
|
2075 |
+
/**
|
2076 |
+
* Property Name: RESOURCES
|
2077 |
+
*/
|
2078 |
+
/**
|
2079 |
+
* creates formatted output for calendar component property resources
|
2080 |
+
*
|
2081 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2082 |
+
* @since 2.16.2 - 2012-12-18
|
2083 |
+
* @uses calendarComponent::$resources
|
2084 |
+
* @uses calendarComponent::getConfig()
|
2085 |
+
* @uses calendarComponent::_createElement()
|
2086 |
+
* @uses calendarComponent::_createParams()
|
2087 |
+
* @uses iCalUtilityFunctions::_strrep()
|
2088 |
+
* @return string
|
2089 |
+
*/
|
2090 |
+
function createResources() {
|
2091 |
+
if( empty( $this->resources )) return FALSE;
|
2092 |
+
$output = null;
|
2093 |
+
foreach( $this->resources as $resource ) {
|
2094 |
+
if( empty( $resource['value'] )) {
|
2095 |
+
if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'RESOURCES' );
|
2096 |
+
continue;
|
2097 |
+
}
|
2098 |
+
$attributes = $this->_createParams( $resource['params'], array( 'ALTREP', 'LANGUAGE' ));
|
2099 |
+
if( is_array( $resource['value'] )) {
|
2100 |
+
foreach( $resource['value'] as $rix => $resourcePart )
|
2101 |
+
$resource['value'][$rix] = iCalUtilityFunctions::_strrep( $resourcePart, $this->format, $this->nl );
|
2102 |
+
$content = implode( ',', $resource['value'] );
|
2103 |
+
}
|
2104 |
+
else
|
2105 |
+
$content = iCalUtilityFunctions::_strrep( $resource['value'], $this->format, $this->nl );
|
2106 |
+
$output .= $this->_createElement( 'RESOURCES', $attributes, $content );
|
2107 |
+
}
|
2108 |
+
return $output;
|
2109 |
+
}
|
2110 |
+
/**
|
2111 |
+
* set calendar component property recources
|
2112 |
+
*
|
2113 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2114 |
+
* @since 2.16.21 - 2013-06-23
|
2115 |
+
* @param mixed $value
|
2116 |
+
* @param array $params
|
2117 |
+
* @param integer $index
|
2118 |
+
* @uses calendarComponent::getConfig()
|
2119 |
+
* @uses iCalUtilityFunctions::_setMval()
|
2120 |
+
* @uses calendarComponent::$resources
|
2121 |
+
* @return bool
|
2122 |
+
*/
|
2123 |
+
function setResources( $value, $params=FALSE, $index=FALSE ) {
|
2124 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2125 |
+
iCalUtilityFunctions::_setMval( $this->resources, $value, $params, FALSE, $index );
|
2126 |
+
return TRUE;
|
2127 |
+
}
|
2128 |
+
/*********************************************************************************/
|
2129 |
+
/**
|
2130 |
+
* Property Name: RRULE
|
2131 |
+
*/
|
2132 |
+
/**
|
2133 |
+
* creates formatted output for calendar component property rrule
|
2134 |
+
*
|
2135 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2136 |
+
* @since 2.4.8 - 2008-10-21
|
2137 |
+
* @uses calendarComponent::$rrule
|
2138 |
+
* @uses calendarComponent::_format_recur()
|
2139 |
+
* @return string
|
2140 |
+
*/
|
2141 |
+
function createRrule() {
|
2142 |
+
if( empty( $this->rrule )) return FALSE;
|
2143 |
+
return $this->_format_recur( 'RRULE', $this->rrule );
|
2144 |
+
}
|
2145 |
+
/**
|
2146 |
+
* set calendar component property rrule
|
2147 |
+
*
|
2148 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2149 |
+
* @since 2.16.21 - 2013-06-23
|
2150 |
+
* @param array $rruleset
|
2151 |
+
* @param array $params
|
2152 |
+
* @param integer $index
|
2153 |
+
* @uses calendarComponent::getConfig()
|
2154 |
+
* @uses iCalUtilityFunctions::_setMval()
|
2155 |
+
* @uses iCalUtilityFunctions::_setRexrule()
|
2156 |
+
* @return void
|
2157 |
+
*/
|
2158 |
+
function setRrule( $rruleset, $params=FALSE, $index=FALSE ) {
|
2159 |
+
if( empty( $rruleset )) if( $this->getConfig( 'allowEmpty' )) $rruleset = ''; else return FALSE;
|
2160 |
+
iCalUtilityFunctions::_setMval( $this->rrule, iCalUtilityFunctions::_setRexrule( $rruleset ), $params, FALSE, $index );
|
2161 |
+
return TRUE;
|
2162 |
+
}
|
2163 |
+
/*********************************************************************************/
|
2164 |
+
/**
|
2165 |
+
* Property Name: SEQUENCE
|
2166 |
+
*/
|
2167 |
+
/**
|
2168 |
+
* creates formatted output for calendar component property sequence
|
2169 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2170 |
+
* @since 2.9.3 - 2011-05-14
|
2171 |
+
* @uses calendarComponent::$sequence
|
2172 |
+
* @uses calendarComponent::getConfig()
|
2173 |
+
* @uses calendarComponent::_createElement()
|
2174 |
+
* @uses calendarComponent::_createParams()
|
2175 |
+
* @return string
|
2176 |
+
*/
|
2177 |
+
function createSequence() {
|
2178 |
+
if( !isset( $this->sequence ) || ( empty( $this->sequence ) && !is_numeric( $this->sequence ))) return FALSE;
|
2179 |
+
if(( !isset($this->sequence['value'] ) || ( empty( $this->sequence['value'] ) && !is_numeric( $this->sequence['value'] ))) &&
|
2180 |
+
( '0' != $this->sequence['value'] ))
|
2181 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'SEQUENCE' ) : FALSE;
|
2182 |
+
$attributes = $this->_createParams( $this->sequence['params'] );
|
2183 |
+
return $this->_createElement( 'SEQUENCE', $attributes, $this->sequence['value'] );
|
2184 |
+
}
|
2185 |
+
/**
|
2186 |
+
* set calendar component property sequence
|
2187 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2188 |
+
* @since 2.10.8 - 2011-09-19
|
2189 |
+
* @param int $value
|
2190 |
+
* @param array $params
|
2191 |
+
* @uses calendarComponent::$sequence
|
2192 |
+
* @uses iCalUtilityFunctions::_setParams();
|
2193 |
+
* @return bool
|
2194 |
+
*/
|
2195 |
+
function setSequence( $value=FALSE, $params=FALSE ) {
|
2196 |
+
if(( empty( $value ) && !is_numeric( $value )) && ( '0' != $value ))
|
2197 |
+
$value = ( isset( $this->sequence['value'] ) && ( -1 < $this->sequence['value'] )) ? $this->sequence['value'] + 1 : '0';
|
2198 |
+
$this->sequence = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2199 |
+
return TRUE;
|
2200 |
+
}
|
2201 |
+
/*********************************************************************************/
|
2202 |
+
/**
|
2203 |
+
* Property Name: STATUS
|
2204 |
+
*/
|
2205 |
+
/**
|
2206 |
+
* creates formatted output for calendar component property status
|
2207 |
+
*
|
2208 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2209 |
+
* @since 2.4.8 - 2008-10-21
|
2210 |
+
* @uses calendarComponent::$status
|
2211 |
+
* @uses calendarComponent::getConfig()
|
2212 |
+
* @uses calendarComponent::_createElement()
|
2213 |
+
* @uses calendarComponent::_createParams()
|
2214 |
+
* @return string
|
2215 |
+
*/
|
2216 |
+
function createStatus() {
|
2217 |
+
if( empty( $this->status )) return FALSE;
|
2218 |
+
if( empty( $this->status['value'] ))
|
2219 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'STATUS' ) : FALSE;
|
2220 |
+
$attributes = $this->_createParams( $this->status['params'] );
|
2221 |
+
return $this->_createElement( 'STATUS', $attributes, $this->status['value'] );
|
2222 |
+
}
|
2223 |
+
/**
|
2224 |
+
* set calendar component property status
|
2225 |
+
*
|
2226 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2227 |
+
* @since 2.16.21 - 2013-06-23
|
2228 |
+
* @param string $value
|
2229 |
+
* @param array $params
|
2230 |
+
* @uses calendarComponent::getConfig()
|
2231 |
+
* @uses calendarComponent::$status
|
2232 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2233 |
+
* @return bool
|
2234 |
+
*/
|
2235 |
+
function setStatus( $value, $params=FALSE ) {
|
2236 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2237 |
+
$this->status = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2238 |
+
return TRUE;
|
2239 |
+
}
|
2240 |
+
/*********************************************************************************/
|
2241 |
+
/**
|
2242 |
+
* Property Name: SUMMARY
|
2243 |
+
*/
|
2244 |
+
/**
|
2245 |
+
* creates formatted output for calendar component property summary
|
2246 |
+
*
|
2247 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2248 |
+
* @since 2.16.2 - 2012-12-18
|
2249 |
+
* @uses calendarComponent::$summary
|
2250 |
+
* @uses calendarComponent::getConfig()
|
2251 |
+
* @uses calendarComponent::_createElement()
|
2252 |
+
* @uses calendarComponent::_createParams()
|
2253 |
+
* @uses iCalUtilityFunctions::_strrep()
|
2254 |
+
* @return string
|
2255 |
+
*/
|
2256 |
+
function createSummary() {
|
2257 |
+
if( empty( $this->summary )) return FALSE;
|
2258 |
+
if( empty( $this->summary['value'] ))
|
2259 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'SUMMARY' ) : FALSE;
|
2260 |
+
$attributes = $this->_createParams( $this->summary['params'], array( 'ALTREP', 'LANGUAGE' ));
|
2261 |
+
$content = iCalUtilityFunctions::_strrep( $this->summary['value'], $this->format, $this->nl );
|
2262 |
+
return $this->_createElement( 'SUMMARY', $attributes, $content );
|
2263 |
+
}
|
2264 |
+
/**
|
2265 |
+
* set calendar component property summary
|
2266 |
+
*
|
2267 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2268 |
+
* @since 2.16.21 - 2013-06-23
|
2269 |
+
* @param string $value
|
2270 |
+
* @param string $params
|
2271 |
+
* @uses calendarComponent::getConfig()
|
2272 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2273 |
+
* @return bool
|
2274 |
+
*/
|
2275 |
+
function setSummary( $value, $params=FALSE ) {
|
2276 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2277 |
+
$this->summary = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2278 |
+
return TRUE;
|
2279 |
+
}
|
2280 |
+
/*********************************************************************************/
|
2281 |
+
/**
|
2282 |
+
* Property Name: TRANSP
|
2283 |
+
*/
|
2284 |
+
/**
|
2285 |
+
* creates formatted output for calendar component property transp
|
2286 |
+
*
|
2287 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2288 |
+
* @since 2.4.8 - 2008-10-21
|
2289 |
+
* @uses calendarComponent::$transp
|
2290 |
+
* @uses calendarComponent::getConfig()
|
2291 |
+
* @uses calendarComponent::_createElement()
|
2292 |
+
* @uses calendarComponent::_createParams()
|
2293 |
+
* @return string
|
2294 |
+
*/
|
2295 |
+
function createTransp() {
|
2296 |
+
if( empty( $this->transp )) return FALSE;
|
2297 |
+
if( empty( $this->transp['value'] ))
|
2298 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TRANSP' ) : FALSE;
|
2299 |
+
$attributes = $this->_createParams( $this->transp['params'] );
|
2300 |
+
return $this->_createElement( 'TRANSP', $attributes, $this->transp['value'] );
|
2301 |
+
}
|
2302 |
+
/**
|
2303 |
+
* set calendar component property transp
|
2304 |
+
*
|
2305 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2306 |
+
* @since 2.16.21 - 2013-06-23
|
2307 |
+
* @param string $value
|
2308 |
+
* @param string $params
|
2309 |
+
* @uses calendarComponent::getConfig()
|
2310 |
+
* @uses calendarComponent::$transp
|
2311 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2312 |
+
* @return bool
|
2313 |
+
*/
|
2314 |
+
function setTransp( $value, $params=FALSE ) {
|
2315 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2316 |
+
$this->transp = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2317 |
+
return TRUE;
|
2318 |
+
}
|
2319 |
+
/*********************************************************************************/
|
2320 |
+
/**
|
2321 |
+
* Property Name: TRIGGER
|
2322 |
+
*/
|
2323 |
+
/**
|
2324 |
+
* creates formatted output for calendar component property trigger
|
2325 |
+
*
|
2326 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2327 |
+
* @since 2.4.16 - 2008-10-21
|
2328 |
+
* @uses calendarComponent::$trigger
|
2329 |
+
* @uses calendarComponent::getConfig()
|
2330 |
+
* @uses calendarComponent::_createElement()
|
2331 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
2332 |
+
* @uses calendarComponent::$intAttrDelimiter
|
2333 |
+
* @uses iCalUtilityFunctions::_duration2str()
|
2334 |
+
* @uses calendarComponent::_createParams()
|
2335 |
+
* @return string
|
2336 |
+
*/
|
2337 |
+
function createTrigger() {
|
2338 |
+
if( empty( $this->trigger )) return FALSE;
|
2339 |
+
if( empty( $this->trigger['value'] ))
|
2340 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TRIGGER' ) : FALSE;
|
2341 |
+
$content = $attributes = null;
|
2342 |
+
if( isset( $this->trigger['value']['year'] ) &&
|
2343 |
+
isset( $this->trigger['value']['month'] ) &&
|
2344 |
+
isset( $this->trigger['value']['day'] ))
|
2345 |
+
$content .= iCalUtilityFunctions::_date2strdate( $this->trigger['value'] );
|
2346 |
+
else {
|
2347 |
+
if( TRUE !== $this->trigger['value']['relatedStart'] )
|
2348 |
+
$attributes .= $this->intAttrDelimiter.'RELATED=END';
|
2349 |
+
if( $this->trigger['value']['before'] )
|
2350 |
+
$content .= '-';
|
2351 |
+
$content .= iCalUtilityFunctions::_duration2str( $this->trigger['value'] );
|
2352 |
+
}
|
2353 |
+
$attributes .= $this->_createParams( $this->trigger['params'] );
|
2354 |
+
return $this->_createElement( 'TRIGGER', $attributes, $content );
|
2355 |
+
}
|
2356 |
+
/**
|
2357 |
+
* set calendar component property trigger
|
2358 |
+
*
|
2359 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2360 |
+
* @since 2.16.21 - 2013-06-23
|
2361 |
+
* @param mixed $year
|
2362 |
+
* @param mixed $month
|
2363 |
+
* @param int $day
|
2364 |
+
* @param int $week
|
2365 |
+
* @param int $hour
|
2366 |
+
* @param int $min
|
2367 |
+
* @param int $sec
|
2368 |
+
* @param bool $relatedStart
|
2369 |
+
* @param bool $before
|
2370 |
+
* @param array $params
|
2371 |
+
* @uses calendarComponent::getConfig()
|
2372 |
+
* @uses calendarComponent::$trigger
|
2373 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2374 |
+
* @uses iCalUtilityFunctions::_isArrayTimestampDate()
|
2375 |
+
* @uses iCalUtilityFunctions::_timestamp2date()
|
2376 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
2377 |
+
* @uses iCalUtilityFunctions::_duration2arr()
|
2378 |
+
* @return bool
|
2379 |
+
*/
|
2380 |
+
function setTrigger( $year, $month=null, $day=null, $week=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $relatedStart=TRUE, $before=TRUE, $params=FALSE ) {
|
2381 |
+
if( empty( $year ) && ( empty( $month ) || is_array( $month )) && empty( $day ) && empty( $week ) && empty( $hour ) && empty( $min ) && empty( $sec ))
|
2382 |
+
if( $this->getConfig( 'allowEmpty' )) {
|
2383 |
+
$this->trigger = array( 'value' => '', 'params' => iCalUtilityFunctions::_setParams( $month ) );
|
2384 |
+
return TRUE;
|
2385 |
+
}
|
2386 |
+
else
|
2387 |
+
return FALSE;
|
2388 |
+
if( iCalUtilityFunctions::_isArrayTimestampDate( $year )) { // timestamp UTC
|
2389 |
+
$params = iCalUtilityFunctions::_setParams( $month );
|
2390 |
+
$date = iCalUtilityFunctions::_timestamp2date( $year, 7 );
|
2391 |
+
foreach( $date as $k => $v )
|
2392 |
+
$$k = $v;
|
2393 |
+
}
|
2394 |
+
elseif( is_array( $year ) && ( is_array( $month ) || empty( $month ))) {
|
2395 |
+
$params = iCalUtilityFunctions::_setParams( $month );
|
2396 |
+
if(!(array_key_exists( 'year', $year ) && // exclude date-time
|
2397 |
+
array_key_exists( 'month', $year ) &&
|
2398 |
+
array_key_exists( 'day', $year ))) { // when this must be a duration
|
2399 |
+
if( isset( $params['RELATED'] ) && ( 'END' == strtoupper( $params['RELATED'] )))
|
2400 |
+
$relatedStart = FALSE;
|
2401 |
+
else
|
2402 |
+
$relatedStart = ( array_key_exists( 'relatedStart', $year ) && ( TRUE !== $year['relatedStart'] )) ? FALSE : TRUE;
|
2403 |
+
$before = ( array_key_exists( 'before', $year ) && ( TRUE !== $year['before'] )) ? FALSE : TRUE;
|
2404 |
+
}
|
2405 |
+
$SSYY = ( array_key_exists( 'year', $year )) ? $year['year'] : null;
|
2406 |
+
$month = ( array_key_exists( 'month', $year )) ? $year['month'] : null;
|
2407 |
+
$day = ( array_key_exists( 'day', $year )) ? $year['day'] : null;
|
2408 |
+
$week = ( array_key_exists( 'week', $year )) ? $year['week'] : null;
|
2409 |
+
$hour = ( array_key_exists( 'hour', $year )) ? $year['hour'] : 0; //null;
|
2410 |
+
$min = ( array_key_exists( 'min', $year )) ? $year['min'] : 0; //null;
|
2411 |
+
$sec = ( array_key_exists( 'sec', $year )) ? $year['sec'] : 0; //null;
|
2412 |
+
$year = $SSYY;
|
2413 |
+
}
|
2414 |
+
elseif(is_string( $year ) && ( is_array( $month ) || empty( $month ))) { // duration or date in a string
|
2415 |
+
$params = iCalUtilityFunctions::_setParams( $month );
|
2416 |
+
if( in_array( $year{0}, array( 'P', '+', '-' ))) { // duration
|
2417 |
+
$relatedStart = ( isset( $params['RELATED'] ) && ( 'END' == strtoupper( $params['RELATED'] ))) ? FALSE : TRUE;
|
2418 |
+
$before = ( '-' == $year[0] ) ? TRUE : FALSE;
|
2419 |
+
if( 'P' != $year[0] )
|
2420 |
+
$year = substr( $year, 1 );
|
2421 |
+
$date = iCalUtilityFunctions::_durationStr2arr( $year);
|
2422 |
+
}
|
2423 |
+
else // date
|
2424 |
+
$date = iCalUtilityFunctions::_strdate2date( $year, 7 );
|
2425 |
+
unset( $year, $month, $day, $date['unparsedtext'] );
|
2426 |
+
if( empty( $date ))
|
2427 |
+
$sec = 0;
|
2428 |
+
else
|
2429 |
+
foreach( $date as $k => $v )
|
2430 |
+
$$k = $v;
|
2431 |
+
}
|
2432 |
+
else // single values in function input parameters
|
2433 |
+
$params = iCalUtilityFunctions::_setParams( $params );
|
2434 |
+
if( !empty( $year ) && !empty( $month ) && !empty( $day )) { // date
|
2435 |
+
$params['VALUE'] = 'DATE-TIME';
|
2436 |
+
$hour = ( $hour ) ? $hour : 0;
|
2437 |
+
$min = ( $min ) ? $min : 0;
|
2438 |
+
$sec = ( $sec ) ? $sec : 0;
|
2439 |
+
$this->trigger = array( 'params' => $params );
|
2440 |
+
$this->trigger['value'] = array( 'year' => $year
|
2441 |
+
, 'month' => $month
|
2442 |
+
, 'day' => $day
|
2443 |
+
, 'hour' => $hour
|
2444 |
+
, 'min' => $min
|
2445 |
+
, 'sec' => $sec
|
2446 |
+
, 'tz' => 'Z' );
|
2447 |
+
return TRUE;
|
2448 |
+
}
|
2449 |
+
elseif(( empty( $year ) && empty( $month )) && // duration
|
2450 |
+
(( !empty( $week ) || ( 0 == $week )) ||
|
2451 |
+
( !empty( $day ) || ( 0 == $day )) ||
|
2452 |
+
( !empty( $hour ) || ( 0 == $hour )) ||
|
2453 |
+
( !empty( $min ) || ( 0 == $min )) ||
|
2454 |
+
( !empty( $sec ) || ( 0 == $sec )))) {
|
2455 |
+
unset( $params['RELATED'] ); // set at output creation (END only)
|
2456 |
+
unset( $params['VALUE'] ); // 'DURATION' default
|
2457 |
+
$this->trigger = array( 'params' => $params );
|
2458 |
+
$this->trigger['value'] = array();
|
2459 |
+
if( !empty( $week )) $this->trigger['value']['week'] = $week;
|
2460 |
+
if( !empty( $day )) $this->trigger['value']['day'] = $day;
|
2461 |
+
if( !empty( $hour )) $this->trigger['value']['hour'] = $hour;
|
2462 |
+
if( !empty( $min )) $this->trigger['value']['min'] = $min;
|
2463 |
+
if( !empty( $sec )) $this->trigger['value']['sec'] = $sec;
|
2464 |
+
if( empty( $this->trigger['value'] )) {
|
2465 |
+
$this->trigger['value']['sec'] = 0;
|
2466 |
+
$before = FALSE;
|
2467 |
+
}
|
2468 |
+
else
|
2469 |
+
$this->trigger['value'] = iCalUtilityFunctions::_duration2arr( $this->trigger['value'] );
|
2470 |
+
$relatedStart = ( FALSE !== $relatedStart ) ? TRUE : FALSE;
|
2471 |
+
$before = ( FALSE !== $before ) ? TRUE : FALSE;
|
2472 |
+
$this->trigger['value']['relatedStart'] = $relatedStart;
|
2473 |
+
$this->trigger['value']['before'] = $before;
|
2474 |
+
return TRUE;
|
2475 |
+
}
|
2476 |
+
return FALSE;
|
2477 |
+
}
|
2478 |
+
/*********************************************************************************/
|
2479 |
+
/**
|
2480 |
+
* Property Name: TZID
|
2481 |
+
*/
|
2482 |
+
/**
|
2483 |
+
* creates formatted output for calendar component property tzid
|
2484 |
+
*
|
2485 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2486 |
+
* @since 2.16.2 - 2012-12-18
|
2487 |
+
* @uses calendarComponent::$tzid
|
2488 |
+
* @uses calendarComponent::getConfig()
|
2489 |
+
* @uses calendarComponent::_createElement()
|
2490 |
+
* @uses calendarComponent::_createParams()
|
2491 |
+
* @uses iCalUtilityFunctions::_strrep()
|
2492 |
+
* @uses calendarComponent::$format
|
2493 |
+
* @uses calendarComponent::$nl
|
2494 |
+
* @return string
|
2495 |
+
*/
|
2496 |
+
function createTzid() {
|
2497 |
+
if( empty( $this->tzid )) return FALSE;
|
2498 |
+
if( empty( $this->tzid['value'] ))
|
2499 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZID' ) : FALSE;
|
2500 |
+
$attributes = $this->_createParams( $this->tzid['params'] );
|
2501 |
+
return $this->_createElement( 'TZID', $attributes, iCalUtilityFunctions::_strrep( $this->tzid['value'], $this->format, $this->nl ));
|
2502 |
+
}
|
2503 |
+
/**
|
2504 |
+
* set calendar component property tzid
|
2505 |
+
*
|
2506 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2507 |
+
* @since 2.16.21 - 2013-06-23
|
2508 |
+
* @param string $value
|
2509 |
+
* @param array $params
|
2510 |
+
* @uses calendarComponent::getConfig()
|
2511 |
+
* @uses calendarComponent::$tzid
|
2512 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2513 |
+
* @return bool
|
2514 |
+
*/
|
2515 |
+
function setTzid( $value, $params=FALSE ) {
|
2516 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2517 |
+
$this->tzid = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2518 |
+
return TRUE;
|
2519 |
+
}
|
2520 |
+
/*********************************************************************************/
|
2521 |
+
/**
|
2522 |
+
* .. .
|
2523 |
+
* Property Name: TZNAME
|
2524 |
+
*/
|
2525 |
+
/**
|
2526 |
+
* creates formatted output for calendar component property tzname
|
2527 |
+
*
|
2528 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2529 |
+
* @since 2.16.2 - 2012-12-18
|
2530 |
+
* @uses calendarComponent::$tzname
|
2531 |
+
* @uses calendarComponent::_createParams()
|
2532 |
+
* @uses calendarComponent::_createElement()
|
2533 |
+
* @uses iCalUtilityFunctions::_strrep(
|
2534 |
+
* @uses calendarComponent::$format
|
2535 |
+
* @uses calendarComponent::$nl
|
2536 |
+
* @uses calendarComponent::getConfig()
|
2537 |
+
* @return string
|
2538 |
+
*/
|
2539 |
+
function createTzname() {
|
2540 |
+
if( empty( $this->tzname )) return FALSE;
|
2541 |
+
$output = null;
|
2542 |
+
foreach( $this->tzname as $theName ) {
|
2543 |
+
if( !empty( $theName['value'] )) {
|
2544 |
+
$attributes = $this->_createParams( $theName['params'], array( 'LANGUAGE' ));
|
2545 |
+
$output .= $this->_createElement( 'TZNAME', $attributes, iCalUtilityFunctions::_strrep( $theName['value'], $this->format, $this->nl ));
|
2546 |
+
}
|
2547 |
+
elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'TZNAME' );
|
2548 |
+
}
|
2549 |
+
return $output;
|
2550 |
+
}
|
2551 |
+
/**
|
2552 |
+
* set calendar component property tzname
|
2553 |
+
*
|
2554 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2555 |
+
* @since 2.16.21 - 2013-06-23
|
2556 |
+
* @param string $value
|
2557 |
+
* @param array $params
|
2558 |
+
* @param integer $index
|
2559 |
+
* @uses calendarComponent::_createParams()
|
2560 |
+
* @uses calendarComponent::$tzname
|
2561 |
+
* @uses iCalUtilityFunctions::_setMval()
|
2562 |
+
* @return bool
|
2563 |
+
*/
|
2564 |
+
function setTzname( $value, $params=FALSE, $index=FALSE ) {
|
2565 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2566 |
+
iCalUtilityFunctions::_setMval( $this->tzname, $value, $params, FALSE, $index );
|
2567 |
+
return TRUE;
|
2568 |
+
}
|
2569 |
+
/*********************************************************************************/
|
2570 |
+
/**
|
2571 |
+
* Property Name: TZOFFSETFROM
|
2572 |
+
*/
|
2573 |
+
/**
|
2574 |
+
* creates formatted output for calendar component property tzoffsetfrom
|
2575 |
+
*
|
2576 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2577 |
+
* @since 2.4.8 - 2008-10-21
|
2578 |
+
* @uses calendarComponent::$tzoffsetfrom
|
2579 |
+
* @uses calendarComponent::getConfig()
|
2580 |
+
* @uses calendarComponent::_createElement()
|
2581 |
+
* @uses calendarComponent::_createParams()
|
2582 |
+
* @return string
|
2583 |
+
*/
|
2584 |
+
function createTzoffsetfrom() {
|
2585 |
+
if( empty( $this->tzoffsetfrom )) return FALSE;
|
2586 |
+
if( empty( $this->tzoffsetfrom['value'] ))
|
2587 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZOFFSETFROM' ) : FALSE;
|
2588 |
+
$attributes = $this->_createParams( $this->tzoffsetfrom['params'] );
|
2589 |
+
return $this->_createElement( 'TZOFFSETFROM', $attributes, $this->tzoffsetfrom['value'] );
|
2590 |
+
}
|
2591 |
+
/**
|
2592 |
+
* set calendar component property tzoffsetfrom
|
2593 |
+
*
|
2594 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2595 |
+
* @since 2.16.21 - 2013-06-23
|
2596 |
+
* @param string $value
|
2597 |
+
* @param array $params
|
2598 |
+
* @uses calendarComponent::getConfig()
|
2599 |
+
* @uses calendarComponent::$tzoffsetfrom
|
2600 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2601 |
+
* @return bool
|
2602 |
+
*/
|
2603 |
+
function setTzoffsetfrom( $value, $params=FALSE ) {
|
2604 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2605 |
+
$this->tzoffsetfrom = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2606 |
+
return TRUE;
|
2607 |
+
}
|
2608 |
+
/*********************************************************************************/
|
2609 |
+
/**
|
2610 |
+
* Property Name: TZOFFSETTO
|
2611 |
+
*/
|
2612 |
+
/**
|
2613 |
+
* creates formatted output for calendar component property tzoffsetto
|
2614 |
+
*
|
2615 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2616 |
+
* @since 2.4.8 - 2008-10-21
|
2617 |
+
* @uses calendarComponent::$tzoffsetto
|
2618 |
+
* @uses calendarComponent::getConfig()
|
2619 |
+
* @uses calendarComponent::_createElement()
|
2620 |
+
* @uses calendarComponent::_createParams()
|
2621 |
+
* @return string
|
2622 |
+
*/
|
2623 |
+
function createTzoffsetto() {
|
2624 |
+
if( empty( $this->tzoffsetto )) return FALSE;
|
2625 |
+
if( empty( $this->tzoffsetto['value'] ))
|
2626 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZOFFSETTO' ) : FALSE;
|
2627 |
+
$attributes = $this->_createParams( $this->tzoffsetto['params'] );
|
2628 |
+
return $this->_createElement( 'TZOFFSETTO', $attributes, $this->tzoffsetto['value'] );
|
2629 |
+
}
|
2630 |
+
/**
|
2631 |
+
* set calendar component property tzoffsetto
|
2632 |
+
*
|
2633 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2634 |
+
* @since 2.16.21 - 2013-06-23
|
2635 |
+
* @param string $value
|
2636 |
+
* @param array $params
|
2637 |
+
* @uses calendarComponent::getConfig()
|
2638 |
+
* @uses calendarComponent::$tzoffsetto
|
2639 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2640 |
+
* @return bool
|
2641 |
+
*/
|
2642 |
+
function setTzoffsetto( $value, $params=FALSE ) {
|
2643 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2644 |
+
$this->tzoffsetto = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2645 |
+
return TRUE;
|
2646 |
+
}
|
2647 |
+
/*********************************************************************************/
|
2648 |
+
/**
|
2649 |
+
* Property Name: TZURL
|
2650 |
+
*/
|
2651 |
+
/**
|
2652 |
+
* creates formatted output for calendar component property tzurl
|
2653 |
+
*
|
2654 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2655 |
+
* @since 2.4.8 - 2008-10-21
|
2656 |
+
* @uses calendarComponent::$tzurl
|
2657 |
+
* @uses calendarComponent::getConfig()
|
2658 |
+
* @uses calendarComponent::_createElement()
|
2659 |
+
* @uses calendarComponent::_createParams()
|
2660 |
+
* @return string
|
2661 |
+
*/
|
2662 |
+
function createTzurl() {
|
2663 |
+
if( empty( $this->tzurl )) return FALSE;
|
2664 |
+
if( empty( $this->tzurl['value'] ))
|
2665 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZURL' ) : FALSE;
|
2666 |
+
$attributes = $this->_createParams( $this->tzurl['params'] );
|
2667 |
+
return $this->_createElement( 'TZURL', $attributes, $this->tzurl['value'] );
|
2668 |
+
}
|
2669 |
+
/**
|
2670 |
+
* set calendar component property tzurl
|
2671 |
+
*
|
2672 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2673 |
+
* @since 2.16.21 - 2013-06-23
|
2674 |
+
* @param string $value
|
2675 |
+
* @param array $params
|
2676 |
+
* @uses calendarComponent::$tzurl
|
2677 |
+
* @uses calendarComponent::getConfig()
|
2678 |
+
* @uses calendarComponent::$tzurl
|
2679 |
+
* @uses iCalUtilityFunctions::_setParams()
|
2680 |
+
* @return boll
|
2681 |
+
*/
|
2682 |
+
function setTzurl( $value, $params=FALSE ) {
|
2683 |
+
if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
2684 |
+
$this->tzurl = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2685 |
+
return TRUE;
|
2686 |
+
}
|
2687 |
+
/*********************************************************************************/
|
2688 |
+
/**
|
2689 |
+
* Property Name: UID
|
2690 |
+
*/
|
2691 |
+
/**
|
2692 |
+
* creates formatted output for calendar component property uid
|
2693 |
+
*
|
2694 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2695 |
+
* @since 2.19.1 - 2014-02-21
|
2696 |
+
* @uses calendarComponent::$uid
|
2697 |
+
* @uses calendarComponent::_makeuid();
|
2698 |
+
* @uses calendarComponent::_createParams()
|
2699 |
+
* @uses calendarComponent::_createElement()
|
2700 |
+
* @return string
|
2701 |
+
*/
|
2702 |
+
function createUid() {
|
2703 |
+
if( empty( $this->uid ))
|
2704 |
+
$this->_makeuid();
|
2705 |
+
$attributes = $this->_createParams( $this->uid['params'] );
|
2706 |
+
return $this->_createElement( 'UID', $attributes, $this->uid['value'] );
|
2707 |
+
}
|
2708 |
+
/**
|
2709 |
+
* create an unique id for this calendar component object instance
|
2710 |
+
*
|
2711 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2712 |
+
* @since 2.2.7 - 2007-09-04
|
2713 |
+
* @uses calendarComponent::$uid
|
2714 |
+
* @uses calendarComponent::getConfig()
|
2715 |
+
* @return void
|
2716 |
+
*/
|
2717 |
+
function _makeUid() {
|
2718 |
+
$date = date('Ymd\THisT');
|
2719 |
+
$unique = substr(microtime(), 2, 4);
|
2720 |
+
$base = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPrRsStTuUvVxXuUvVwWzZ1234567890';
|
2721 |
+
$start = 0;
|
2722 |
+
$end = strlen( $base ) - 1;
|
2723 |
+
$length = 6;
|
2724 |
+
$str = null;
|
2725 |
+
for( $p = 0; $p < $length; $p++ )
|
2726 |
+
$unique .= $base{mt_rand( $start, $end )};
|
2727 |
+
$this->uid = array( 'params' => null );
|
2728 |
+
$this->uid['value'] = $date.'-'.$unique.'@'.$this->getConfig( 'unique_id' );
|
2729 |
+
}
|
2730 |
+
/**
|
2731 |
+
* set calendar component property uid
|
2732 |
+
*
|
2733 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2734 |
+
* @since 2.19.1 - 2014-02-21
|
2735 |
+
* @param string $value
|
2736 |
+
* @param array $params
|
2737 |
+
* @uses calendarComponent::$uid
|
2738 |
+
* @uses calendarComponent::_setParams()
|
2739 |
+
* @return bool
|
2740 |
+
*/
|
2741 |
+
function setUid( $value, $params=FALSE ) {
|
2742 |
+
if( empty( $value ) && ( '0' != $value )) return FALSE; // no allowEmpty check here !!!!
|
2743 |
+
$this->uid = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2744 |
+
return TRUE;
|
2745 |
+
}
|
2746 |
+
/*********************************************************************************/
|
2747 |
+
/**
|
2748 |
+
* Property Name: URL
|
2749 |
+
*/
|
2750 |
+
/**
|
2751 |
+
* creates formatted output for calendar component property url
|
2752 |
+
*
|
2753 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2754 |
+
* @since 2.4.8 - 2008-10-21
|
2755 |
+
* @uses calendarComponent::$url
|
2756 |
+
* @uses calendarComponent::getConfig()
|
2757 |
+
* @uses calendarComponent::_createElement()
|
2758 |
+
* @uses calendarComponent::_createParams()
|
2759 |
+
* @return string
|
2760 |
+
*/
|
2761 |
+
function createUrl() {
|
2762 |
+
if( empty( $this->url )) return FALSE;
|
2763 |
+
if( empty( $this->url['value'] ))
|
2764 |
+
return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'URL' ) : FALSE;
|
2765 |
+
$attributes = $this->_createParams( $this->url['params'] );
|
2766 |
+
return $this->_createElement( 'URL', $attributes, $this->url['value'] );
|
2767 |
+
}
|
2768 |
+
/**
|
2769 |
+
* set calendar component property url
|
2770 |
+
*
|
2771 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2772 |
+
* @since 2.16.21 - 2013-06-23
|
2773 |
+
* @param string $value
|
2774 |
+
* @param array $params
|
2775 |
+
* @uses calendarComponent::getConfig()
|
2776 |
+
* @uses calendarComponent::$url
|
2777 |
+
* @uses calendarComponent::_setParams()
|
2778 |
+
* @return bool
|
2779 |
+
*/
|
2780 |
+
function setUrl( $value, $params=FALSE ) {
|
2781 |
+
if( !empty( $value )) {
|
2782 |
+
if( !filter_var( $value, FILTER_VALIDATE_URL ) && ( 'urn' != strtolower( substr( $value, 0, 3 ))))
|
2783 |
+
return FALSE;
|
2784 |
+
}
|
2785 |
+
elseif( $this->getConfig( 'allowEmpty' ))
|
2786 |
+
$value = '';
|
2787 |
+
else
|
2788 |
+
return FALSE;
|
2789 |
+
$this->url = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
|
2790 |
+
return TRUE;
|
2791 |
+
}
|
2792 |
+
/*********************************************************************************/
|
2793 |
+
/*********************************************************************************/
|
2794 |
+
/**
|
2795 |
+
* create element format parts
|
2796 |
+
*
|
2797 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2798 |
+
* @since 2.0.6 - 2006-06-20
|
2799 |
+
* @uses iCalBase::_createFormat()
|
2800 |
+
* @uses calendarComponent::$timezonetype
|
2801 |
+
* @return string
|
2802 |
+
*/
|
2803 |
+
function _createFormat() {
|
2804 |
+
parent::_createFormat();
|
2805 |
+
$objectname = null;
|
2806 |
+
switch( $this->format ) {
|
2807 |
+
case 'xcal':
|
2808 |
+
return ( isset( $this->timezonetype )) ? strtolower( $this->timezonetype ) : strtolower( $this->objName );
|
2809 |
+
break;
|
2810 |
+
default:
|
2811 |
+
return ( isset( $this->timezonetype )) ? strtoupper( $this->timezonetype ) : strtoupper( $this->objName );
|
2812 |
+
break;
|
2813 |
+
}
|
2814 |
+
}
|
2815 |
+
/**
|
2816 |
+
* creates formatted output for calendar component property data value type recur
|
2817 |
+
*
|
2818 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2819 |
+
* @since 2.16.25 - 2013-06-30
|
2820 |
+
* @param array $recurlabel
|
2821 |
+
* @param array $recurdata
|
2822 |
+
* @uses calendarComponent::getConfig()
|
2823 |
+
* @uses calendarComponent::_createElement()
|
2824 |
+
* @uses calendarComponent::_createParams()
|
2825 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
2826 |
+
* @uses iCalUtilityFunctions::_recurBydaySort()
|
2827 |
+
* @return string
|
2828 |
+
*/
|
2829 |
+
function _format_recur( $recurlabel, $recurdata ) {
|
2830 |
+
$output = null;
|
2831 |
+
foreach( $recurdata as $therule ) {
|
2832 |
+
if( empty( $therule['value'] )) {
|
2833 |
+
if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( $recurlabel );
|
2834 |
+
continue;
|
2835 |
+
}
|
2836 |
+
$attributes = ( isset( $therule['params'] )) ? $this->_createParams( $therule['params'] ) : null;
|
2837 |
+
$content1 = $content2 = null;
|
2838 |
+
foreach( $therule['value'] as $rulelabel => $rulevalue ) {
|
2839 |
+
switch( strtoupper( $rulelabel )) {
|
2840 |
+
case 'FREQ': {
|
2841 |
+
$content1 .= "FREQ=$rulevalue";
|
2842 |
+
break;
|
2843 |
+
}
|
2844 |
+
case 'UNTIL': {
|
2845 |
+
$parno = ( isset( $rulevalue['hour'] )) ? 7 : 3;
|
2846 |
+
$content2 .= ';UNTIL='.iCalUtilityFunctions::_date2strdate( $rulevalue, $parno );
|
2847 |
+
break;
|
2848 |
+
}
|
2849 |
+
case 'COUNT':
|
2850 |
+
case 'INTERVAL':
|
2851 |
+
case 'WKST': {
|
2852 |
+
$content2 .= ";$rulelabel=$rulevalue";
|
2853 |
+
break;
|
2854 |
+
}
|
2855 |
+
case 'BYSECOND':
|
2856 |
+
case 'BYMINUTE':
|
2857 |
+
case 'BYHOUR':
|
2858 |
+
case 'BYMONTHDAY':
|
2859 |
+
case 'BYYEARDAY':
|
2860 |
+
case 'BYWEEKNO':
|
2861 |
+
case 'BYMONTH':
|
2862 |
+
case 'BYSETPOS': {
|
2863 |
+
$content2 .= ";$rulelabel=";
|
2864 |
+
if( is_array( $rulevalue )) {
|
2865 |
+
foreach( $rulevalue as $vix => $valuePart ) {
|
2866 |
+
$content2 .= ( $vix ) ? ',' : null;
|
2867 |
+
$content2 .= $valuePart;
|
2868 |
+
}
|
2869 |
+
}
|
2870 |
+
else
|
2871 |
+
$content2 .= $rulevalue;
|
2872 |
+
break;
|
2873 |
+
}
|
2874 |
+
case 'BYDAY': {
|
2875 |
+
$byday = array( '' );
|
2876 |
+
$bx = 0;
|
2877 |
+
foreach( $rulevalue as $bix => $bydayPart ) {
|
2878 |
+
if( ! empty( $byday[$bx] ) && ! ctype_digit( substr( $byday[$bx], -1 ))) // new day
|
2879 |
+
$byday[++$bx] = '';
|
2880 |
+
if( ! is_array( $bydayPart )) // day without order number
|
2881 |
+
$byday[$bx] .= (string) $bydayPart;
|
2882 |
+
else { // day with order number
|
2883 |
+
foreach( $bydayPart as $bix2 => $bydayPart2 )
|
2884 |
+
$byday[$bx] .= (string) $bydayPart2;
|
2885 |
+
}
|
2886 |
+
} // end foreach( $rulevalue as $bix => $bydayPart )
|
2887 |
+
if( 1 < count( $byday ))
|
2888 |
+
usort( $byday, array( 'iCalUtilityFunctions', '_recurBydaySort' ));
|
2889 |
+
$content2 .= ';BYDAY='.implode( ',', $byday );
|
2890 |
+
break;
|
2891 |
+
}
|
2892 |
+
default: {
|
2893 |
+
$content2 .= ";$rulelabel=$rulevalue";
|
2894 |
+
break;
|
2895 |
+
}
|
2896 |
+
}
|
2897 |
+
}
|
2898 |
+
$output .= $this->_createElement( $recurlabel, $attributes, $content1.$content2 );
|
2899 |
+
}
|
2900 |
+
return $output;
|
2901 |
+
}
|
2902 |
+
/**
|
2903 |
+
* check if property not exists within component
|
2904 |
+
*
|
2905 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2906 |
+
* @since 2.5.1 - 2008-10-15
|
2907 |
+
* @param string $propName
|
2908 |
+
* @uses calendarComponent::$lastmodified
|
2909 |
+
* @uses calendarComponent::$percentcomplete
|
2910 |
+
* @uses calendarComponent::$recurrenceid
|
2911 |
+
* @uses calendarComponent::$relatedto
|
2912 |
+
* @uses calendarComponent::$requeststatus
|
2913 |
+
* @uses calendarComponent::getConfig()
|
2914 |
+
* @uses calendarComponent::{$propname}
|
2915 |
+
* @return bool
|
2916 |
+
*/
|
2917 |
+
function _notExistProp( $propName ) {
|
2918 |
+
if( empty( $propName )) return FALSE; // when deleting x-prop, an empty propName may be used=allowed
|
2919 |
+
$propName = strtolower( $propName );
|
2920 |
+
if( 'last-modified' == $propName ) { if( !isset( $this->lastmodified )) return TRUE; }
|
2921 |
+
elseif( 'percent-complete' == $propName ) { if( !isset( $this->percentcomplete )) return TRUE; }
|
2922 |
+
elseif( 'recurrence-id' == $propName ) { if( !isset( $this->recurrenceid )) return TRUE; }
|
2923 |
+
elseif( 'related-to' == $propName ) { if( !isset( $this->relatedto )) return TRUE; }
|
2924 |
+
elseif( 'request-status' == $propName ) { if( !isset( $this->requeststatus )) return TRUE; }
|
2925 |
+
elseif(( 'x-' != substr($propName,0,2)) && !isset( $this->$propName )) return TRUE;
|
2926 |
+
return FALSE;
|
2927 |
+
}
|
2928 |
+
/*********************************************************************************/
|
2929 |
+
/*********************************************************************************/
|
2930 |
+
/**
|
2931 |
+
* get general component config variables or info about subcomponents
|
2932 |
+
*
|
2933 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2934 |
+
* @since 2.21.11 - 2015-03-21
|
2935 |
+
* @param mixed $config
|
2936 |
+
* @uses calendarComponent::getConfig()
|
2937 |
+
* @uses calendarComponent::$allowEmpty
|
2938 |
+
* @uses calendarComponent::$compix
|
2939 |
+
* @uses calendarComponent::$components
|
2940 |
+
* @uses calendarComponent::$objName
|
2941 |
+
* @uses calendarComponent::getProperty()
|
2942 |
+
* @uses calendarComponent::$format
|
2943 |
+
* @uses calendarComponent::$language
|
2944 |
+
* @uses calendarComponent::$nl
|
2945 |
+
* @uses iCalUtilityFunctions::$miscComps
|
2946 |
+
* @uses calendarComponent::$uid
|
2947 |
+
* @uses calendarComponent::_makeuid()
|
2948 |
+
* @uses calendarComponent::dtstamp
|
2949 |
+
* @uses calendarComponent::_makeDtstamp()
|
2950 |
+
* @uses calendarComponent::$summary
|
2951 |
+
* @uses calendarComponent::$description
|
2952 |
+
* @uses calendarComponent::$dtstart
|
2953 |
+
* @uses calendarComponent::$dtend
|
2954 |
+
* @uses calendarComponent::$due
|
2955 |
+
* @uses calendarComponent::$duration
|
2956 |
+
* @uses calendarComponent::$rrule
|
2957 |
+
* @uses calendarComponent::$rdate
|
2958 |
+
* @uses calendarComponent::$exdate
|
2959 |
+
* @uses calendarComponent::$exrule
|
2960 |
+
* @uses calendarComponent::$action
|
2961 |
+
* @uses calendarComponent::$attach
|
2962 |
+
* @uses calendarComponent::$attendee
|
2963 |
+
* @uses calendarComponent::$categories
|
2964 |
+
* @uses calendarComponent::$class
|
2965 |
+
* @uses calendarComponent::$comment
|
2966 |
+
* @uses calendarComponent::$completed
|
2967 |
+
* @uses calendarComponent::$contact
|
2968 |
+
* @uses calendarComponent::$created
|
2969 |
+
* @uses calendarComponent::$freebusy
|
2970 |
+
* @uses calendarComponent::$geo
|
2971 |
+
* @uses calendarComponent::$lastmodified
|
2972 |
+
* @uses calendarComponent::$location
|
2973 |
+
* @uses calendarComponent::$organizer
|
2974 |
+
* @uses calendarComponent::$percentcomplete
|
2975 |
+
* @uses calendarComponent::$priority
|
2976 |
+
* @uses calendarComponent::$recurrenceid
|
2977 |
+
* @uses calendarComponent::$relatedto
|
2978 |
+
* @uses calendarComponent::$repeat
|
2979 |
+
* @uses calendarComponent::$requeststatus
|
2980 |
+
* @uses calendarComponent::$resources
|
2981 |
+
* @uses calendarComponent::$sequence
|
2982 |
+
* @uses calendarComponent::$sequence
|
2983 |
+
* @uses calendarComponent::$status
|
2984 |
+
* @uses calendarComponent::$transp
|
2985 |
+
* @uses calendarComponent::$trigger
|
2986 |
+
* @uses calendarComponent::$tzid
|
2987 |
+
* @uses calendarComponent::$tzname
|
2988 |
+
* @uses calendarComponent::$tzoffsetfrom
|
2989 |
+
* @uses calendarComponent::$tzoffsetto
|
2990 |
+
* @uses calendarComponent::$tzurl
|
2991 |
+
* @uses calendarComponent::$url
|
2992 |
+
* @uses calendarComponent::$xprop
|
2993 |
+
* @uses calendarComponent::$dtzid
|
2994 |
+
* @uses calendarComponent::$unique_id
|
2995 |
+
* @return value
|
2996 |
+
*/
|
2997 |
+
function getConfig( $config = FALSE) {
|
2998 |
+
if( !$config ) {
|
2999 |
+
$return = array();
|
3000 |
+
$return['ALLOWEMPTY'] = $this->getConfig( 'ALLOWEMPTY' );
|
3001 |
+
$return['FORMAT'] = $this->getConfig( 'FORMAT' );
|
3002 |
+
if( FALSE !== ( $lang = $this->getConfig( 'LANGUAGE' )))
|
3003 |
+
$return['LANGUAGE'] = $lang;
|
3004 |
+
$return['NEWLINECHAR'] = $this->getConfig( 'NEWLINECHAR' );
|
3005 |
+
$return['TZTD'] = $this->getConfig( 'TZID' );
|
3006 |
+
$return['UNIQUE_ID'] = $this->getConfig( 'UNIQUE_ID' );
|
3007 |
+
return $return;
|
3008 |
+
}
|
3009 |
+
switch( strtoupper( $config )) {
|
3010 |
+
case 'ALLOWEMPTY':
|
3011 |
+
return $this->allowEmpty;
|
3012 |
+
break;
|
3013 |
+
case 'COMPSINFO':
|
3014 |
+
unset( $this->compix );
|
3015 |
+
$info = array();
|
3016 |
+
if( isset( $this->components )) {
|
3017 |
+
foreach( $this->components as $cix => $component ) {
|
3018 |
+
if( empty( $component )) continue;
|
3019 |
+
$info[$cix]['ordno'] = $cix + 1;
|
3020 |
+
$info[$cix]['type'] = $component->objName;
|
3021 |
+
$info[$cix]['uid'] = $component->getProperty( 'uid' );
|
3022 |
+
$info[$cix]['props'] = $component->getConfig( 'propinfo' );
|
3023 |
+
$info[$cix]['sub'] = $component->getConfig( 'compsinfo' );
|
3024 |
+
}
|
3025 |
+
}
|
3026 |
+
return $info;
|
3027 |
+
break;
|
3028 |
+
case 'FORMAT':
|
3029 |
+
return $this->format;
|
3030 |
+
break;
|
3031 |
+
case 'LANGUAGE':
|
3032 |
+
// get language for calendar component as defined in [RFC 1766]
|
3033 |
+
return $this->language;
|
3034 |
+
break;
|
3035 |
+
case 'NL':
|
3036 |
+
case 'NEWLINECHAR':
|
3037 |
+
return $this->nl;
|
3038 |
+
break;
|
3039 |
+
case 'PROPINFO':
|
3040 |
+
$output = array();
|
3041 |
+
if( ! in_array( $this->objName, iCalUtilityFunctions::$miscComps )) {
|
3042 |
+
if( empty( $this->uid )) $this->_makeuid();
|
3043 |
+
$output['UID'] = 1;
|
3044 |
+
if( empty( $this->dtstamp )) $this->_makeDtstamp();
|
3045 |
+
$output['DTSTAMP'] = 1;
|
3046 |
+
}
|
3047 |
+
if( !empty( $this->summary )) $output['SUMMARY'] = 1;
|
3048 |
+
if( !empty( $this->description )) $output['DESCRIPTION'] = count( $this->description );
|
3049 |
+
if( !empty( $this->dtstart )) $output['DTSTART'] = 1;
|
3050 |
+
if( !empty( $this->dtend )) $output['DTEND'] = 1;
|
3051 |
+
if( !empty( $this->due )) $output['DUE'] = 1;
|
3052 |
+
if( !empty( $this->duration )) $output['DURATION'] = 1;
|
3053 |
+
if( !empty( $this->rrule )) $output['RRULE'] = count( $this->rrule );
|
3054 |
+
if( !empty( $this->rdate )) $output['RDATE'] = count( $this->rdate );
|
3055 |
+
if( !empty( $this->exdate )) $output['EXDATE'] = count( $this->exdate );
|
3056 |
+
if( !empty( $this->exrule )) $output['EXRULE'] = count( $this->exrule );
|
3057 |
+
if( !empty( $this->action )) $output['ACTION'] = 1;
|
3058 |
+
if( !empty( $this->attach )) $output['ATTACH'] = count( $this->attach );
|
3059 |
+
if( !empty( $this->attendee )) $output['ATTENDEE'] = count( $this->attendee );
|
3060 |
+
if( !empty( $this->categories )) $output['CATEGORIES'] = count( $this->categories );
|
3061 |
+
if( !empty( $this->class )) $output['CLASS'] = 1;
|
3062 |
+
if( !empty( $this->comment )) $output['COMMENT'] = count( $this->comment );
|
3063 |
+
if( !empty( $this->completed )) $output['COMPLETED'] = 1;
|
3064 |
+
if( !empty( $this->contact )) $output['CONTACT'] = count( $this->contact );
|
3065 |
+
if( !empty( $this->created )) $output['CREATED'] = 1;
|
3066 |
+
if( !empty( $this->freebusy )) $output['FREEBUSY'] = count( $this->freebusy );
|
3067 |
+
if( !empty( $this->geo )) $output['GEO'] = 1;
|
3068 |
+
if( !empty( $this->lastmodified )) $output['LAST-MODIFIED'] = 1;
|
3069 |
+
if( !empty( $this->location )) $output['LOCATION'] = 1;
|
3070 |
+
if( !empty( $this->organizer )) $output['ORGANIZER'] = 1;
|
3071 |
+
if( !empty( $this->percentcomplete )) $output['PERCENT-COMPLETE'] = 1;
|
3072 |
+
if( !empty( $this->priority )) $output['PRIORITY'] = 1;
|
3073 |
+
if( !empty( $this->recurrenceid )) $output['RECURRENCE-ID'] = 1;
|
3074 |
+
if( !empty( $this->relatedto )) $output['RELATED-TO'] = count( $this->relatedto );
|
3075 |
+
if( !empty( $this->repeat )) $output['REPEAT'] = 1;
|
3076 |
+
if( !empty( $this->requeststatus )) $output['REQUEST-STATUS'] = count( $this->requeststatus );
|
3077 |
+
if( !empty( $this->resources )) $output['RESOURCES'] = count( $this->resources );
|
3078 |
+
if( !empty( $this->sequence )) $output['SEQUENCE'] = 1;
|
3079 |
+
if( !empty( $this->sequence )) $output['SEQUENCE'] = 1;
|
3080 |
+
if( !empty( $this->status )) $output['STATUS'] = 1;
|
3081 |
+
if( !empty( $this->transp )) $output['TRANSP'] = 1;
|
3082 |
+
if( !empty( $this->trigger )) $output['TRIGGER'] = 1;
|
3083 |
+
if( !empty( $this->tzid )) $output['TZID'] = 1;
|
3084 |
+
if( !empty( $this->tzname )) $output['TZNAME'] = count( $this->tzname );
|
3085 |
+
if( !empty( $this->tzoffsetfrom )) $output['TZOFFSETFROM'] = 1;
|
3086 |
+
if( !empty( $this->tzoffsetto )) $output['TZOFFSETTO'] = 1;
|
3087 |
+
if( !empty( $this->tzurl )) $output['TZURL'] = 1;
|
3088 |
+
if( !empty( $this->url )) $output['URL'] = 1;
|
3089 |
+
if( !empty( $this->xprop )) $output['X-PROP'] = count( $this->xprop );
|
3090 |
+
return $output;
|
3091 |
+
break;
|
3092 |
+
case 'SETPROPERTYNAMES':
|
3093 |
+
return array_keys( $this->getConfig( 'propinfo' ));
|
3094 |
+
break;
|
3095 |
+
case 'TZID':
|
3096 |
+
return $this->dtzid;
|
3097 |
+
break;
|
3098 |
+
case 'UNIQUE_ID':
|
3099 |
+
if( empty( $this->unique_id ))
|
3100 |
+
$this->unique_id = ( isset( $_SERVER['SERVER_NAME'] )) ? gethostbyname( $_SERVER['SERVER_NAME'] ) : 'localhost';
|
3101 |
+
return $this->unique_id;
|
3102 |
+
break;
|
3103 |
+
}
|
3104 |
+
}
|
3105 |
+
/**
|
3106 |
+
* general component config setting
|
3107 |
+
*
|
3108 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
3109 |
+
* @since 2.10.18 - 2013-09-06
|
3110 |
+
* @param mixed $config
|
3111 |
+
* @param string $value
|
3112 |
+
* @param bool $softUpdate
|
3113 |
+
* @uses calendarComponent::getConfig()
|
3114 |
+
* @uses calendarComponent::$allowEmpty
|
3115 |
+
* @uses calendarComponent::$format
|
3116 |
+
* @uses calendarComponent::$language
|
3117 |
+
* @uses calendarComponent::$nl
|
3118 |
+
* @uses calendarComponent::$dtzid
|
3119 |
+
* @uses calendarComponent::$unique_id
|
3120 |
+
* @uses calendarComponent::$components
|
3121 |
+
* @uses calendarComponent::copy()
|
3122 |
+
* @return void
|
3123 |
+
*/
|
3124 |
+
function setConfig( $config, $value = FALSE, $softUpdate = FALSE ) {
|
3125 |
+
if( is_array( $config )) {
|
3126 |
+
$config = array_change_key_case( $config, CASE_UPPER );
|
3127 |
+
if( isset( $config['NEWLINECHAR'] ) || isset( $config['NL'] )) {
|
3128 |
+
$k = ( isset( $config['NEWLINECHAR'] )) ? 'NEWLINECHAR' : 'NL';
|
3129 |
+
if( FALSE === $this->setConfig( 'NL', $config[$k] ))
|
3130 |
+
return FALSE;
|
3131 |
+
unset( $config[$k] );
|
3132 |
+
}
|
3133 |
+
foreach( $config as $cKey => $cValue ) {
|
3134 |
+
if( FALSE === $this->setConfig( $cKey, $cValue, $softUpdate ))
|
3135 |
+
return FALSE;
|
3136 |
+
}
|
3137 |
+
return TRUE;
|
3138 |
+
}
|
3139 |
+
else
|
3140 |
+
$config = strtoupper( $config );
|
3141 |
+
$res = FALSE;
|
3142 |
+
switch( $config ) {
|
3143 |
+
case 'ALLOWEMPTY':
|
3144 |
+
$this->allowEmpty = $value;
|
3145 |
+
$subcfg = array( 'ALLOWEMPTY' => $value );
|
3146 |
+
$res = TRUE;
|
3147 |
+
break;
|
3148 |
+
case 'FORMAT':
|
3149 |
+
$value = trim( strtolower( $value ));
|
3150 |
+
$this->format = $value;
|
3151 |
+
$this->_createFormat();
|
3152 |
+
$subcfg = array( 'FORMAT' => $value );
|
3153 |
+
$res = TRUE;
|
3154 |
+
break;
|
3155 |
+
case 'LANGUAGE':
|
3156 |
+
// set language for calendar component as defined in [RFC 1766]
|
3157 |
+
$value = trim( $value );
|
3158 |
+
if( empty( $this->language ) || !$softUpdate )
|
3159 |
+
$this->language = $value;
|
3160 |
+
$subcfg = array( 'LANGUAGE' => $value );
|
3161 |
+
$res = TRUE;
|
3162 |
+
break;
|
3163 |
+
case 'NL':
|
3164 |
+
case 'NEWLINECHAR':
|
3165 |
+
$this->nl = $value;
|
3166 |
+
$this->_createFormat();
|
3167 |
+
$subcfg = array( 'NL' => $value );
|
3168 |
+
$res = TRUE;
|
3169 |
+
break;
|
3170 |
+
case 'TZID':
|
3171 |
+
$this->dtzid = $value;
|
3172 |
+
$subcfg = array( 'TZID' => $value );
|
3173 |
+
$res = TRUE;
|
3174 |
+
break;
|
3175 |
+
case 'UNIQUE_ID':
|
3176 |
+
$value = trim( $value );
|
3177 |
+
$this->unique_id = $value;
|
3178 |
+
$subcfg = array( 'UNIQUE_ID' => $value );
|
3179 |
+
$res = TRUE;
|
3180 |
+
break;
|
3181 |
+
default: // any unvalid config key.. .
|
3182 |
+
return TRUE;
|
3183 |
+
}
|
3184 |
+
if( !$res ) return FALSE;
|
3185 |
+
if( isset( $subcfg ) && !empty( $this->components )) {
|
3186 |
+
foreach( $subcfg as $cfgkey => $cfgvalue ) {
|
3187 |
+
foreach( $this->components as $cix => $component ) {
|
3188 |
+
$res = $component->setConfig( $cfgkey, $cfgvalue, $softUpdate );
|
3189 |
+
if( !$res )
|
3190 |
+
break 2;
|
3191 |
+
$this->components[$cix] = $component->copy(); // PHP4 compliant
|
3192 |
+
}
|
3193 |
+
}
|
3194 |
+
}
|
3195 |
+
return $res;
|
3196 |
+
}
|
3197 |
+
/*********************************************************************************/
|
3198 |
+
/**
|
3199 |
+
* delete component property value
|
3200 |
+
*
|
3201 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
3202 |
+
* @since 2.8.8 - 2011-03-15
|
3203 |
+
* @param mixed $propName bool FALSE => X-property
|
3204 |
+
* @param int $propix specific property in case of multiply occurences
|
3205 |
+
* @uses calendarComponent::_notExistProp()
|
3206 |
+
* @uses iCalUtilityFunctions::$mProps2
|
3207 |
+
* @uses calendarComponent::$propdelix
|
3208 |
+
* @uses calendarComponent::$action
|
3209 |
+
* @uses calendarComponent::deletePropertyM()
|
3210 |
+
* @uses calendarComponent::$attendee
|
3211 |
+
* @uses calendarComponent::$categories
|
3212 |
+
* @uses calendarComponent::$class
|
3213 |
+
* @uses calendarComponent::$comment
|
3214 |
+
* @uses calendarComponent::$completed
|
3215 |
+
* @uses calendarComponent::$contact
|
3216 |
+
* @uses calendarComponent::$created
|
3217 |
+
* @uses calendarComponent::$description
|
3218 |
+
* @uses calendarComponent::$dtend
|
3219 |
+
* @uses iCalUtilityFunctions::$miscComps
|
3220 |
+
* @uses calendarComponent::$objName
|
3221 |
+
* @uses calendarComponent::$dtstamp
|
3222 |
+
* @uses calendarComponent::$dtstart
|
3223 |
+
* @uses calendarComponent::$due
|
3224 |
+
* @uses calendarComponent::$duration
|
3225 |
+
* @uses calendarComponent::$exdate
|
3226 |
+
* @uses calendarComponent::$exrule
|
3227 |
+
* @uses calendarComponent::$freebusy
|
3228 |
+
* @uses calendarComponent::$geo
|
3229 |
+
* @uses calendarComponent::$lastmodified
|
3230 |
+
* @uses calendarComponent::$location
|
3231 |
+
* @uses calendarComponent::$organizer
|
3232 |
+
* @uses calendarComponent::$percentcomplete
|
3233 |
+
* @uses calendarComponent::$priority
|
3234 |
+
* @uses calendarComponent::$rdate
|
3235 |
+
* @uses calendarComponent::$recurrenceid
|
3236 |
+
* @uses calendarComponent::$relatedto
|
3237 |
+
* @uses calendarComponent::$repeat
|
3238 |
+
* @uses calendarComponent::$requeststatus
|
3239 |
+
* @uses calendarComponent::$resources
|
3240 |
+
* @uses calendarComponent::$rrule
|
3241 |
+
* @uses calendarComponent::$sequence
|
3242 |
+
* @uses calendarComponent::$status
|
3243 |
+
* @uses calendarComponent::$summary
|
3244 |
+
* @uses calendarComponent::$transp
|
3245 |
+
* @uses calendarComponent::$trigger
|
3246 |
+
* @uses calendarComponent::$tzid
|
3247 |
+
* @uses calendarComponent::$tzname
|
3248 |
+
* @uses calendarComponent::$tzoffsetfrom
|
3249 |
+
* @uses calendarComponent::$tzoffsetto
|
3250 |
+
* @uses calendarComponent::$tzurl
|
3251 |
+
* @uses calendarComponent::$uid
|
3252 |
+
* @uses calendarComponent::$url
|
3253 |
+
* @uses calendarComponent::$xprop
|
3254 |
+
* @return bool, if successfull delete TRUE
|
3255 |
+
*/
|
3256 |
+
function deleteProperty( $propName=FALSE, $propix=FALSE ) {
|
3257 |
+
if( $this->_notExistProp( $propName )) return FALSE;
|
3258 |
+
$propName = strtoupper( $propName );
|
3259 |
+
if( in_array( $propName, iCalUtilityFunctions::$mProps2 )) {
|
3260 |
+
if( !$propix )
|
3261 |
+
$propix = ( isset( $this->propdelix[$propName] ) && ( 'X-PROP' != $propName )) ? $this->propdelix[$propName] + 2 : 1;
|
3262 |
+
$this->propdelix[$propName] = --$propix;
|
3263 |
+
}
|
3264 |
+
$return = FALSE;
|
3265 |
+
switch( $propName ) {
|
3266 |
+
case 'ACTION':
|
3267 |
+
if( !empty( $this->action )) {
|
3268 |
+
$this->action = '';
|
3269 |
+
$return = TRUE;
|
3270 |
+
}
|
3271 |
+
break;
|
3272 |
+
case 'ATTACH':
|
3273 |
+
return $this->deletePropertyM( $this->attach, $this->propdelix[$propName] );
|
3274 |
+
break;
|
3275 |
+
case 'ATTENDEE':
|
3276 |
+
return $this->deletePropertyM( $this->attendee, $this->propdelix[$propName] );
|
3277 |
+
break;
|
3278 |
+
case 'CATEGORIES':
|
3279 |
+
return $this->deletePropertyM( $this->categories, $this->propdelix[$propName] );
|
3280 |
+
break;
|
3281 |
+
case 'CLASS':
|
3282 |
+
if( !empty( $this->class )) {
|
3283 |
+
$this->class = '';
|
3284 |
+
$return = TRUE;
|
3285 |
+
}
|
3286 |
+
break;
|
3287 |
+
case 'COMMENT':
|
3288 |
+
return $this->deletePropertyM( $this->comment, $this->propdelix[$propName] );
|
3289 |
+
break;
|
3290 |
+
case 'COMPLETED':
|
3291 |
+
if( !empty( $this->completed )) {
|
3292 |
+
$this->completed = '';
|
3293 |
+
$return = TRUE;
|
3294 |
+
}
|
3295 |
+
break;
|
3296 |
+
case 'CONTACT':
|
3297 |
+
return $this->deletePropertyM( $this->contact, $this->propdelix[$propName] );
|
3298 |
+
break;
|
3299 |
+
case 'CREATED':
|
3300 |
+
if( !empty( $this->created )) {
|
3301 |
+
$this->created = '';
|
3302 |
+
$return = TRUE;
|
3303 |
+
}
|
3304 |
+
break;
|
3305 |
+
case 'DESCRIPTION':
|
3306 |
+
return $this->deletePropertyM( $this->description, $this->propdelix[$propName] );
|
3307 |
+
break;
|
3308 |
+
case 'DTEND':
|
3309 |
+
if( !empty( $this->dtend )) {
|
3310 |
+
$this->dtend = '';
|
3311 |
+
$return = TRUE;
|
3312 |
+
}
|
3313 |
+
break;
|
3314 |
+
case 'DTSTAMP':
|
3315 |
+
if( in_array( $this->objName, iCalUtilityFunctions::$miscComps ))
|
3316 |
+
return FALSE;
|
3317 |
+
if( !empty( $this->dtstamp )) {
|
3318 |
+
$this->dtstamp = '';
|
3319 |
+
$return = TRUE;
|
3320 |
+
}
|
3321 |
+
break;
|
3322 |
+
case 'DTSTART':
|
3323 |
+
if( !empty( $this->dtstart )) {
|
3324 |
+
$this->dtstart = '';
|
3325 |
+
$return = TRUE;
|
3326 |
+
}
|
3327 |
+
break;
|
3328 |
+
case 'DUE':
|
3329 |
+
if( !empty( $this->due )) {
|
3330 |
+
$this->due = '';
|
3331 |
+
$return = TRUE;
|
3332 |
+
}
|
3333 |
+
break;
|
3334 |
+
case 'DURATION':
|
3335 |
+
if( !empty( $this->duration )) {
|
3336 |
+
$this->duration = '';
|
3337 |
+
$return = TRUE;
|
3338 |
+
}
|
3339 |
+
break;
|
3340 |
+
case 'EXDATE':
|
3341 |
+
return $this->deletePropertyM( $this->exdate, $this->propdelix[$propName] );
|
3342 |
+
break;
|
3343 |
+
case 'EXRULE':
|
3344 |
+
return $this->deletePropertyM( $this->exrule, $this->propdelix[$propName] );
|
3345 |
+
break;
|
3346 |
+
case 'FREEBUSY':
|
3347 |
+
return $this->deletePropertyM( $this->freebusy, $this->propdelix[$propName] );
|
3348 |
+
break;
|
3349 |
+
case 'GEO':
|
3350 |
+
if( !empty( $this->geo )) {
|
3351 |
+
$this->geo = '';
|
3352 |
+
$return = TRUE;
|
3353 |
+
}
|
3354 |
+
break;
|
3355 |
+
case 'LAST-MODIFIED':
|
3356 |
+
if( !empty( $this->lastmodified )) {
|
3357 |
+
$this->lastmodified = '';
|
3358 |
+
$return = TRUE;
|
3359 |
+
}
|
3360 |
+
break;
|
3361 |
+
case 'LOCATION':
|
3362 |
+
if( !empty( $this->location )) {
|
3363 |
+
$this->location = '';
|
3364 |
+
$return = TRUE;
|
3365 |
+
}
|
3366 |
+
break;
|
3367 |
+
case 'ORGANIZER':
|
3368 |
+
if( !empty( $this->organizer )) {
|
3369 |
+
$this->organizer = '';
|
3370 |
+
$return = TRUE;
|
3371 |
+
}
|
3372 |
+
break;
|
3373 |
+
case 'PERCENT-COMPLETE':
|
3374 |
+
if( !empty( $this->percentcomplete )) {
|
3375 |
+
$this->percentcomplete = '';
|
3376 |
+
$return = TRUE;
|
3377 |
+
}
|
3378 |
+
break;
|
3379 |
+
case 'PRIORITY':
|
3380 |
+
if( !empty( $this->priority )) {
|
3381 |
+
$this->priority = '';
|
3382 |
+
$return = TRUE;
|
3383 |
+
}
|
3384 |
+
break;
|
3385 |
+
case 'RDATE':
|
3386 |
+
return $this->deletePropertyM( $this->rdate, $this->propdelix[$propName] );
|
3387 |
+
break;
|
3388 |
+
case 'RECURRENCE-ID':
|
3389 |
+
if( !empty( $this->recurrenceid )) {
|
3390 |
+
$this->recurrenceid = '';
|
3391 |
+
$return = TRUE;
|
3392 |
+
}
|
3393 |
+
break;
|
3394 |
+
case 'RELATED-TO':
|
3395 |
+
return $this->deletePropertyM( $this->relatedto, $this->propdelix[$propName] );
|
3396 |
+
break;
|
3397 |
+
case 'REPEAT':
|
3398 |
+
if( !empty( $this->repeat )) {
|
3399 |
+
$this->repeat = '';
|
3400 |
+
$return = TRUE;
|
3401 |
+
}
|
3402 |
+
break;
|
3403 |
+
case 'REQUEST-STATUS':
|
3404 |
+
return $this->deletePropertyM( $this->requeststatus, $this->propdelix[$propName] );
|
3405 |
+
break;
|
3406 |
+
case 'RESOURCES':
|
3407 |
+
return $this->deletePropertyM( $this->resources, $this->propdelix[$propName] );
|
3408 |
+
break;
|
3409 |
+
case 'RRULE':
|
3410 |
+
return $this->deletePropertyM( $this->rrule, $this->propdelix[$propName] );
|
3411 |
+
break;
|
3412 |
+
case 'SEQUENCE':
|
3413 |
+
if( !empty( $this->sequence )) {
|
3414 |
+
$this->sequence = '';
|
3415 |
+
$return = TRUE;
|
3416 |
+
}
|
3417 |
+
break;
|
3418 |
+
case 'STATUS':
|
3419 |
+
if( !empty( $this->status )) {
|
3420 |
+
$this->status = '';
|
3421 |
+
$return = TRUE;
|
3422 |
+
}
|
3423 |
+
break;
|
3424 |
+
case 'SUMMARY':
|
3425 |
+
if( !empty( $this->summary )) {
|
3426 |
+
$this->summary = '';
|
3427 |
+
$return = TRUE;
|
3428 |
+
}
|
3429 |
+
break;
|
3430 |
+
case 'TRANSP':
|
3431 |
+
if( !empty( $this->transp )) {
|
3432 |
+
$this->transp = '';
|
3433 |
+
$return = TRUE;
|
3434 |
+
}
|
3435 |
+
break;
|
3436 |
+
case 'TRIGGER':
|
3437 |
+
if( !empty( $this->trigger )) {
|
3438 |
+
$this->trigger = '';
|
3439 |
+
$return = TRUE;
|
3440 |
+
}
|
3441 |
+
break;
|
3442 |
+
case 'TZID':
|
3443 |
+
if( !empty( $this->tzid )) {
|
3444 |
+
$this->tzid = '';
|
3445 |
+
$return = TRUE;
|
3446 |
+
}
|
3447 |
+
break;
|
3448 |
+
case 'TZNAME':
|
3449 |
+
return $this->deletePropertyM( $this->tzname, $this->propdelix[$propName] );
|
3450 |
+
break;
|
3451 |
+
case 'TZOFFSETFROM':
|
3452 |
+
if( !empty( $this->tzoffsetfrom )) {
|
3453 |
+
$this->tzoffsetfrom = '';
|
3454 |
+
$return = TRUE;
|
3455 |
+
}
|
3456 |
+
break;
|
3457 |
+
case 'TZOFFSETTO':
|
3458 |
+
if( !empty( $this->tzoffsetto )) {
|
3459 |
+
$this->tzoffsetto = '';
|
3460 |
+
$return = TRUE;
|
3461 |
+
}
|
3462 |
+
break;
|
3463 |
+
case 'TZURL':
|
3464 |
+
if( !empty( $this->tzurl )) {
|
3465 |
+
$this->tzurl = '';
|
3466 |
+
$return = TRUE;
|
3467 |
+
}
|
3468 |
+
break;
|
3469 |
+
case 'UID':
|
3470 |
+
if( in_array( $this->objName, iCalUtilityFunctions::$miscComps ))
|
3471 |
+
return FALSE;
|
3472 |
+
if( ! empty( $this->uid )) {
|
3473 |
+
$this->uid = '';
|
3474 |
+
$return = TRUE;
|
3475 |
+
}
|
3476 |
+
break;
|
3477 |
+
case 'URL':
|
3478 |
+
if( !empty( $this->url )) {
|
3479 |
+
$this->url = '';
|
3480 |
+
$return = TRUE;
|
3481 |
+
}
|
3482 |
+
break;
|
3483 |
+
default:
|
3484 |
+
$reduced = '';
|
3485 |
+
if( $propName != 'X-PROP' ) {
|
3486 |
+
if( !isset( $this->xprop[$propName] )) return FALSE;
|
3487 |
+
foreach( $this->xprop as $k => $a ) {
|
3488 |
+
if(( $k != $propName ) && !empty( $a ))
|
3489 |
+
$reduced[$k] = $a;
|
3490 |
+
}
|
3491 |
+
}
|
3492 |
+
else {
|
3493 |
+
if( count( $this->xprop ) <= $propix ) { unset( $this->propdelix[$propName] ); return FALSE; }
|
3494 |
+
$xpropno = 0;
|
3495 |
+
foreach( $this->xprop as $xpropkey => $xpropvalue ) {
|
3496 |
+
if( $propix != $xpropno )
|
3497 |
+
$reduced[$xpropkey] = $xpropvalue;
|
3498 |
+
$xpropno++;
|
3499 |
+
}
|
3500 |
+
}
|
3501 |
+
$this->xprop = $reduced;
|
3502 |
+
if( empty( $this->xprop )) {
|
3503 |
+
unset( $this->propdelix[$propName] );
|
3504 |
+
return FALSE;
|
3505 |
+
}
|
3506 |
+
return TRUE;
|
3507 |
+
}
|
3508 |
+
return $return;
|
3509 |
+
}
|
3510 |
+
/*********************************************************************************/
|
3511 |
+
/**
|
3512 |
+
* delete component property value, fixing components with multiple occurencies
|
3513 |
+
*
|
3514 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
3515 |
+
* @since 2.8.8 - 2011-03-15
|
3516 |
+
* @param array $multiprop component (multi-)property
|
3517 |
+
* @param int $propix removal counter
|
3518 |
+
* @return bool TRUE
|
3519 |
+
*/
|
3520 |
+
function deletePropertyM( & $multiprop, & $propix ) {
|
3521 |
+
if( isset( $multiprop[$propix] ))
|
3522 |
+
unset( $multiprop[$propix] );
|
3523 |
+
if( empty( $multiprop )) {
|
3524 |
+
$multiprop = '';
|
3525 |
+
unset( $propix );
|
3526 |
+
return FALSE;
|
3527 |
+
}
|
3528 |
+
else
|
3529 |
+
return TRUE;
|
3530 |
+
}
|
3531 |
+
/**
|
3532 |
+
* get component property value/params
|
3533 |
+
*
|
3534 |
+
* if property has multiply values, consequtive function calls are needed
|
3535 |
+
*
|
3536 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
3537 |
+
* @since 2.21.13 - 2015-03-29
|
3538 |
+
* @param string $propName
|
3539 |
+
* @param int $propix specific property in case of multiply occurences
|
3540 |
+
* @param bool $inclParam
|
3541 |
+
* @param bool $specform
|
3542 |
+
* @uses calendarComponent::getProperty()
|
3543 |
+
* @uses iCalUtilityFunctions::_geo2str2()
|
3544 |
+
* @uses iCalUtilityFunctions::$geoLatFmt
|
3545 |
+
* @uses iCalUtilityFunctions::$geoLongFmt
|
3546 |
+
* @uses calendarComponent::_notExistProp()
|
3547 |
+
* @uses iCalUtilityFunctions::$mProps2
|
3548 |
+
* @uses calendarComponent::$propix
|
3549 |
+
* @uses calendarComponent::$action
|
3550 |
+
* @uses calendarComponent::$attendee
|
3551 |
+
* @uses calendarComponent::$categories
|
3552 |
+
* @uses calendarComponent::$class
|
3553 |
+
* @uses calendarComponent::$comment
|
3554 |
+
* @uses calendarComponent::$completed
|
3555 |
+
* @uses calendarComponent::$contact
|
3556 |
+
* @uses calendarComponent::$created
|
3557 |
+
* @uses calendarComponent::$description
|
3558 |
+
* @uses calendarComponent::$dtend
|
3559 |
+
* @uses iCalUtilityFunctions::$miscComps
|
3560 |
+
* @uses calendarComponent::$dtstamp
|
3561 |
+
* @uses calendarComponent::_makeDtstamp()
|
3562 |
+
* @uses calendarComponent::$dtstart
|
3563 |
+
* @uses calendarComponent::$due
|
3564 |
+
* @uses calendarComponent::$duration
|
3565 |
+
* @uses iCalUtilityFunctions::_duration2date()
|
3566 |
+
* @uses calendarComponent::$exdate
|
3567 |
+
* @uses calendarComponent::$exrule
|
3568 |
+
* @uses calendarComponent::$freebusy
|
3569 |
+
* @uses calendarComponent::$geo
|
3570 |
+
* @uses calendarComponent::$lastmodified
|
3571 |
+
* @uses calendarComponent::$location
|
3572 |
+
* @uses calendarComponent::$organizer
|
3573 |
+
* @uses calendarComponent::$percentcomplete
|
3574 |
+
* @uses calendarComponent::$priority
|
3575 |
+
* @uses calendarComponent::$rdate
|
3576 |
+
* @uses calendarComponent::$recurrenceid
|
3577 |
+
* @uses calendarComponent::$relatedto
|
3578 |
+
* @uses calendarComponent::$repeat
|
3579 |
+
* @uses calendarComponent::$requeststatus
|
3580 |
+
* @uses calendarComponent::$resources
|
3581 |
+
* @uses calendarComponent::$rrule
|
3582 |
+
* @uses calendarComponent::$sequence
|
3583 |
+
* @uses calendarComponent::$status
|
3584 |
+
* @uses calendarComponent::$summary
|
3585 |
+
* @uses calendarComponent::$transp
|
3586 |
+
* @uses calendarComponent::$trigger
|
3587 |
+
* @uses calendarComponent::$tzid
|
3588 |
+
* @uses calendarComponent::$tzname
|
3589 |
+
* @uses calendarComponent::$tzoffsetfrom
|
3590 |
+
* @uses calendarComponent::$tzoffsetto
|
3591 |
+
* @uses calendarComponent::$tzurl
|
3592 |
+
* @uses calendarComponent::$uid
|
3593 |
+
* @uses calendarComponent::$objName
|
3594 |
+
* @uses calendarComponent::_makeuid()
|
3595 |
+
* @uses calendarComponent::$url
|
3596 |
+
* @uses calendarComponent::$xprop
|
3597 |
+
* @return mixed
|
3598 |
+
*/
|
3599 |
+
function getProperty( $propName=FALSE, $propix=FALSE, $inclParam=FALSE, $specform=FALSE ) {
|
3600 |
+
if( 'GEOLOCATION' == strtoupper( $propName )) {
|
3601 |
+
$content = ( FALSE === ( $loc = $this->getProperty( 'LOCATION' ))) ? '' : $loc.' ';
|
3602 |
+
if( FALSE === ( $geo = $this->getProperty( 'GEO' )))
|
3603 |
+
return FALSE;
|
3604 |
+
return $content.
|
3605 |
+
iCalUtilityFunctions::_geo2str2( $geo['latitude'], iCalUtilityFunctions::$geoLatFmt ).
|
3606 |
+
iCalUtilityFunctions::_geo2str2( $geo['longitude'], iCalUtilityFunctions::$geoLongFmt ).'/';
|
3607 |
+
}
|
3608 |
+
if( $this->_notExistProp( $propName )) return FALSE;
|
3609 |
+
$propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
|
3610 |
+
if( in_array( $propName, iCalUtilityFunctions::$mProps2 )) {
|
3611 |
+
if( empty( $propix ))
|
3612 |
+
$propix = ( isset( $this->propix[$propName] )) ? $this->propix[$propName] + 2 : 1;
|
3613 |
+
$this->propix[$propName] = --$propix;
|
3614 |
+
}
|
3615 |
+
switch( $propName ) {
|
3616 |
+
case 'ACTION':
|
3617 |
+
if( isset( $this->action['value'] )) return ( $inclParam ) ? $this->action : $this->action['value'];
|
3618 |
+
break;
|
3619 |
+
case 'ATTACH':
|
3620 |
+
$ak = ( is_array( $this->attach )) ? array_keys( $this->attach ) : array();
|
3621 |
+
while( is_array( $this->attach ) && !isset( $this->attach[$propix] ) && ( 0 < count( $this->attach )) && ( $propix < end( $ak )))
|
3622 |
+
$propix++;
|
3623 |
+
$this->propix[$propName] = $propix;
|
3624 |
+
if( !isset( $this->attach[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3625 |
+
return ( $inclParam ) ? $this->attach[$propix] : $this->attach[$propix]['value'];
|
3626 |
+
break;
|
3627 |
+
case 'ATTENDEE':
|
3628 |
+
$ak = ( is_array( $this->attendee )) ? array_keys( $this->attendee ) : array();
|
3629 |
+
while( is_array( $this->attendee ) && !isset( $this->attendee[$propix] ) && ( 0 < count( $this->attendee )) && ( $propix < end( $ak )))
|
3630 |
+
$propix++;
|
3631 |
+
$this->propix[$propName] = $propix;
|
3632 |
+
if( !isset( $this->attendee[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3633 |
+
return ( $inclParam ) ? $this->attendee[$propix] : $this->attendee[$propix]['value'];
|
3634 |
+
break;
|
3635 |
+
case 'CATEGORIES':
|
3636 |
+
$ak = ( is_array( $this->categories )) ? array_keys( $this->categories ) : array();
|
3637 |
+
while( is_array( $this->categories ) && !isset( $this->categories[$propix] ) && ( 0 < count( $this->categories )) && ( $propix < end( $ak )))
|
3638 |
+
$propix++;
|
3639 |
+
$this->propix[$propName] = $propix;
|
3640 |
+
if( !isset( $this->categories[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3641 |
+
return ( $inclParam ) ? $this->categories[$propix] : $this->categories[$propix]['value'];
|
3642 |
+
break;
|
3643 |
+
case 'CLASS':
|
3644 |
+
if( isset( $this->class['value'] )) return ( $inclParam ) ? $this->class : $this->class['value'];
|
3645 |
+
break;
|
3646 |
+
case 'COMMENT':
|
3647 |
+
$ak = ( is_array( $this->comment )) ? array_keys( $this->comment ) : array();
|
3648 |
+
while( is_array( $this->comment ) && !isset( $this->comment[$propix] ) && ( 0 < count( $this->comment )) && ( $propix < end( $ak )))
|
3649 |
+
$propix++;
|
3650 |
+
$this->propix[$propName] = $propix;
|
3651 |
+
if( !isset( $this->comment[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3652 |
+
return ( $inclParam ) ? $this->comment[$propix] : $this->comment[$propix]['value'];
|
3653 |
+
break;
|
3654 |
+
case 'COMPLETED':
|
3655 |
+
if( isset( $this->completed['value'] )) return ( $inclParam ) ? $this->completed : $this->completed['value'];
|
3656 |
+
break;
|
3657 |
+
case 'CONTACT':
|
3658 |
+
$ak = ( is_array( $this->contact )) ? array_keys( $this->contact ) : array();
|
3659 |
+
while( is_array( $this->contact ) && !isset( $this->contact[$propix] ) && ( 0 < count( $this->contact )) && ( $propix < end( $ak )))
|
3660 |
+
$propix++;
|
3661 |
+
$this->propix[$propName] = $propix;
|
3662 |
+
if( !isset( $this->contact[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3663 |
+
return ( $inclParam ) ? $this->contact[$propix] : $this->contact[$propix]['value'];
|
3664 |
+
break;
|
3665 |
+
case 'CREATED':
|
3666 |
+
if( isset( $this->created['value'] )) return ( $inclParam ) ? $this->created : $this->created['value'];
|
3667 |
+
break;
|
3668 |
+
case 'DESCRIPTION':
|
3669 |
+
$ak = ( is_array( $this->description )) ? array_keys( $this->description ) : array();
|
3670 |
+
while( is_array( $this->description ) && !isset( $this->description[$propix] ) && ( 0 < count( $this->description )) && ( $propix < end( $ak )))
|
3671 |
+
$propix++;
|
3672 |
+
$this->propix[$propName] = $propix;
|
3673 |
+
if( !isset( $this->description[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3674 |
+
return ( $inclParam ) ? $this->description[$propix] : $this->description[$propix]['value'];
|
3675 |
+
break;
|
3676 |
+
case 'DTEND':
|
3677 |
+
if( isset( $this->dtend['value'] )) return ( $inclParam ) ? $this->dtend : $this->dtend['value'];
|
3678 |
+
break;
|
3679 |
+
case 'DTSTAMP':
|
3680 |
+
if( in_array( $this->objName, iCalUtilityFunctions::$miscComps ))
|
3681 |
+
return;
|
3682 |
+
if( !isset( $this->dtstamp['value'] ))
|
3683 |
+
$this->_makeDtstamp();
|
3684 |
+
return ( $inclParam ) ? $this->dtstamp : $this->dtstamp['value'];
|
3685 |
+
break;
|
3686 |
+
case 'DTSTART':
|
3687 |
+
if( isset( $this->dtstart['value'] )) return ( $inclParam ) ? $this->dtstart : $this->dtstart['value'];
|
3688 |
+
break;
|
3689 |
+
case 'DUE':
|
3690 |
+
if( isset( $this->due['value'] )) return ( $inclParam ) ? $this->due : $this->due['value'];
|
3691 |
+
break;
|
3692 |
+
case 'DURATION':
|
3693 |
+
if( ! isset( $this->duration['value'] )) return FALSE;
|
3694 |
+
$value = ( $specform && isset( $this->dtstart['value'] ) && isset( $this->duration['value'] )) ? iCalUtilityFunctions::_duration2date( $this->dtstart['value'], $this->duration['value'] ) : $this->duration['value'];
|
3695 |
+
$params = ( $specform && $inclParam && isset( $this->dtstart['params']['TZID'] )) ? array_merge((array) $this->duration['params'], $this->dtstart['params'] ) : $this->duration['params'];
|
3696 |
+
return ( $inclParam ) ? array( 'value' => $value, 'params' => $params ) : $value;
|
3697 |
+
break;
|
3698 |
+
case 'EXDATE':
|
3699 |
+
$ak = ( is_array( $this->exdate )) ? array_keys( $this->exdate ) : array();
|
3700 |
+
while( is_array( $this->exdate ) && !isset( $this->exdate[$propix] ) && ( 0 < count( $this->exdate )) && ( $propix < end( $ak )))
|
3701 |
+
$propix++;
|
3702 |
+
$this->propix[$propName] = $propix;
|
3703 |
+
if( !isset( $this->exdate[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3704 |
+
return ( $inclParam ) ? $this->exdate[$propix] : $this->exdate[$propix]['value'];
|
3705 |
+
break;
|
3706 |
+
case 'EXRULE':
|
3707 |
+
$ak = ( is_array( $this->exrule )) ? array_keys( $this->exrule ) : array();
|
3708 |
+
while( is_array( $this->exrule ) && !isset( $this->exrule[$propix] ) && ( 0 < count( $this->exrule )) && ( $propix < end( $ak )))
|
3709 |
+
$propix++;
|
3710 |
+
$this->propix[$propName] = $propix;
|
3711 |
+
if( !isset( $this->exrule[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3712 |
+
return ( $inclParam ) ? $this->exrule[$propix] : $this->exrule[$propix]['value'];
|
3713 |
+
break;
|
3714 |
+
case 'FREEBUSY':
|
3715 |
+
$ak = ( is_array( $this->freebusy )) ? array_keys( $this->freebusy ) : array();
|
3716 |
+
while( is_array( $this->freebusy ) && !isset( $this->freebusy[$propix] ) && ( 0 < count( $this->freebusy )) && ( $propix < end( $ak )))
|
3717 |
+
$propix++;
|
3718 |
+
$this->propix[$propName] = $propix;
|
3719 |
+
if( !isset( $this->freebusy[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3720 |
+
return ( $inclParam ) ? $this->freebusy[$propix] : $this->freebusy[$propix]['value'];
|
3721 |
+
break;
|
3722 |
+
case 'GEO':
|
3723 |
+
if( isset( $this->geo['value'] )) return ( $inclParam ) ? $this->geo : $this->geo['value'];
|
3724 |
+
break;
|
3725 |
+
case 'LAST-MODIFIED':
|
3726 |
+
if( isset( $this->lastmodified['value'] )) return ( $inclParam ) ? $this->lastmodified : $this->lastmodified['value'];
|
3727 |
+
break;
|
3728 |
+
case 'LOCATION':
|
3729 |
+
if( isset( $this->location['value'] )) return ( $inclParam ) ? $this->location : $this->location['value'];
|
3730 |
+
break;
|
3731 |
+
case 'ORGANIZER':
|
3732 |
+
if( isset( $this->organizer['value'] )) return ( $inclParam ) ? $this->organizer : $this->organizer['value'];
|
3733 |
+
break;
|
3734 |
+
case 'PERCENT-COMPLETE':
|
3735 |
+
if( isset( $this->percentcomplete['value'] )) return ( $inclParam ) ? $this->percentcomplete : $this->percentcomplete['value'];
|
3736 |
+
break;
|
3737 |
+
case 'PRIORITY':
|
3738 |
+
if( isset( $this->priority['value'] )) return ( $inclParam ) ? $this->priority : $this->priority['value'];
|
3739 |
+
break;
|
3740 |
+
case 'RDATE':
|
3741 |
+
$ak = ( is_array( $this->rdate )) ? array_keys( $this->rdate ) : array();
|
3742 |
+
while( is_array( $this->rdate ) && !isset( $this->rdate[$propix] ) && ( 0 < count( $this->rdate )) && ( $propix < end( $ak )))
|
3743 |
+
$propix++;
|
3744 |
+
$this->propix[$propName] = $propix;
|
3745 |
+
if( !isset( $this->rdate[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3746 |
+
return ( $inclParam ) ? $this->rdate[$propix] : $this->rdate[$propix]['value'];
|
3747 |
+
break;
|
3748 |
+
case 'RECURRENCE-ID':
|
3749 |
+
if( isset( $this->recurrenceid['value'] )) return ( $inclParam ) ? $this->recurrenceid : $this->recurrenceid['value'];
|
3750 |
+
break;
|
3751 |
+
case 'RELATED-TO':
|
3752 |
+
$ak = ( is_array( $this->relatedto )) ? array_keys( $this->relatedto ) : array();
|
3753 |
+
while( is_array( $this->relatedto ) && !isset( $this->relatedto[$propix] ) && ( 0 < count( $this->relatedto )) && ( $propix < end( $ak )))
|
3754 |
+
$propix++;
|
3755 |
+
$this->propix[$propName] = $propix;
|
3756 |
+
if( !isset( $this->relatedto[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3757 |
+
return ( $inclParam ) ? $this->relatedto[$propix] : $this->relatedto[$propix]['value'];
|
3758 |
+
break;
|
3759 |
+
case 'REPEAT':
|
3760 |
+
if( isset( $this->repeat['value'] )) return ( $inclParam ) ? $this->repeat : $this->repeat['value'];
|
3761 |
+
break;
|
3762 |
+
case 'REQUEST-STATUS':
|
3763 |
+
$ak = ( is_array( $this->requeststatus )) ? array_keys( $this->requeststatus ) : array();
|
3764 |
+
while( is_array( $this->requeststatus ) && !isset( $this->requeststatus[$propix] ) && ( 0 < count( $this->requeststatus )) && ( $propix < end( $ak )))
|
3765 |
+
$propix++;
|
3766 |
+
$this->propix[$propName] = $propix;
|
3767 |
+
if( !isset( $this->requeststatus[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3768 |
+
return ( $inclParam ) ? $this->requeststatus[$propix] : $this->requeststatus[$propix]['value'];
|
3769 |
+
break;
|
3770 |
+
case 'RESOURCES':
|
3771 |
+
$ak = ( is_array( $this->resources )) ? array_keys( $this->resources ) : array();
|
3772 |
+
while( is_array( $this->resources ) && !isset( $this->resources[$propix] ) && ( 0 < count( $this->resources )) && ( $propix < end( $ak )))
|
3773 |
+
$propix++;
|
3774 |
+
$this->propix[$propName] = $propix;
|
3775 |
+
if( !isset( $this->resources[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3776 |
+
return ( $inclParam ) ? $this->resources[$propix] : $this->resources[$propix]['value'];
|
3777 |
+
break;
|
3778 |
+
case 'RRULE':
|
3779 |
+
$ak = ( is_array( $this->rrule )) ? array_keys( $this->rrule ) : array();
|
3780 |
+
while( is_array( $this->rrule ) && !isset( $this->rrule[$propix] ) && ( 0 < count( $this->rrule )) && ( $propix < end( $ak )))
|
3781 |
+
$propix++;
|
3782 |
+
$this->propix[$propName] = $propix;
|
3783 |
+
if( !isset( $this->rrule[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3784 |
+
return ( $inclParam ) ? $this->rrule[$propix] : $this->rrule[$propix]['value'];
|
3785 |
+
break;
|
3786 |
+
case 'SEQUENCE':
|
3787 |
+
if( isset( $this->sequence['value'] )) return ( $inclParam ) ? $this->sequence : $this->sequence['value'];
|
3788 |
+
break;
|
3789 |
+
case 'STATUS':
|
3790 |
+
if( isset( $this->status['value'] )) return ( $inclParam ) ? $this->status : $this->status['value'];
|
3791 |
+
break;
|
3792 |
+
case 'SUMMARY':
|
3793 |
+
if( isset( $this->summary['value'] )) return ( $inclParam ) ? $this->summary : $this->summary['value'];
|
3794 |
+
break;
|
3795 |
+
case 'TRANSP':
|
3796 |
+
if( isset( $this->transp['value'] )) return ( $inclParam ) ? $this->transp : $this->transp['value'];
|
3797 |
+
break;
|
3798 |
+
case 'TRIGGER':
|
3799 |
+
if( isset( $this->trigger['value'] )) return ( $inclParam ) ? $this->trigger : $this->trigger['value'];
|
3800 |
+
break;
|
3801 |
+
case 'TZID':
|
3802 |
+
if( isset( $this->tzid['value'] )) return ( $inclParam ) ? $this->tzid : $this->tzid['value'];
|
3803 |
+
break;
|
3804 |
+
case 'TZNAME':
|
3805 |
+
$ak = ( is_array( $this->tzname )) ? array_keys( $this->tzname ) : array();
|
3806 |
+
while( is_array( $this->tzname ) && !isset( $this->tzname[$propix] ) && ( 0 < count( $this->tzname )) && ( $propix < end( $ak )))
|
3807 |
+
$propix++;
|
3808 |
+
$this->propix[$propName] = $propix;
|
3809 |
+
if( !isset( $this->tzname[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
|
3810 |
+
return ( $inclParam ) ? $this->tzname[$propix] : $this->tzname[$propix]['value'];
|
3811 |
+
break;
|
3812 |
+
case 'TZOFFSETFROM':
|
3813 |
+
if( isset( $this->tzoffsetfrom['value'] )) return ( $inclParam ) ? $this->tzoffsetfrom : $this->tzoffsetfrom['value'];
|
3814 |
+
break;
|
3815 |
+
case 'TZOFFSETTO':
|
3816 |
+
if( isset( $this->tzoffsetto['value'] )) return ( $inclParam ) ? $this->tzoffsetto : $this->tzoffsetto['value'];
|
3817 |
+
break;
|
3818 |
+
case 'TZURL':
|
3819 |
+
if( isset( $this->tzurl['value'] )) return ( $inclParam ) ? $this->tzurl : $this->tzurl['value'];
|
3820 |
+
break;
|
3821 |
+
case 'UID':
|
3822 |
+
if( in_array( $this->objName, iCalUtilityFunctions::$miscComps ))
|
3823 |
+
return FALSE;
|
3824 |
+
if( empty( $this->uid ))
|
3825 |
+
$this->_makeuid();
|
3826 |
+
return ( $inclParam ) ? $this->uid : $this->uid['value'];
|
3827 |
+
break;
|
3828 |
+
case 'URL':
|
3829 |
+
if( isset( $this->url['value'] )) return ( $inclParam ) ? $this->url : $this->url['value'];
|
3830 |
+
break;
|
3831 |
+
default:
|
3832 |
+
if( $propName != 'X-PROP' ) {
|
3833 |
+
if( !isset( $this->xprop[$propName] )) return FALSE;
|
3834 |
+
return ( $inclParam ) ? array( $propName, $this->xprop[$propName] )
|
3835 |
+
: array( $propName, $this->xprop[$propName]['value'] );
|
3836 |
+
}
|
3837 |
+
else {
|
3838 |
+
if( empty( $this->xprop )) return FALSE;
|
3839 |
+
$xpropno = 0;
|
3840 |
+
foreach( $this->xprop as $xpropkey => $xpropvalue ) {
|
3841 |
+
if( $propix == $xpropno )
|
3842 |
+
return ( $inclParam ) ? array( $xpropkey, $this->xprop[$xpropkey] )
|
3843 |
+
: array( $xpropkey, $this->xprop[$xpropkey]['value'] );
|
3844 |
+
else
|
3845 |
+
$xpropno++;
|
3846 |
+
}
|
3847 |
+
return FALSE; // not found ??
|
3848 |
+
}
|
3849 |
+
}
|
3850 |
+
return FALSE;
|
3851 |
+
}
|
3852 |
+
/**
|
3853 |
+
* returns calendar property unique values for 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'RELATED-TO' or 'RESOURCES' and for each, number of occurrence
|
3854 |
+
*
|
3855 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
3856 |
+
* @since 2.21.11 - 2015-03-21
|
3857 |
+
* @param string $propName
|
3858 |
+
* @param array $output incremented result array
|
3859 |
+
* @uses iCalUtilityFunctions::$mProps1
|
3860 |
+
* @uses calendarComponent::getProperty()
|
3861 |
+
* return void
|
3862 |
+
*/
|
3863 |
+
function _getProperties( $propName, & $output ) {
|
3864 |
+
if( empty( $output ))
|
3865 |
+
$output = array();
|
3866 |
+
if( !in_array( strtoupper( $propName ), iCalUtilityFunctions::$mProps1 ))
|
3867 |
+
return $output;
|
3868 |
+
while( FALSE !== ( $content = $this->getProperty( $propName ))) {
|
3869 |
+
if( empty( $content ))
|
3870 |
+
continue;
|
3871 |
+
if( is_array( $content )) {
|
3872 |
+
foreach( $content as $part ) {
|
3873 |
+
if( FALSE !== strpos( $part, ',' )) {
|
3874 |
+
$part = explode( ',', $part );
|
3875 |
+
foreach( $part as $thePart ) {
|
3876 |
+
$thePart = trim( $thePart );
|
3877 |
+
if( !empty( $thePart )) {
|
3878 |
+
if( !isset( $output[$thePart] ))
|
3879 |
+
$output[$thePart] = 1;
|
3880 |
+
else
|
3881 |
+
$output[$thePart] += 1;
|
3882 |
+
}
|
3883 |
+
}
|
3884 |
+
}
|
3885 |
+
else {
|
3886 |
+
$part = trim( $part );
|
3887 |
+
if( !isset( $output[$part] ))
|
3888 |
+
$output[$part] = 1;
|
3889 |
+
else
|
3890 |
+
$output[$part] += 1;
|
3891 |
+
}
|
3892 |
+
}
|
3893 |
+
} // end if( is_array( $content ))
|
3894 |
+
elseif( FALSE !== strpos( $content, ',' )) {
|
3895 |
+
$content = explode( ',', $content );
|
3896 |
+
foreach( $content as $thePart ) {
|
3897 |
+
$thePart = trim( $thePart );
|
3898 |
+
if( !empty( $thePart )) {
|
3899 |
+
if( !isset( $output[$thePart] ))
|
3900 |
+
$output[$thePart] = 1;
|
3901 |
+
else
|
3902 |
+
$output[$thePart] += 1;
|
3903 |
+
}
|
3904 |
+
}
|
3905 |
+
} // end elseif( FALSE !== strpos( $content, ',' ))
|
3906 |
+
else {
|
3907 |
+
$content = trim( $content );
|
3908 |
+
if( !empty( $content )) {
|
3909 |
+
if( !isset( $output[$content] ))
|
3910 |
+
$output[$content] = 1;
|
3911 |
+
else
|
3912 |
+
$output[$content] += 1;
|
3913 |
+
}
|
3914 |
+
}
|
3915 |
+
}
|
3916 |
+
ksort( $output );
|
3917 |
+
}
|
3918 |
+
/**
|
3919 |
+
* general component property setting
|
3920 |
+
*
|
3921 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
3922 |
+
* @since 2.5.1 - 2008-11-05
|
3923 |
+
* @param mixed $args variable number of function arguments,
|
3924 |
+
* first argument is ALWAYS component name,
|
3925 |
+
* second ALWAYS component value!
|
3926 |
+
* @uses calendarComponent::getProperty()
|
3927 |
+
* @uses calendarComponent::_notExistProp()
|
3928 |
+
* @uses calendarComponent::getConfig()
|
3929 |
+
* @uses calendarComponent::setAction()
|
3930 |
+
* @uses calendarComponent::setAttendee()
|
3931 |
+
* @uses calendarComponent::setCategories()
|
3932 |
+
* @uses calendarComponent::setClass()
|
3933 |
+
* @uses calendarComponent::setComment()
|
3934 |
+
* @uses calendarComponent::setCompleted()
|
3935 |
+
* @uses calendarComponent::setContact()
|
3936 |
+
* @uses calendarComponent::setCreated()
|
3937 |
+
* @uses calendarComponent::setDescription()
|
3938 |
+
* @uses calendarComponent::setDtend()
|
3939 |
+
* @uses calendarComponent::setDtstamp()
|
3940 |
+
* @uses calendarComponent::setDtstart()
|
3941 |
+
* @uses calendarComponent::setDue()
|
3942 |
+
* @uses calendarComponent::setDuration()
|
3943 |
+
* @uses calendarComponent::setExdate()
|
3944 |
+
* @uses calendarComponent::setExrule()
|
3945 |
+
* @uses calendarComponent::setFreebusy()
|
3946 |
+
* @uses calendarComponent::setGeo()
|
3947 |
+
* @uses calendarComponent::setLastmodified()
|
3948 |
+
* @uses calendarComponent::setLocation()
|
3949 |
+
* @uses calendarComponent::setOrganizer()
|
3950 |
+
* @uses calendarComponent::setPercentcomplete()
|
3951 |
+
* @uses calendarComponent::setPriority()
|
3952 |
+
* @uses calendarComponent::setRdate()
|
3953 |
+
* @uses calendarComponent::setRecurrenceid()
|
3954 |
+
* @uses calendarComponent::setRelatedto()
|
3955 |
+
* @uses calendarComponent::setRepeat()
|
3956 |
+
* @uses calendarComponent::setRequeststatus()
|
3957 |
+
* @uses calendarComponent::setResources()
|
3958 |
+
* @uses calendarComponent::setRrule()
|
3959 |
+
* @uses calendarComponent::setSequence()
|
3960 |
+
* @uses calendarComponent::setStatus()
|
3961 |
+
* @uses calendarComponent::setSummary()
|
3962 |
+
* @uses calendarComponent::setTransp()
|
3963 |
+
* @uses calendarComponent::setTrigger()
|
3964 |
+
* @uses calendarComponent::setTzid()
|
3965 |
+
* @uses calendarComponent::setTzname()
|
3966 |
+
* @uses calendarComponent::setTzoffsetfrom()
|
3967 |
+
* @uses calendarComponent::setTzoffsetto()
|
3968 |
+
* @uses calendarComponent::setTzurl()
|
3969 |
+
* @uses calendarComponent::setUid()
|
3970 |
+
* @uses calendarComponent::$objName
|
3971 |
+
* @uses calendarComponent::setUrl()
|
3972 |
+
* @uses calendarComponent::setXprop()
|
3973 |
+
* @return void
|
3974 |
+
*/
|
3975 |
+
function setProperty() {
|
3976 |
+
$numargs = func_num_args();
|
3977 |
+
if( 1 > $numargs ) return FALSE;
|
3978 |
+
$arglist = func_get_args();
|
3979 |
+
if( $this->_notExistProp( $arglist[0] )) return FALSE;
|
3980 |
+
if( !$this->getConfig( 'allowEmpty' ) && ( !isset( $arglist[1] ) || empty( $arglist[1] )))
|
3981 |
+
return FALSE;
|
3982 |
+
$arglist[0] = strtoupper( $arglist[0] );
|
3983 |
+
for( $argix=$numargs; $argix < 12; $argix++ ) {
|
3984 |
+
if( !isset( $arglist[$argix] ))
|
3985 |
+
$arglist[$argix] = null;
|
3986 |
+
}
|
3987 |
+
switch( $arglist[0] ) {
|
3988 |
+
case 'ACTION':
|
3989 |
+
return $this->setAction( $arglist[1], $arglist[2] );
|
3990 |
+
case 'ATTACH':
|
3991 |
+
return $this->setAttach( $arglist[1], $arglist[2], $arglist[3] );
|
3992 |
+
case 'ATTENDEE':
|
3993 |
+
return $this->setAttendee( $arglist[1], $arglist[2], $arglist[3] );
|
3994 |
+
case 'CATEGORIES':
|
3995 |
+
return $this->setCategories( $arglist[1], $arglist[2], $arglist[3] );
|
3996 |
+
case 'CLASS':
|
3997 |
+
return $this->setClass( $arglist[1], $arglist[2] );
|
3998 |
+
case 'COMMENT':
|
3999 |
+
return $this->setComment( $arglist[1], $arglist[2], $arglist[3] );
|
4000 |
+
case 'COMPLETED':
|
4001 |
+
return $this->setCompleted( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
|
4002 |
+
case 'CONTACT':
|
4003 |
+
return $this->setContact( $arglist[1], $arglist[2], $arglist[3] );
|
4004 |
+
case 'CREATED':
|
4005 |
+
return $this->setCreated( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
|
4006 |
+
case 'DESCRIPTION':
|
4007 |
+
return $this->setDescription( $arglist[1], $arglist[2], $arglist[3] );
|
4008 |
+
case 'DTEND':
|
4009 |
+
return $this->setDtend( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
|
4010 |
+
case 'DTSTAMP':
|
4011 |
+
return $this->setDtstamp( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
|
4012 |
+
case 'DTSTART':
|
4013 |
+
return $this->setDtstart( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
|
4014 |
+
case 'DUE':
|
4015 |
+
return $this->setDue( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
|
4016 |
+
case 'DURATION':
|
4017 |
+
return $this->setDuration( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6] );
|
4018 |
+
case 'EXDATE':
|
4019 |
+
return $this->setExdate( $arglist[1], $arglist[2], $arglist[3] );
|
4020 |
+
case 'EXRULE':
|
4021 |
+
return $this->setExrule( $arglist[1], $arglist[2], $arglist[3] );
|
4022 |
+
case 'FREEBUSY':
|
4023 |
+
return $this->setFreebusy( $arglist[1], $arglist[2], $arglist[3], $arglist[4] );
|
4024 |
+
case 'GEO':
|
4025 |
+
return $this->setGeo( $arglist[1], $arglist[2], $arglist[3] );
|
4026 |
+
case 'LAST-MODIFIED':
|
4027 |
+
return $this->setLastModified( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
|
4028 |
+
case 'LOCATION':
|
4029 |
+
return $this->setLocation( $arglist[1], $arglist[2] );
|
4030 |
+
case 'ORGANIZER':
|
4031 |
+
return $this->setOrganizer( $arglist[1], $arglist[2] );
|
4032 |
+
case 'PERCENT-COMPLETE':
|
4033 |
+
return $this->setPercentComplete( $arglist[1], $arglist[2] );
|
4034 |
+
case 'PRIORITY':
|
4035 |
+
return $this->setPriority( $arglist[1], $arglist[2] );
|
4036 |
+
case 'RDATE':
|
4037 |
+
return $this->setRdate( $arglist[1], $arglist[2], $arglist[3] );
|
4038 |
+
case 'RECURRENCE-ID':
|
4039 |
+
return $this->setRecurrenceid( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
|
4040 |
+
case 'RELATED-TO':
|
4041 |
+
return $this->setRelatedTo( $arglist[1], $arglist[2], $arglist[3] );
|
4042 |
+
case 'REPEAT':
|
4043 |
+
return $this->setRepeat( $arglist[1], $arglist[2] );
|
4044 |
+
case 'REQUEST-STATUS':
|
4045 |
+
return $this->setRequestStatus( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5] );
|
4046 |
+
case 'RESOURCES':
|
4047 |
+
return $this->setResources( $arglist[1], $arglist[2], $arglist[3] );
|
4048 |
+
case 'RRULE':
|
4049 |
+
return $this->setRrule( $arglist[1], $arglist[2], $arglist[3] );
|
4050 |
+
case 'SEQUENCE':
|
4051 |
+
return $this->setSequence( $arglist[1], $arglist[2] );
|
4052 |
+
case 'STATUS':
|
4053 |
+
return $this->setStatus( $arglist[1], $arglist[2] );
|
4054 |
+
case 'SUMMARY':
|
4055 |
+
return $this->setSummary( $arglist[1], $arglist[2] );
|
4056 |
+
case 'TRANSP':
|
4057 |
+
return $this->setTransp( $arglist[1], $arglist[2] );
|
4058 |
+
case 'TRIGGER':
|
4059 |
+
return $this->setTrigger( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8], $arglist[9], $arglist[10], $arglist[11] );
|
4060 |
+
case 'TZID':
|
4061 |
+
return $this->setTzid( $arglist[1], $arglist[2] );
|
4062 |
+
case 'TZNAME':
|
4063 |
+
return $this->setTzname( $arglist[1], $arglist[2], $arglist[3] );
|
4064 |
+
case 'TZOFFSETFROM':
|
4065 |
+
return $this->setTzoffsetfrom( $arglist[1], $arglist[2] );
|
4066 |
+
case 'TZOFFSETTO':
|
4067 |
+
return $this->setTzoffsetto( $arglist[1], $arglist[2] );
|
4068 |
+
case 'TZURL':
|
4069 |
+
return $this->setTzurl( $arglist[1], $arglist[2] );
|
4070 |
+
case 'UID':
|
4071 |
+
return $this->setUid( $arglist[1], $arglist[2] );
|
4072 |
+
case 'URL':
|
4073 |
+
return $this->setUrl( $arglist[1], $arglist[2] );
|
4074 |
+
default:
|
4075 |
+
return $this->setXprop( $arglist[0], $arglist[1], $arglist[2] );
|
4076 |
+
}
|
4077 |
+
return FALSE;
|
4078 |
+
}
|
4079 |
+
/*********************************************************************************/
|
4080 |
+
/**
|
4081 |
+
* parse component unparsed data into properties
|
4082 |
+
*
|
4083 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4084 |
+
* @since 2.20.3 - 2015-03-05
|
4085 |
+
* @param mixed $unparsedtext strict rfc2445 formatted, single property string or array of strings
|
4086 |
+
* @uses calendarComponent::getConfig()
|
4087 |
+
* @uses iCalUtilityFunctions::convEolChar()
|
4088 |
+
* @uses calendarComponent::$unparsed
|
4089 |
+
* @uses calendarComponent::$components
|
4090 |
+
* @uses calendarComponent::copy()
|
4091 |
+
* @uses iCalUtilityFunctions::_splitContent()
|
4092 |
+
* @uses calendarComponent::setProperty()
|
4093 |
+
* @uses iCalUtilityFunctions::_strunrep()
|
4094 |
+
* @uses calendarComponent::parse()
|
4095 |
+
* @return bool FALSE if error occurs during parsing
|
4096 |
+
*/
|
4097 |
+
function parse( $unparsedtext=null ) {
|
4098 |
+
$nl = $this->getConfig( 'nl' );
|
4099 |
+
if( !empty( $unparsedtext )) {
|
4100 |
+
if( is_array( $unparsedtext ))
|
4101 |
+
$unparsedtext = implode( '\n'.$nl, $unparsedtext );
|
4102 |
+
$unparsedtext = iCalUtilityFunctions::convEolChar( $unparsedtext, $nl );
|
4103 |
+
}
|
4104 |
+
elseif( !isset( $this->unparsed ))
|
4105 |
+
$unparsedtext = array();
|
4106 |
+
else
|
4107 |
+
$unparsedtext = $this->unparsed;
|
4108 |
+
/* skip leading (empty/invalid) lines */
|
4109 |
+
foreach( $unparsedtext as $lix => $line ) {
|
4110 |
+
if( FALSE !== ( $pos = stripos( $line, 'BEGIN:' ))) {
|
4111 |
+
$unparsedtext[$lix] = substr( $unparsedtext[$lix], $pos );
|
4112 |
+
break;
|
4113 |
+
}
|
4114 |
+
$tst = trim( $line );
|
4115 |
+
if(( '\n' == $tst ) || empty( $tst ))
|
4116 |
+
unset( $unparsedtext[$lix] );
|
4117 |
+
}
|
4118 |
+
$this->unparsed = array();
|
4119 |
+
$comp = & $this;
|
4120 |
+
$config = $this->getConfig();
|
4121 |
+
$compsync = $subsync = 0;
|
4122 |
+
foreach ( $unparsedtext as $lix => $line ) {
|
4123 |
+
if( 'END:VALARM' == strtoupper( substr( $line, 0, 10 ))) {
|
4124 |
+
if( 1 != $subsync ) return FALSE;
|
4125 |
+
$this->components[] = $comp->copy();
|
4126 |
+
$subsync--;
|
4127 |
+
}
|
4128 |
+
elseif( 'END:DAYLIGHT' == strtoupper( substr( $line, 0, 12 ))) {
|
4129 |
+
if( 1 != $subsync ) return FALSE;
|
4130 |
+
$this->components[] = $comp->copy();
|
4131 |
+
$subsync--;
|
4132 |
+
}
|
4133 |
+
elseif( 'END:STANDARD' == strtoupper( substr( $line, 0, 12 ))) {
|
4134 |
+
if( 1 != $subsync ) return FALSE;
|
4135 |
+
array_unshift( $this->components, $comp->copy());
|
4136 |
+
$subsync--;
|
4137 |
+
}
|
4138 |
+
elseif( 'END:' == strtoupper( substr( $line, 0, 4 ))) { // end:<component>
|
4139 |
+
if( 1 != $compsync ) return FALSE;
|
4140 |
+
if( 0 < $subsync )
|
4141 |
+
$this->components[] = $comp->copy();
|
4142 |
+
$compsync--;
|
4143 |
+
break; /* skip trailing empty lines */
|
4144 |
+
}
|
4145 |
+
elseif( 'BEGIN:VALARM' == strtoupper( substr( $line, 0, 12 ))) {
|
4146 |
+
$comp = new valarm( $config);
|
4147 |
+
$subsync++;
|
4148 |
+
}
|
4149 |
+
elseif( 'BEGIN:STANDARD' == strtoupper( substr( $line, 0, 14 ))) {
|
4150 |
+
$comp = new vtimezone( 'standard', $config );
|
4151 |
+
$subsync++;
|
4152 |
+
}
|
4153 |
+
elseif( 'BEGIN:DAYLIGHT' == strtoupper( substr( $line, 0, 14 ))) {
|
4154 |
+
$comp = new vtimezone( 'daylight', $config );
|
4155 |
+
$subsync++;
|
4156 |
+
}
|
4157 |
+
elseif( 'BEGIN:' == strtoupper( substr( $line, 0, 6 ))) // begin:<component>
|
4158 |
+
$compsync++;
|
4159 |
+
else
|
4160 |
+
$comp->unparsed[] = $line;
|
4161 |
+
}
|
4162 |
+
if( 0 < $subsync )
|
4163 |
+
$this->components[] = $comp->copy();
|
4164 |
+
unset( $config );
|
4165 |
+
/* concatenate property values spread over several lines */
|
4166 |
+
$lastix = -1;
|
4167 |
+
$propnames = array( 'action', 'attach', 'attendee', 'categories', 'comment', 'completed'
|
4168 |
+
, 'contact', 'class', 'created', 'description', 'dtend', 'dtstart'
|
4169 |
+
, 'dtstamp', 'due', 'duration', 'exdate', 'exrule', 'freebusy', 'geo'
|
4170 |
+
, 'last-modified', 'location', 'organizer', 'percent-complete'
|
4171 |
+
, 'priority', 'rdate', 'recurrence-id', 'related-to', 'repeat'
|
4172 |
+
, 'request-status', 'resources', 'rrule', 'sequence', 'status'
|
4173 |
+
, 'summary', 'transp', 'trigger', 'tzid', 'tzname', 'tzoffsetfrom'
|
4174 |
+
, 'tzoffsetto', 'tzurl', 'uid', 'url', 'x-' );
|
4175 |
+
$proprows = array();
|
4176 |
+
for( $i = 0; $i < count( $this->unparsed ); $i++ ) { // concatenate lines
|
4177 |
+
$line = rtrim( $this->unparsed[$i], $nl );
|
4178 |
+
while( isset( $this->unparsed[$i+1] ) && !empty( $this->unparsed[$i+1] ) && ( ' ' == $this->unparsed[$i+1]{0} ))
|
4179 |
+
$line .= rtrim( substr( $this->unparsed[++$i], 1 ), $nl );
|
4180 |
+
$proprows[] = $line;
|
4181 |
+
}
|
4182 |
+
/* parse each property 'line' */
|
4183 |
+
foreach( $proprows as $line ) {
|
4184 |
+
if( '\n' == substr( $line, -2 ))
|
4185 |
+
$line = substr( $line, 0, -2 );
|
4186 |
+
/* get propname */
|
4187 |
+
$propname = null;
|
4188 |
+
$cix = 0;
|
4189 |
+
while( isset( $line[$cix] )) {
|
4190 |
+
if( in_array( $line[$cix], array( ':', ';' )))
|
4191 |
+
break;
|
4192 |
+
else
|
4193 |
+
$propname .= $line[$cix];
|
4194 |
+
$cix++;
|
4195 |
+
}
|
4196 |
+
if(( 'x-' == substr( $propname, 0, 2 )) || ( 'X-' == substr( $propname, 0, 2 ))) {
|
4197 |
+
$propname2 = $propname;
|
4198 |
+
$propname = 'X-';
|
4199 |
+
}
|
4200 |
+
if( !in_array( strtolower( $propname ), $propnames )) // skip non standard property names
|
4201 |
+
continue;
|
4202 |
+
/* rest of the line is opt.params and value */
|
4203 |
+
$line = substr( $line, $cix );
|
4204 |
+
/* separate attributes from value */
|
4205 |
+
iCalUtilityFunctions::_splitContent( $line, $propAttr );
|
4206 |
+
/* call setProperty( $propname.. . */
|
4207 |
+
switch( strtoupper( $propname )) {
|
4208 |
+
case 'ATTENDEE':
|
4209 |
+
foreach( $propAttr as $pix => $attr ) {
|
4210 |
+
if( !in_array( strtoupper( $pix ), array( 'MEMBER', 'DELEGATED-TO', 'DELEGATED-FROM' )))
|
4211 |
+
continue;
|
4212 |
+
$attr2 = explode( ',', $attr );
|
4213 |
+
if( 1 < count( $attr2 ))
|
4214 |
+
$propAttr[$pix] = $attr2;
|
4215 |
+
}
|
4216 |
+
$this->setProperty( $propname, $line, $propAttr );
|
4217 |
+
break;
|
4218 |
+
case 'CATEGORIES':
|
4219 |
+
case 'RESOURCES':
|
4220 |
+
if( FALSE !== strpos( $line, ',' )) {
|
4221 |
+
$content = array( 0 => '' );
|
4222 |
+
$cix = $lix = 0;
|
4223 |
+
while( FALSE !== substr( $line, $lix, 1 )) {
|
4224 |
+
if(( ',' == $line[$lix] ) && ( "\\" != $line[( $lix - 1 )])) {
|
4225 |
+
$cix++;
|
4226 |
+
$content[$cix] = '';
|
4227 |
+
}
|
4228 |
+
else
|
4229 |
+
$content[$cix] .= $line[$lix];
|
4230 |
+
$lix++;
|
4231 |
+
}
|
4232 |
+
if( 1 < count( $content )) {
|
4233 |
+
$content = array_values( $content );
|
4234 |
+
foreach( $content as $cix => $contentPart )
|
4235 |
+
$content[$cix] = iCalUtilityFunctions::_strunrep( $contentPart );
|
4236 |
+
$this->setProperty( $propname, $content, $propAttr );
|
4237 |
+
break;
|
4238 |
+
}
|
4239 |
+
else
|
4240 |
+
$line = reset( $content );
|
4241 |
+
}
|
4242 |
+
case 'COMMENT':
|
4243 |
+
case 'CONTACT':
|
4244 |
+
case 'DESCRIPTION':
|
4245 |
+
case 'LOCATION':
|
4246 |
+
case 'SUMMARY':
|
4247 |
+
if( empty( $line ))
|
4248 |
+
$propAttr = null;
|
4249 |
+
$this->setProperty( $propname, iCalUtilityFunctions::_strunrep( $line ), $propAttr );
|
4250 |
+
break;
|
4251 |
+
case 'REQUEST-STATUS':
|
4252 |
+
$values = explode( ';', $line, 3 );
|
4253 |
+
$values[1] = ( !isset( $values[1] )) ? null : iCalUtilityFunctions::_strunrep( $values[1] );
|
4254 |
+
$values[2] = ( !isset( $values[2] )) ? null : iCalUtilityFunctions::_strunrep( $values[2] );
|
4255 |
+
$this->setProperty( $propname
|
4256 |
+
, $values[0] // statcode
|
4257 |
+
, $values[1] // statdesc
|
4258 |
+
, $values[2] // extdata
|
4259 |
+
, $propAttr );
|
4260 |
+
break;
|
4261 |
+
case 'FREEBUSY':
|
4262 |
+
$fbtype = ( isset( $propAttr['FBTYPE'] )) ? $propAttr['FBTYPE'] : ''; // force setting default, if missing
|
4263 |
+
unset( $propAttr['FBTYPE'] );
|
4264 |
+
$values = explode( ',', $line );
|
4265 |
+
foreach( $values as $vix => $value ) {
|
4266 |
+
$value2 = explode( '/', $value );
|
4267 |
+
if( 1 < count( $value2 ))
|
4268 |
+
$values[$vix] = $value2;
|
4269 |
+
}
|
4270 |
+
$this->setProperty( $propname, $fbtype, $values, $propAttr );
|
4271 |
+
break;
|
4272 |
+
case 'GEO':
|
4273 |
+
$value = explode( ';', $line, 2 );
|
4274 |
+
if( 2 > count( $value ))
|
4275 |
+
$value[1] = null;
|
4276 |
+
$this->setProperty( $propname, $value[0], $value[1], $propAttr );
|
4277 |
+
break;
|
4278 |
+
case 'EXDATE':
|
4279 |
+
$values = ( !empty( $line )) ? explode( ',', $line ) : null;
|
4280 |
+
$this->setProperty( $propname, $values, $propAttr );
|
4281 |
+
break;
|
4282 |
+
case 'RDATE':
|
4283 |
+
if( empty( $line )) {
|
4284 |
+
$this->setProperty( $propname, $line, $propAttr );
|
4285 |
+
break;
|
4286 |
+
}
|
4287 |
+
$values = explode( ',', $line );
|
4288 |
+
foreach( $values as $vix => $value ) {
|
4289 |
+
$value2 = explode( '/', $value );
|
4290 |
+
if( 1 < count( $value2 ))
|
4291 |
+
$values[$vix] = $value2;
|
4292 |
+
}
|
4293 |
+
$this->setProperty( $propname, $values, $propAttr );
|
4294 |
+
break;
|
4295 |
+
case 'EXRULE':
|
4296 |
+
case 'RRULE':
|
4297 |
+
$values = explode( ';', $line );
|
4298 |
+
$recur = array();
|
4299 |
+
foreach( $values as $value2 ) {
|
4300 |
+
if( empty( $value2 ))
|
4301 |
+
continue; // ;-char in ending position ???
|
4302 |
+
$value3 = explode( '=', $value2, 2 );
|
4303 |
+
$rulelabel = strtoupper( $value3[0] );
|
4304 |
+
switch( $rulelabel ) {
|
4305 |
+
case 'BYDAY': {
|
4306 |
+
$value4 = explode( ',', $value3[1] );
|
4307 |
+
if( 1 < count( $value4 )) {
|
4308 |
+
foreach( $value4 as $v5ix => $value5 ) {
|
4309 |
+
$value6 = array();
|
4310 |
+
$dayno = $dayname = null;
|
4311 |
+
$value5 = trim( (string) $value5 );
|
4312 |
+
if(( ctype_alpha( substr( $value5, -1 ))) &&
|
4313 |
+
( ctype_alpha( substr( $value5, -2, 1 )))) {
|
4314 |
+
$dayname = substr( $value5, -2, 2 );
|
4315 |
+
if( 2 < strlen( $value5 ))
|
4316 |
+
$dayno = substr( $value5, 0, ( strlen( $value5 ) - 2 ));
|
4317 |
+
}
|
4318 |
+
if( $dayno )
|
4319 |
+
$value6[] = $dayno;
|
4320 |
+
if( $dayname )
|
4321 |
+
$value6['DAY'] = $dayname;
|
4322 |
+
$value4[$v5ix] = $value6;
|
4323 |
+
}
|
4324 |
+
}
|
4325 |
+
else {
|
4326 |
+
$value4 = array();
|
4327 |
+
$dayno = $dayname = null;
|
4328 |
+
$value5 = trim( (string) $value3[1] );
|
4329 |
+
if(( ctype_alpha( substr( $value5, -1 ))) &&
|
4330 |
+
( ctype_alpha( substr( $value5, -2, 1 )))) {
|
4331 |
+
$dayname = substr( $value5, -2, 2 );
|
4332 |
+
if( 2 < strlen( $value5 ))
|
4333 |
+
$dayno = substr( $value5, 0, ( strlen( $value5 ) - 2 ));
|
4334 |
+
}
|
4335 |
+
if( $dayno )
|
4336 |
+
$value4[] = $dayno;
|
4337 |
+
if( $dayname )
|
4338 |
+
$value4['DAY'] = $dayname;
|
4339 |
+
}
|
4340 |
+
$recur[$rulelabel] = $value4;
|
4341 |
+
break;
|
4342 |
+
}
|
4343 |
+
default: {
|
4344 |
+
$value4 = explode( ',', $value3[1] );
|
4345 |
+
if( 1 < count( $value4 ))
|
4346 |
+
$value3[1] = $value4;
|
4347 |
+
$recur[$rulelabel] = $value3[1];
|
4348 |
+
break;
|
4349 |
+
}
|
4350 |
+
} // end - switch $rulelabel
|
4351 |
+
} // end - foreach( $values.. .
|
4352 |
+
$this->setProperty( $propname, $recur, $propAttr );
|
4353 |
+
break;
|
4354 |
+
case 'X-':
|
4355 |
+
$propname = ( isset( $propname2 )) ? $propname2 : $propname;
|
4356 |
+
unset( $propname2 );
|
4357 |
+
case 'ACTION':
|
4358 |
+
case 'CLASSIFICATION':
|
4359 |
+
case 'STATUS':
|
4360 |
+
case 'TRANSP':
|
4361 |
+
case 'UID':
|
4362 |
+
case 'TZID':
|
4363 |
+
case 'RELATED-TO':
|
4364 |
+
case 'TZNAME':
|
4365 |
+
$line = iCalUtilityFunctions::_strunrep( $line );
|
4366 |
+
default:
|
4367 |
+
$this->setProperty( $propname, $line, $propAttr );
|
4368 |
+
break;
|
4369 |
+
} // end switch( $propname.. .
|
4370 |
+
} // end - foreach( $proprows.. .
|
4371 |
+
unset( $unparsedtext, $this->unparsed, $proprows );
|
4372 |
+
if( isset( $this->components ) && is_array( $this->components ) && ( 0 < count( $this->components ))) {
|
4373 |
+
$ckeys = array_keys( $this->components );
|
4374 |
+
foreach( $ckeys as $ckey ) {
|
4375 |
+
if( !empty( $this->components[$ckey] ) && !empty( $this->components[$ckey]->unparsed )) {
|
4376 |
+
$this->components[$ckey]->parse();
|
4377 |
+
}
|
4378 |
+
}
|
4379 |
+
}
|
4380 |
+
return TRUE;
|
4381 |
+
}
|
4382 |
+
/*********************************************************************************/
|
4383 |
+
/*********************************************************************************/
|
4384 |
+
/**
|
4385 |
+
* return a copy of this component
|
4386 |
+
*
|
4387 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4388 |
+
* @since 2.15.4 - 2012-10-18
|
4389 |
+
* @return object
|
4390 |
+
*/
|
4391 |
+
function copy() {
|
4392 |
+
return unserialize( serialize( $this ));
|
4393 |
+
}
|
4394 |
+
/*********************************************************************************/
|
4395 |
+
/*********************************************************************************/
|
4396 |
+
/**
|
4397 |
+
* delete calendar subcomponent from component container
|
4398 |
+
*
|
4399 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4400 |
+
* @since 2.8.8 - 2011-03-15
|
4401 |
+
* @param mixed $arg1 ordno / component type / component uid
|
4402 |
+
* @param mixed $arg2 ordno if arg1 = component type
|
4403 |
+
* @uses calendarComponent::$components
|
4404 |
+
* @uses calendarComponent::$objName
|
4405 |
+
* @uses calendarComponent::getProperty()
|
4406 |
+
* @return void
|
4407 |
+
*/
|
4408 |
+
function deleteComponent( $arg1, $arg2=FALSE ) {
|
4409 |
+
if( !isset( $this->components )) return FALSE;
|
4410 |
+
$argType = $index = null;
|
4411 |
+
if ( ctype_digit( (string) $arg1 )) {
|
4412 |
+
$argType = 'INDEX';
|
4413 |
+
$index = (int) $arg1 - 1;
|
4414 |
+
}
|
4415 |
+
elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
|
4416 |
+
$argType = strtolower( $arg1 );
|
4417 |
+
$index = ( !empty( $arg2 ) && ctype_digit( (string) $arg2 )) ? (( int ) $arg2 - 1 ) : 0;
|
4418 |
+
}
|
4419 |
+
$cix2dC = 0;
|
4420 |
+
foreach ( $this->components as $cix => $component) {
|
4421 |
+
if( empty( $component )) continue;
|
4422 |
+
if(( 'INDEX' == $argType ) && ( $index == $cix )) {
|
4423 |
+
unset( $this->components[$cix] );
|
4424 |
+
return TRUE;
|
4425 |
+
}
|
4426 |
+
elseif( $argType == $component->objName ) {
|
4427 |
+
if( $index == $cix2dC ) {
|
4428 |
+
unset( $this->components[$cix] );
|
4429 |
+
return TRUE;
|
4430 |
+
}
|
4431 |
+
$cix2dC++;
|
4432 |
+
}
|
4433 |
+
elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
|
4434 |
+
unset( $this->components[$cix] );
|
4435 |
+
return TRUE;
|
4436 |
+
}
|
4437 |
+
}
|
4438 |
+
return FALSE;
|
4439 |
+
}
|
4440 |
+
/**
|
4441 |
+
* get calendar component subcomponent from component container
|
4442 |
+
*
|
4443 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4444 |
+
* @since 2.8.8 - 2011-03-15
|
4445 |
+
* @param mixed $arg1 ordno/component type/ component uid
|
4446 |
+
* @param mixed $arg2 ordno if arg1 = component type
|
4447 |
+
* @uses calendarComponent::$components
|
4448 |
+
* @uses calendarComponent::$compix
|
4449 |
+
* @uses calendarComponent::$objName
|
4450 |
+
* @uses calendarComponent::copy()
|
4451 |
+
* @uses calendarComponent::getProperty()
|
4452 |
+
* @return object
|
4453 |
+
*/
|
4454 |
+
function getComponent ( $arg1=FALSE, $arg2=FALSE ) {
|
4455 |
+
if( !isset( $this->components )) return FALSE;
|
4456 |
+
$index = $argType = null;
|
4457 |
+
if ( !$arg1 ) {
|
4458 |
+
$argType = 'INDEX';
|
4459 |
+
$index = $this->compix['INDEX'] =
|
4460 |
+
( isset( $this->compix['INDEX'] )) ? $this->compix['INDEX'] + 1 : 1;
|
4461 |
+
}
|
4462 |
+
elseif ( ctype_digit( (string) $arg1 )) {
|
4463 |
+
$argType = 'INDEX';
|
4464 |
+
$index = (int) $arg1;
|
4465 |
+
unset( $this->compix );
|
4466 |
+
}
|
4467 |
+
elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
|
4468 |
+
unset( $this->compix['INDEX'] );
|
4469 |
+
$argType = strtolower( $arg1 );
|
4470 |
+
if( !$arg2 )
|
4471 |
+
$index = $this->compix[$argType] = ( isset( $this->compix[$argType] )) ? $this->compix[$argType] + 1 : 1;
|
4472 |
+
else
|
4473 |
+
$index = (int) $arg2;
|
4474 |
+
}
|
4475 |
+
$index -= 1;
|
4476 |
+
$ckeys = array_keys( $this->components );
|
4477 |
+
if( !empty( $index) && ( $index > end( $ckeys )))
|
4478 |
+
return FALSE;
|
4479 |
+
$cix2gC = 0;
|
4480 |
+
foreach( $this->components as $cix => $component ) {
|
4481 |
+
if( empty( $component )) continue;
|
4482 |
+
if(( 'INDEX' == $argType ) && ( $index == $cix ))
|
4483 |
+
return $component->copy();
|
4484 |
+
elseif( $argType == $component->objName ) {
|
4485 |
+
if( $index == $cix2gC )
|
4486 |
+
return $component->copy();
|
4487 |
+
$cix2gC++;
|
4488 |
+
}
|
4489 |
+
elseif( !$argType && ( $arg1 == $component->getProperty( 'uid' )))
|
4490 |
+
return $component->copy();
|
4491 |
+
}
|
4492 |
+
/* not found.. . */
|
4493 |
+
unset( $this->compix );
|
4494 |
+
return false;
|
4495 |
+
}
|
4496 |
+
/**
|
4497 |
+
* add calendar component as subcomponent to container for subcomponents
|
4498 |
+
*
|
4499 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4500 |
+
* @since 1.x.x - 2007-04-24
|
4501 |
+
* @param object $component calendar component
|
4502 |
+
* @uses calendarComponent::setComponent( $component )
|
4503 |
+
* @return void
|
4504 |
+
*/
|
4505 |
+
function addSubComponent ( $component ) {
|
4506 |
+
$this->setComponent( $component );
|
4507 |
+
}
|
4508 |
+
/**
|
4509 |
+
* create new calendar component subcomponent, already included within component
|
4510 |
+
*
|
4511 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4512 |
+
* @since 2.6.33 - 2011-01-03
|
4513 |
+
* @param string $compType subcomponent type
|
4514 |
+
* @uses calendarComponent::getConfig()
|
4515 |
+
* @uses calendarComponent::$components
|
4516 |
+
* @uses calendarComponent::calendarComponent()
|
4517 |
+
* @return object (reference)
|
4518 |
+
*/
|
4519 |
+
function & newComponent( $compType ) {
|
4520 |
+
$config = $this->getConfig();
|
4521 |
+
$keys = array_keys( $this->components );
|
4522 |
+
$ix = end( $keys) + 1;
|
4523 |
+
switch( strtoupper( $compType )) {
|
4524 |
+
case 'ALARM':
|
4525 |
+
case 'VALARM':
|
4526 |
+
$this->components[$ix] = new valarm( $config );
|
4527 |
+
break;
|
4528 |
+
case 'STANDARD':
|
4529 |
+
array_unshift( $this->components, new vtimezone( 'STANDARD', $config ));
|
4530 |
+
$ix = 0;
|
4531 |
+
break;
|
4532 |
+
case 'DAYLIGHT':
|
4533 |
+
$this->components[$ix] = new vtimezone( 'DAYLIGHT', $config );
|
4534 |
+
break;
|
4535 |
+
default:
|
4536 |
+
return FALSE;
|
4537 |
+
}
|
4538 |
+
return $this->components[$ix];
|
4539 |
+
}
|
4540 |
+
/**
|
4541 |
+
* add calendar component as subcomponent to container for subcomponents
|
4542 |
+
*
|
4543 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4544 |
+
* @since 2.21.11 - 2015-03-21
|
4545 |
+
* @param object $component calendar component
|
4546 |
+
* @param mixed $arg1 ordno/component type/ component uid
|
4547 |
+
* @param mixed $arg2 ordno if arg1 = component type
|
4548 |
+
* @uses calendarComponent::$components
|
4549 |
+
* @uses calendarComponent::setConfig()
|
4550 |
+
* @uses calendarComponent::getConfig()
|
4551 |
+
* @uses calendarComponent::$objName
|
4552 |
+
* @uses iCalUtilityFunctions::$miscComps
|
4553 |
+
* @uses calendarComponent::getProperty()
|
4554 |
+
* @uses calendarComponent::copy()
|
4555 |
+
* @uses iCalUtilityFunctions::$mComps
|
4556 |
+
* @return bool
|
4557 |
+
*/
|
4558 |
+
function setComponent( $component, $arg1=FALSE, $arg2=FALSE ) {
|
4559 |
+
if( !isset( $this->components )) return FALSE;
|
4560 |
+
$component->setConfig( $this->getConfig(), FALSE, TRUE );
|
4561 |
+
if( ! in_array( $component->objName, iCalUtilityFunctions::$miscComps )) {
|
4562 |
+
/* make sure dtstamp and uid is set */
|
4563 |
+
$dummy = $component->getProperty( 'dtstamp' );
|
4564 |
+
$dummy = $component->getProperty( 'uid' );
|
4565 |
+
}
|
4566 |
+
if( !$arg1 ) { // plain insert, last in chain
|
4567 |
+
$this->components[] = $component->copy();
|
4568 |
+
return TRUE;
|
4569 |
+
}
|
4570 |
+
$argType = $index = null;
|
4571 |
+
if ( ctype_digit( (string) $arg1 )) { // index insert/replace
|
4572 |
+
$argType = 'INDEX';
|
4573 |
+
$index = (int) $arg1 - 1;
|
4574 |
+
}
|
4575 |
+
elseif( in_array( strtolower( $arg1 ), iCalUtilityFunctions::$mComps )) {
|
4576 |
+
$argType = strtolower( $arg1 );
|
4577 |
+
$index = ( ctype_digit( (string) $arg2 )) ? ((int) $arg2) - 1 : 0;
|
4578 |
+
}
|
4579 |
+
// else if arg1 is set, arg1 must be an UID
|
4580 |
+
$cix2sC = 0;
|
4581 |
+
foreach ( $this->components as $cix => $component2 ) {
|
4582 |
+
if( empty( $component2 )) continue;
|
4583 |
+
if(( 'INDEX' == $argType ) && ( $index == $cix )) { // index insert/replace
|
4584 |
+
$this->components[$cix] = $component->copy();
|
4585 |
+
return TRUE;
|
4586 |
+
}
|
4587 |
+
elseif( $argType == $component2->objName ) { // component Type index insert/replace
|
4588 |
+
if( $index == $cix2sC ) {
|
4589 |
+
$this->components[$cix] = $component->copy();
|
4590 |
+
return TRUE;
|
4591 |
+
}
|
4592 |
+
$cix2sC++;
|
4593 |
+
}
|
4594 |
+
elseif( !$argType && ( $arg1 == $component2->getProperty( 'uid' ))) { // UID insert/replace
|
4595 |
+
$this->components[$cix] = $component->copy();
|
4596 |
+
return TRUE;
|
4597 |
+
}
|
4598 |
+
}
|
4599 |
+
/* arg1=index and not found.. . insert at index .. .*/
|
4600 |
+
if( 'INDEX' == $argType ) {
|
4601 |
+
$this->components[$index] = $component->copy();
|
4602 |
+
ksort( $this->components, SORT_NUMERIC );
|
4603 |
+
}
|
4604 |
+
else /* not found.. . insert last in chain anyway .. .*/
|
4605 |
+
$this->components[] = $component->copy();
|
4606 |
+
return TRUE;
|
4607 |
+
}
|
4608 |
+
/**
|
4609 |
+
* creates formatted output for subcomponents
|
4610 |
+
*
|
4611 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
4612 |
+
* @since 2.21.11 - 2015-03-10
|
4613 |
+
* @param array $xcaldecl
|
4614 |
+
* @uses calendarComponent::$objName
|
4615 |
+
* @uses calendarComponent::$components
|
4616 |
+
* @uses calendarComponent::getProperty()
|
4617 |
+
* @uses iCalUtilityFunctions::$fmt
|
4618 |
+
* @uses calendarComponent::copy()
|
4619 |
+
* @uses calendarComponent::setConfig()
|
4620 |
+
* @uses calendarComponent::getConfig()
|
4621 |
+
* @uses calendarComponent::createComponent()
|
4622 |
+
* @uses calendarComponent::$xcaldecl()
|
4623 |
+
* @return string
|
4624 |
+
*/
|
4625 |
+
function createSubComponent() {
|
4626 |
+
$output = null;
|
4627 |
+
if( 'vtimezone' == $this->objName ) { // sort subComponents, first standard, then daylight, in dtstart order
|
4628 |
+
$stdarr = $dlarr = array();
|
4629 |
+
foreach( $this->components as $component ) {
|
4630 |
+
if( empty( $component ))
|
4631 |
+
continue;
|
4632 |
+
$dt = $component->getProperty( 'dtstart' );
|
4633 |
+
$key = (int) sprintf( iCalUtilityFunctions::$fmt['dateKey'], (int) $dt['year'], (int) $dt['month'], (int) $dt['day'], (int) $dt['hour'], (int) $dt['min'], (int) $dt['sec'] );
|
4634 |
+
if( 'standard' == $component->objName ) {
|
4635 |
+
while( isset( $stdarr[$key] ))
|
4636 |
+
$key += 1;
|
4637 |
+
$stdarr[$key] = $component->copy();
|
4638 |
+
}
|
4639 |
+
elseif( 'daylight' == $component->objName ) {
|
4640 |
+
while( isset( $dlarr[$key] ))
|
4641 |
+
$key += 1;
|
4642 |
+
$dlarr[$key] = $component->copy();
|
4643 |
+
}
|
4644 |
+
} // end foreach( $this->components as $component )
|
4645 |
+
$this->components = array();
|
4646 |
+
ksort( $stdarr, SORT_NUMERIC );
|
4647 |
+
foreach( $stdarr as $std )
|
4648 |
+
$this->components[] = $std->copy();
|
4649 |
+
unset( $stdarr );
|
4650 |
+
ksort( $dlarr, SORT_NUMERIC );
|
4651 |
+
foreach( $dlarr as $dl )
|
4652 |
+
$this->components[] = $dl->copy();
|
4653 |
+
unset( $dlarr );
|
4654 |
+
} // end if( 'vtimezone' == $this->objName )
|
4655 |
+
foreach( $this->components as $component ) {
|
4656 |
+
$component->setConfig( $this->getConfig(), FALSE, TRUE );
|
4657 |
+
$output .= $component->createComponent( $this->xcaldecl );
|
4658 |
+
}
|
4659 |
+
return $output;
|
4660 |
+
}
|
4661 |
+
}
|
includes/libs/iCal/lib/iCal.XML.inc.php
ADDED
@@ -0,0 +1,897 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/* iCalcreator XML (rfc6321) helper functions */
|
30 |
+
/*********************************************************************************/
|
31 |
+
/**
|
32 |
+
* format iCal XML output, rfc6321, using PHP SimpleXMLElement
|
33 |
+
*
|
34 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
35 |
+
* @since 2.18.1 - 2013-08-18
|
36 |
+
* @param object $calendar iCalcreator vcalendar instance reference
|
37 |
+
* @uses ICALCREATOR_VERSION
|
38 |
+
* @uses vcalendar::getProperty()
|
39 |
+
* @uses wpsbc__addXMLchild()
|
40 |
+
* @uses vcalendar::getConfig()
|
41 |
+
* @uses vcalendar::getComponent()
|
42 |
+
* @uses calendarComponent::$objName
|
43 |
+
* @uses calendarComponent::getProperty()
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
function wpsbc_iCal2XML( $calendar ) {
|
47 |
+
/** fix an SimpleXMLElement instance and create root element */
|
48 |
+
$xmlstr = '<?xml version="1.0" encoding="utf-8"?><icalendar xmlns="urn:ietf:params:xml:ns:icalendar-2.0">';
|
49 |
+
$xmlstr .= '<!-- created '.gmdate( 'Ymd\THis\Z' );
|
50 |
+
$xmlstr .= ' using kigkonsult.se '.ICALCREATOR_VERSION.' iCal2XMl (rfc6321) -->';
|
51 |
+
$xmlstr .= '</icalendar>';
|
52 |
+
$xml = new SimpleXMLElement( $xmlstr );
|
53 |
+
$vcalendar = $xml->addChild( 'vcalendar' );
|
54 |
+
/** fix calendar properties */
|
55 |
+
$properties = $vcalendar->addChild( 'properties' );
|
56 |
+
$calProps = array( 'version', 'prodid', 'calscale', 'method' );
|
57 |
+
foreach( $calProps as $calProp ) {
|
58 |
+
if( FALSE !== ( $content = $calendar->getProperty( $calProp )))
|
59 |
+
wpsbc__addXMLchild( $properties, $calProp, 'text', $content );
|
60 |
+
}
|
61 |
+
while( FALSE !== ( $content = $calendar->getProperty( FALSE, FALSE, TRUE )))
|
62 |
+
wpsbc__addXMLchild( $properties, $content[0], 'unknown', $content[1]['value'], $content[1]['params'] );
|
63 |
+
$langCal = $calendar->getConfig( 'language' );
|
64 |
+
/** prepare to fix components with properties */
|
65 |
+
$components = $vcalendar->addChild( 'components' );
|
66 |
+
/** fix component properties */
|
67 |
+
while( FALSE !== ( $component = $calendar->getComponent())) {
|
68 |
+
$compName = $component->objName;
|
69 |
+
$child = $components->addChild( $compName );
|
70 |
+
$properties = $child->addChild( 'properties' );
|
71 |
+
$langComp = $component->getConfig( 'language' );
|
72 |
+
$props = $component->getConfig( 'setPropertyNames' );
|
73 |
+
foreach( $props as $prop ) {
|
74 |
+
switch( strtolower( $prop )) {
|
75 |
+
case 'attach': // may occur multiple times, below
|
76 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
77 |
+
$type = ( isset( $content['params']['VALUE'] ) && ( 'BINARY' == $content['params']['VALUE'] )) ? 'binary' : 'uri';
|
78 |
+
unset( $content['params']['VALUE'] );
|
79 |
+
wpsbc__addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
|
80 |
+
}
|
81 |
+
break;
|
82 |
+
case 'attendee':
|
83 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
84 |
+
if( isset( $content['params']['CN'] ) && !isset( $content['params']['LANGUAGE'] )) {
|
85 |
+
if( $langComp )
|
86 |
+
$content['params']['LANGUAGE'] = $langComp;
|
87 |
+
elseif( $langCal )
|
88 |
+
$content['params']['LANGUAGE'] = $langCal;
|
89 |
+
}
|
90 |
+
wpsbc__addXMLchild( $properties, $prop, 'cal-address', $content['value'], $content['params'] );
|
91 |
+
}
|
92 |
+
break;
|
93 |
+
case 'exdate':
|
94 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
95 |
+
$type = ( isset( $content['params']['VALUE'] ) && ( 'DATE' == $content['params']['VALUE'] )) ? 'date' : 'date-time';
|
96 |
+
unset( $content['params']['VALUE'] );
|
97 |
+
wpsbc__addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
|
98 |
+
}
|
99 |
+
break;
|
100 |
+
case 'freebusy':
|
101 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
102 |
+
if( is_array( $content ) && isset( $content['value']['fbtype'] )) {
|
103 |
+
$content['params']['FBTYPE'] = $content['value']['fbtype'];
|
104 |
+
unset( $content['value']['fbtype'] );
|
105 |
+
}
|
106 |
+
wpsbc__addXMLchild( $properties, $prop, 'period', $content['value'], $content['params'] );
|
107 |
+
}
|
108 |
+
break;
|
109 |
+
case 'request-status':
|
110 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
111 |
+
if( !isset( $content['params']['LANGUAGE'] )) {
|
112 |
+
if( $langComp )
|
113 |
+
$content['params']['LANGUAGE'] = $langComp;
|
114 |
+
elseif( $langCal )
|
115 |
+
$content['params']['LANGUAGE'] = $langCal;
|
116 |
+
}
|
117 |
+
wpsbc__addXMLchild( $properties, $prop, 'rstatus', $content['value'], $content['params'] );
|
118 |
+
}
|
119 |
+
break;
|
120 |
+
case 'rdate':
|
121 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
122 |
+
$type = 'date-time';
|
123 |
+
if( isset( $content['params']['VALUE'] )) {
|
124 |
+
if( 'DATE' == $content['params']['VALUE'] )
|
125 |
+
$type = 'date';
|
126 |
+
elseif( 'PERIOD' == $content['params']['VALUE'] )
|
127 |
+
$type = 'period';
|
128 |
+
}
|
129 |
+
unset( $content['params']['VALUE'] );
|
130 |
+
wpsbc__addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
|
131 |
+
}
|
132 |
+
break;
|
133 |
+
case 'categories':
|
134 |
+
case 'comment':
|
135 |
+
case 'contact':
|
136 |
+
case 'description':
|
137 |
+
case 'related-to':
|
138 |
+
case 'resources':
|
139 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
140 |
+
if(( 'related-to' != $prop ) && !isset( $content['params']['LANGUAGE'] )) {
|
141 |
+
if( $langComp )
|
142 |
+
$content['params']['LANGUAGE'] = $langComp;
|
143 |
+
elseif( $langCal )
|
144 |
+
$content['params']['LANGUAGE'] = $langCal;
|
145 |
+
}
|
146 |
+
wpsbc__addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
|
147 |
+
}
|
148 |
+
break;
|
149 |
+
case 'x-prop':
|
150 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
|
151 |
+
wpsbc__addXMLchild( $properties, $content[0], 'unknown', $content[1]['value'], $content[1]['params'] );
|
152 |
+
break;
|
153 |
+
case 'created': // single occurence below, if set
|
154 |
+
case 'completed':
|
155 |
+
case 'dtstamp':
|
156 |
+
case 'last-modified':
|
157 |
+
$utcDate = TRUE;
|
158 |
+
case 'dtstart':
|
159 |
+
case 'dtend':
|
160 |
+
case 'due':
|
161 |
+
case 'recurrence-id':
|
162 |
+
if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
163 |
+
$type = ( isset( $content['params']['VALUE'] ) && ( 'DATE' == $content['params']['VALUE'] )) ? 'date' : 'date-time';
|
164 |
+
unset( $content['params']['VALUE'] );
|
165 |
+
if(( isset( $content['params']['TZID'] ) && empty( $content['params']['TZID'] )) || @is_null( $content['params']['TZID'] ))
|
166 |
+
unset( $content['params']['TZID'] );
|
167 |
+
wpsbc__addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
|
168 |
+
}
|
169 |
+
unset( $utcDate );
|
170 |
+
break;
|
171 |
+
case 'duration':
|
172 |
+
if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
|
173 |
+
wpsbc__addXMLchild( $properties, $prop, 'duration', $content['value'], $content['params'] );
|
174 |
+
break;
|
175 |
+
case 'exrule':
|
176 |
+
case 'rrule':
|
177 |
+
while( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
|
178 |
+
wpsbc__addXMLchild( $properties, $prop, 'recur', $content['value'], $content['params'] );
|
179 |
+
break;
|
180 |
+
case 'class':
|
181 |
+
case 'location':
|
182 |
+
case 'status':
|
183 |
+
case 'summary':
|
184 |
+
case 'transp':
|
185 |
+
case 'tzid':
|
186 |
+
case 'uid':
|
187 |
+
if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
188 |
+
if((( 'location' == $prop ) || ( 'summary' == $prop )) && !isset( $content['params']['LANGUAGE'] )) {
|
189 |
+
if( $langComp )
|
190 |
+
$content['params']['LANGUAGE'] = $langComp;
|
191 |
+
elseif( $langCal )
|
192 |
+
$content['params']['LANGUAGE'] = $langCal;
|
193 |
+
}
|
194 |
+
wpsbc__addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
|
195 |
+
}
|
196 |
+
break;
|
197 |
+
case 'geo':
|
198 |
+
if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
|
199 |
+
wpsbc__addXMLchild( $properties, $prop, 'geo', $content['value'], $content['params'] );
|
200 |
+
break;
|
201 |
+
case 'organizer':
|
202 |
+
if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE ))) {
|
203 |
+
if( isset( $content['params']['CN'] ) && !isset( $content['params']['LANGUAGE'] )) {
|
204 |
+
if( $langComp )
|
205 |
+
$content['params']['LANGUAGE'] = $langComp;
|
206 |
+
elseif( $langCal )
|
207 |
+
$content['params']['LANGUAGE'] = $langCal;
|
208 |
+
}
|
209 |
+
wpsbc__addXMLchild( $properties, $prop, 'cal-address', $content['value'], $content['params'] );
|
210 |
+
}
|
211 |
+
break;
|
212 |
+
case 'percent-complete':
|
213 |
+
case 'priority':
|
214 |
+
case 'sequence':
|
215 |
+
if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
|
216 |
+
wpsbc__addXMLchild( $properties, $prop, 'integer', $content['value'], $content['params'] );
|
217 |
+
break;
|
218 |
+
case 'tzurl':
|
219 |
+
case 'url':
|
220 |
+
if( FALSE !== ( $content = $component->getProperty( $prop, FALSE, TRUE )))
|
221 |
+
wpsbc__addXMLchild( $properties, $prop, 'uri', $content['value'], $content['params'] );
|
222 |
+
break;
|
223 |
+
} // end switch( $prop )
|
224 |
+
} // end foreach( $props as $prop )
|
225 |
+
/** fix subComponent properties, if any */
|
226 |
+
while( FALSE !== ( $subcomp = $component->getComponent())) {
|
227 |
+
$subCompName = $subcomp->objName;
|
228 |
+
$child2 = $child->addChild( $subCompName );
|
229 |
+
$properties = $child2->addChild( 'properties' );
|
230 |
+
$langComp = $subcomp->getConfig( 'language' );
|
231 |
+
$subCompProps = $subcomp->getConfig( 'setPropertyNames' );
|
232 |
+
foreach( $subCompProps as $prop ) {
|
233 |
+
switch( strtolower( $prop )) {
|
234 |
+
case 'attach': // may occur multiple times, below
|
235 |
+
while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
|
236 |
+
$type = ( isset( $content['params']['VALUE'] ) && ( 'BINARY' == $content['params']['VALUE'] )) ? 'binary' : 'uri';
|
237 |
+
unset( $content['params']['VALUE'] );
|
238 |
+
wpsbc__addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
|
239 |
+
}
|
240 |
+
break;
|
241 |
+
case 'attendee':
|
242 |
+
while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
|
243 |
+
if( isset( $content['params']['CN'] ) && !isset( $content['params']['LANGUAGE'] )) {
|
244 |
+
if( $langComp )
|
245 |
+
$content['params']['LANGUAGE'] = $langComp;
|
246 |
+
elseif( $langCal )
|
247 |
+
$content['params']['LANGUAGE'] = $langCal;
|
248 |
+
}
|
249 |
+
wpsbc__addXMLchild( $properties, $prop, 'cal-address', $content['value'], $content['params'] );
|
250 |
+
}
|
251 |
+
break;
|
252 |
+
case 'comment':
|
253 |
+
case 'tzname':
|
254 |
+
while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
|
255 |
+
if( !isset( $content['params']['LANGUAGE'] )) {
|
256 |
+
if( $langComp )
|
257 |
+
$content['params']['LANGUAGE'] = $langComp;
|
258 |
+
elseif( $langCal )
|
259 |
+
$content['params']['LANGUAGE'] = $langCal;
|
260 |
+
}
|
261 |
+
wpsbc__addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
|
262 |
+
}
|
263 |
+
break;
|
264 |
+
case 'rdate':
|
265 |
+
while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
|
266 |
+
$type = 'date-time';
|
267 |
+
if( isset( $content['params']['VALUE'] )) {
|
268 |
+
if( 'DATE' == $content['params']['VALUE'] )
|
269 |
+
$type = 'date';
|
270 |
+
elseif( 'PERIOD' == $content['params']['VALUE'] )
|
271 |
+
$type = 'period';
|
272 |
+
}
|
273 |
+
unset( $content['params']['VALUE'] );
|
274 |
+
wpsbc__addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
|
275 |
+
}
|
276 |
+
break;
|
277 |
+
case 'x-prop':
|
278 |
+
while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
|
279 |
+
wpsbc__addXMLchild( $properties, $content[0], 'unknown', $content[1]['value'], $content[1]['params'] );
|
280 |
+
break;
|
281 |
+
case 'action': // single occurence below, if set
|
282 |
+
case 'description':
|
283 |
+
case 'summary':
|
284 |
+
if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
|
285 |
+
if(( 'action' != $prop ) && !isset( $content['params']['LANGUAGE'] )) {
|
286 |
+
if( $langComp )
|
287 |
+
$content['params']['LANGUAGE'] = $langComp;
|
288 |
+
elseif( $langCal )
|
289 |
+
$content['params']['LANGUAGE'] = $langCal;
|
290 |
+
}
|
291 |
+
wpsbc__addXMLchild( $properties, $prop, 'text', $content['value'], $content['params'] );
|
292 |
+
}
|
293 |
+
break;
|
294 |
+
case 'dtstart':
|
295 |
+
if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
|
296 |
+
unset( $content['value']['tz'], $content['params']['VALUE'] ); // always local time
|
297 |
+
wpsbc__addXMLchild( $properties, $prop, 'date-time', $content['value'], $content['params'] );
|
298 |
+
}
|
299 |
+
break;
|
300 |
+
case 'duration':
|
301 |
+
if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
|
302 |
+
wpsbc__addXMLchild( $properties, $prop, 'duration', $content['value'], $content['params'] );
|
303 |
+
break;
|
304 |
+
case 'repeat':
|
305 |
+
if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
|
306 |
+
wpsbc__addXMLchild( $properties, $prop, 'integer', $content['value'], $content['params'] );
|
307 |
+
break;
|
308 |
+
case 'trigger':
|
309 |
+
if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE ))) {
|
310 |
+
if( isset( $content['value']['year'] ) &&
|
311 |
+
isset( $content['value']['month'] ) &&
|
312 |
+
isset( $content['value']['day'] ))
|
313 |
+
$type = 'date-time';
|
314 |
+
else {
|
315 |
+
$type = 'duration';
|
316 |
+
if( !isset( $content['value']['relatedStart'] ) || ( TRUE !== $content['value']['relatedStart'] ))
|
317 |
+
$content['params']['RELATED'] = 'END';
|
318 |
+
}
|
319 |
+
wpsbc__addXMLchild( $properties, $prop, $type, $content['value'], $content['params'] );
|
320 |
+
}
|
321 |
+
break;
|
322 |
+
case 'tzoffsetto':
|
323 |
+
case 'tzoffsetfrom':
|
324 |
+
if( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
|
325 |
+
wpsbc__addXMLchild( $properties, $prop, 'utc-offset', $content['value'], $content['params'] );
|
326 |
+
break;
|
327 |
+
case 'rrule':
|
328 |
+
while( FALSE !== ( $content = $subcomp->getProperty( $prop, FALSE, TRUE )))
|
329 |
+
wpsbc__addXMLchild( $properties, $prop, 'recur', $content['value'], $content['params'] );
|
330 |
+
break;
|
331 |
+
} // switch( $prop )
|
332 |
+
} // end foreach( $subCompProps as $prop )
|
333 |
+
} // end while( FALSE !== ( $subcomp = $component->getComponent()))
|
334 |
+
} // end while( FALSE !== ( $component = $calendar->getComponent()))
|
335 |
+
return $xml->asXML();
|
336 |
+
}
|
337 |
+
/**
|
338 |
+
* Add children to a SimpleXMLelement
|
339 |
+
*
|
340 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
341 |
+
* @since 2.18.10 - 2013-09-04
|
342 |
+
* @param object $parent reference to a SimpleXMLelement node
|
343 |
+
* @param string $name new element node name
|
344 |
+
* @param string $type content type, subelement(-s) name
|
345 |
+
* @param string $content new subelement content
|
346 |
+
* @param array $params new element 'attributes'
|
347 |
+
* @uses iCalUtilityFunctions::_duration2str()
|
348 |
+
* @uses iCalUtilityFunctions::_geo2str2()
|
349 |
+
* @uses iCalUtilityFunctions::$geoLatFmt
|
350 |
+
* @uses iCalUtilityFunctions::$geoLongFmt
|
351 |
+
* @return void
|
352 |
+
*/
|
353 |
+
function wpsbc__addXMLchild( & $parent, $name, $type, $content, $params=array()) {
|
354 |
+
static $fmtYmd = '%04d-%02d-%02d';
|
355 |
+
static $fmtYmdHis = '%04d-%02d-%02dT%02d:%02d:%02d';
|
356 |
+
/** create new child node */
|
357 |
+
$name = strtolower( $name );
|
358 |
+
$child = $parent->addChild( $name );
|
359 |
+
if( !empty( $params )) {
|
360 |
+
$parameters = $child->addChild( 'parameters' );
|
361 |
+
foreach( $params as $param => $parVal ) {
|
362 |
+
if( 'VALUE' == $param )
|
363 |
+
continue;
|
364 |
+
$param = strtolower( $param );
|
365 |
+
if( 'x-' == substr( $param, 0, 2 )) {
|
366 |
+
$p1 = $parameters->addChild( $param );
|
367 |
+
$p2 = $p1->addChild( 'unknown', htmlspecialchars( $parVal ));
|
368 |
+
}
|
369 |
+
else {
|
370 |
+
$p1 = $parameters->addChild( $param );
|
371 |
+
switch( $param ) {
|
372 |
+
case 'altrep':
|
373 |
+
case 'dir': $ptype = 'uri'; break;
|
374 |
+
case 'delegated-from':
|
375 |
+
case 'delegated-to':
|
376 |
+
case 'member':
|
377 |
+
case 'sent-by': $ptype = 'cal-address'; break;
|
378 |
+
case 'rsvp': $ptype = 'boolean'; break ;
|
379 |
+
default: $ptype = 'text'; break;
|
380 |
+
}
|
381 |
+
if( is_array( $parVal )) {
|
382 |
+
foreach( $parVal as $pV )
|
383 |
+
$p2 = $p1->addChild( $ptype, htmlspecialchars( $pV ));
|
384 |
+
}
|
385 |
+
else
|
386 |
+
$p2 = $p1->addChild( $ptype, htmlspecialchars( $parVal ));
|
387 |
+
}
|
388 |
+
}
|
389 |
+
} // end if( !empty( $params ))
|
390 |
+
if(( empty( $content ) && ( '0' != $content )) || ( !is_array( $content) && ( '-' != substr( $content, 0, 1 ) && ( 0 > $content ))))
|
391 |
+
return;
|
392 |
+
/** store content */
|
393 |
+
switch( $type ) {
|
394 |
+
case 'binary':
|
395 |
+
$v = $child->addChild( $type, $content );
|
396 |
+
break;
|
397 |
+
case 'boolean':
|
398 |
+
break;
|
399 |
+
case 'cal-address':
|
400 |
+
$v = $child->addChild( $type, $content );
|
401 |
+
break;
|
402 |
+
case 'date':
|
403 |
+
if( array_key_exists( 'year', $content ))
|
404 |
+
$content = array( $content );
|
405 |
+
foreach( $content as $date ) {
|
406 |
+
$str = sprintf( $fmtYmd, (int) $date['year'], (int) $date['month'], (int) $date['day'] );
|
407 |
+
$v = $child->addChild( $type, $str );
|
408 |
+
}
|
409 |
+
break;
|
410 |
+
case 'date-time':
|
411 |
+
if( array_key_exists( 'year', $content ))
|
412 |
+
$content = array( $content );
|
413 |
+
foreach( $content as $dt ) {
|
414 |
+
if( !isset( $dt['hour'] )) $dt['hour'] = 0;
|
415 |
+
if( !isset( $dt['min'] )) $dt['min'] = 0;
|
416 |
+
if( !isset( $dt['sec'] )) $dt['sec'] = 0;
|
417 |
+
$str = sprintf( $fmtYmdHis, (int) $dt['year'], (int) $dt['month'], (int) $dt['day'], (int) $dt['hour'], (int) $dt['min'], (int) $dt['sec'] );
|
418 |
+
if( isset( $dt['tz'] ) && ( 'Z' == $dt['tz'] ))
|
419 |
+
$str .= 'Z';
|
420 |
+
$v = $child->addChild( $type, $str );
|
421 |
+
}
|
422 |
+
break;
|
423 |
+
case 'duration':
|
424 |
+
$output = (( 'trigger' == $name ) && ( FALSE !== $content['before'] )) ? '-' : '';
|
425 |
+
$v = $child->addChild( $type, $output.iCalUtilityFunctions::_duration2str( $content ) );
|
426 |
+
break;
|
427 |
+
case 'geo':
|
428 |
+
if( !empty( $content )) {
|
429 |
+
$v1 = $child->addChild( 'latitude', iCalUtilityFunctions::_geo2str2( $content['latitude'], iCalUtilityFunctions::$geoLatFmt ));
|
430 |
+
$v1 = $child->addChild( 'longitude', iCalUtilityFunctions::_geo2str2( $content['longitude'], iCalUtilityFunctions::$geoLongFmt ));
|
431 |
+
}
|
432 |
+
break;
|
433 |
+
case 'integer':
|
434 |
+
$v = $child->addChild( $type, (string) $content );
|
435 |
+
break;
|
436 |
+
case 'period':
|
437 |
+
if( !is_array( $content ))
|
438 |
+
break;
|
439 |
+
foreach( $content as $period ) {
|
440 |
+
$v1 = $child->addChild( $type );
|
441 |
+
$str = sprintf( $fmtYmdHis, (int) $period[0]['year'], (int) $period[0]['month'], (int) $period[0]['day'], (int) $period[0]['hour'], (int) $period[0]['min'], (int) $period[0]['sec'] );
|
442 |
+
if( isset( $period[0]['tz'] ) && ( 'Z' == $period[0]['tz'] ))
|
443 |
+
$str .= 'Z';
|
444 |
+
$v2 = $v1->addChild( 'start', $str );
|
445 |
+
if( array_key_exists( 'year', $period[1] )) {
|
446 |
+
$str = sprintf( $fmtYmdHis, (int) $period[1]['year'], (int) $period[1]['month'], (int) $period[1]['day'], (int) $period[1]['hour'], (int) $period[1]['min'], (int) $period[1]['sec'] );
|
447 |
+
if( isset($period[1]['tz'] ) && ( 'Z' == $period[1]['tz'] ))
|
448 |
+
$str .= 'Z';
|
449 |
+
$v2 = $v1->addChild( 'end', $str );
|
450 |
+
}
|
451 |
+
else
|
452 |
+
$v2 = $v1->addChild( 'duration', iCalUtilityFunctions::_duration2str( $period[1] ));
|
453 |
+
}
|
454 |
+
break;
|
455 |
+
case 'recur':
|
456 |
+
$content = array_change_key_case( $content );
|
457 |
+
foreach( $content as $rulelabel => $rulevalue ) {
|
458 |
+
switch( $rulelabel ) {
|
459 |
+
case 'until':
|
460 |
+
if( isset( $rulevalue['hour'] ))
|
461 |
+
$str = sprintf( $fmtYmdHis, (int) $rulevalue['year'], (int) $rulevalue['month'], (int) $rulevalue['day'], (int) $rulevalue['hour'], (int) $rulevalue['min'], (int) $rulevalue['sec'] ).'Z';
|
462 |
+
else
|
463 |
+
$str = sprintf( $fmtYmd, (int) $rulevalue['year'], (int) $rulevalue['month'], (int) $rulevalue['day'] );
|
464 |
+
$v = $child->addChild( $rulelabel, $str );
|
465 |
+
break;
|
466 |
+
case 'bysecond':
|
467 |
+
case 'byminute':
|
468 |
+
case 'byhour':
|
469 |
+
case 'bymonthday':
|
470 |
+
case 'byyearday':
|
471 |
+
case 'byweekno':
|
472 |
+
case 'bymonth':
|
473 |
+
case 'bysetpos': {
|
474 |
+
if( is_array( $rulevalue )) {
|
475 |
+
foreach( $rulevalue as $vix => $valuePart )
|
476 |
+
$v = $child->addChild( $rulelabel, $valuePart );
|
477 |
+
}
|
478 |
+
else
|
479 |
+
$v = $child->addChild( $rulelabel, $rulevalue );
|
480 |
+
break;
|
481 |
+
}
|
482 |
+
case 'byday': {
|
483 |
+
if( isset( $rulevalue['DAY'] )) {
|
484 |
+
$str = ( isset( $rulevalue[0] )) ? $rulevalue[0] : '';
|
485 |
+
$str .= $rulevalue['DAY'];
|
486 |
+
$p = $child->addChild( $rulelabel, $str );
|
487 |
+
}
|
488 |
+
else {
|
489 |
+
foreach( $rulevalue as $valuePart ) {
|
490 |
+
if( isset( $valuePart['DAY'] )) {
|
491 |
+
$str = ( isset( $valuePart[0] )) ? $valuePart[0] : '';
|
492 |
+
$str .= $valuePart['DAY'];
|
493 |
+
$p = $child->addChild( $rulelabel, $str );
|
494 |
+
}
|
495 |
+
else
|
496 |
+
$p = $child->addChild( $rulelabel, $valuePart );
|
497 |
+
}
|
498 |
+
}
|
499 |
+
break;
|
500 |
+
}
|
501 |
+
case 'freq':
|
502 |
+
case 'count':
|
503 |
+
case 'interval':
|
504 |
+
case 'wkst':
|
505 |
+
default:
|
506 |
+
$p = $child->addChild( $rulelabel, $rulevalue );
|
507 |
+
break;
|
508 |
+
} // end switch( $rulelabel )
|
509 |
+
} // end foreach( $content as $rulelabel => $rulevalue )
|
510 |
+
break;
|
511 |
+
case 'rstatus':
|
512 |
+
$v = $child->addChild( 'code', number_format( (float) $content['statcode'], 2, '.', ''));
|
513 |
+
$v = $child->addChild( 'description', htmlspecialchars( $content['text'] ));
|
514 |
+
if( isset( $content['extdata'] ))
|
515 |
+
$v = $child->addChild( 'data', htmlspecialchars( $content['extdata'] ));
|
516 |
+
break;
|
517 |
+
case 'text':
|
518 |
+
if( !is_array( $content ))
|
519 |
+
$content = array( $content );
|
520 |
+
foreach( $content as $part )
|
521 |
+
$v = $child->addChild( $type, htmlspecialchars( $part ));
|
522 |
+
break;
|
523 |
+
case 'time':
|
524 |
+
break;
|
525 |
+
case 'uri':
|
526 |
+
$v = $child->addChild( $type, $content );
|
527 |
+
break;
|
528 |
+
case 'utc-offset':
|
529 |
+
if( in_array( substr( $content, 0, 1 ), array( '-', '+' ))) {
|
530 |
+
$str = substr( $content, 0, 1 );
|
531 |
+
$content = substr( $content, 1 );
|
532 |
+
}
|
533 |
+
else
|
534 |
+
$str = '+';
|
535 |
+
$str .= substr( $content, 0, 2 ).':'.substr( $content, 2, 2 );
|
536 |
+
if( 4 < strlen( $content ))
|
537 |
+
$str .= ':'.substr( $content, 4 );
|
538 |
+
$v = $child->addChild( $type, $str );
|
539 |
+
break;
|
540 |
+
case 'unknown':
|
541 |
+
default:
|
542 |
+
if( is_array( $content ))
|
543 |
+
$content = implode( '', $content );
|
544 |
+
$v = $child->addChild( 'unknown', htmlspecialchars( $content ));
|
545 |
+
break;
|
546 |
+
}
|
547 |
+
}
|
548 |
+
/**
|
549 |
+
* parse xml file into iCalcreator instance
|
550 |
+
*
|
551 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
552 |
+
* @since 2.16.22 - 2013-06-18
|
553 |
+
* @param string $xmlfile
|
554 |
+
* @param array $iCalcfg iCalcreator config array (opt)
|
555 |
+
* @return mixediCalcreator instance or FALSE on error
|
556 |
+
*/
|
557 |
+
function wpsbc_XMLfile2iCal( $xmlfile, $iCalcfg=array()) {
|
558 |
+
if( FALSE === ( $xmlstr = file_get_contents( $xmlfile )))
|
559 |
+
return FALSE;
|
560 |
+
return wpsbc_xml2iCal( $xmlstr, $iCalcfg );
|
561 |
+
}
|
562 |
+
/**
|
563 |
+
* parse xml string into iCalcreator instance, alias of XML2iCal
|
564 |
+
*
|
565 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
566 |
+
* @since 2.16.22 - 2013-06-18
|
567 |
+
* @param string $xmlstr
|
568 |
+
* @param array $iCalcfg iCalcreator config array (opt)
|
569 |
+
* @return mixed iCalcreator instance or FALSE on error
|
570 |
+
*/
|
571 |
+
function wpsbc_XMLstr2iCal( $xmlstr, $iCalcfg=array()) {
|
572 |
+
return wpsbc_XML2iCal( $xmlstr, $iCalcfg);
|
573 |
+
}
|
574 |
+
/**
|
575 |
+
* parse xml string into iCalcreator instance
|
576 |
+
*
|
577 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
578 |
+
* @since 2.16.22 - 2013-06-20
|
579 |
+
* @param string $xmlstr
|
580 |
+
* @param array $iCalcfg iCalcreator config array (opt)
|
581 |
+
* @uses vcalendar::vcalendar()
|
582 |
+
* @uses XMLgetComps()
|
583 |
+
* @return mixed iCalcreator instance or FALSE on error
|
584 |
+
*/
|
585 |
+
function wpsbc_XML2iCal( $xmlstr, $iCalcfg=array()) {
|
586 |
+
$xmlstr = str_replace( array( "\r\n", "\n\r", "\n", "\r" ), '', $xmlstr );
|
587 |
+
$xml = wpsbc_XMLgetTagContent1( $xmlstr, 'vcalendar', $endIx );
|
588 |
+
$iCal = new vcalendar( $iCalcfg );
|
589 |
+
wpsbc_XMLgetComps( $iCal, $xmlstr );
|
590 |
+
unset( $xmlstr );
|
591 |
+
return $iCal;
|
592 |
+
}
|
593 |
+
/**
|
594 |
+
* parse XML string into iCalcreator components
|
595 |
+
*
|
596 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
597 |
+
* @since 2.21.11 - 2015-03-21
|
598 |
+
* @param object $iCal iCalcreator vcalendar or component object instance
|
599 |
+
* @param string $xml
|
600 |
+
* @uses iCalUtilityFunctions::$allComps
|
601 |
+
* @uses wpsbc_XMLgetTagContent1()
|
602 |
+
* @uses XMLgetProps()
|
603 |
+
* @uses wpsbc_XMLgetTagContent2()
|
604 |
+
* @uses vcalendar::newComponent()
|
605 |
+
* @uses iCalUtilityFunctions::$allComps
|
606 |
+
* @uses XMLgetComps()
|
607 |
+
* @return object
|
608 |
+
*/
|
609 |
+
function wpsbc_XMLgetComps( $iCal, $xml ) {
|
610 |
+
$sx = 0;
|
611 |
+
while(( FALSE !== substr( $xml, ( $sx + 11 ), 1 )) &&
|
612 |
+
( '<properties>' != substr( $xml, $sx, 12 )) && ( '<components>' != substr( $xml, $sx, 12 )))
|
613 |
+
$sx += 1;
|
614 |
+
if( FALSE === substr( $xml, ( $sx + 11 ), 1 ))
|
615 |
+
return FALSE;
|
616 |
+
if( '<properties>' == substr( $xml, $sx, 12 )) {
|
617 |
+
$xml2 = wpsbc_XMLgetTagContent1( $xml, 'properties', $endIx );
|
618 |
+
wpsbc_XMLgetProps( $iCal, $xml2 );
|
619 |
+
$xml = substr( $xml, $endIx );
|
620 |
+
}
|
621 |
+
if( '<components>' == substr( $xml, 0, 12 ))
|
622 |
+
$xml = wpsbc_XMLgetTagContent1( $xml, 'components', $endIx );
|
623 |
+
while( ! empty( $xml )) {
|
624 |
+
$xml2 = wpsbc_XMLgetTagContent2( $xml, $tagName, $endIx );
|
625 |
+
if( in_array( strtolower( $tagName ), iCalUtilityFunctions::$allComps ) &&
|
626 |
+
( FALSE !== ( $subComp = $iCal->newComponent( $tagName ))))
|
627 |
+
XMLgetComps( $subComp, $xml2 );
|
628 |
+
$xml = substr( $xml, $endIx);
|
629 |
+
}
|
630 |
+
unset( $xml );
|
631 |
+
return $iCal;
|
632 |
+
}
|
633 |
+
/**
|
634 |
+
* parse XML into iCalcreator properties
|
635 |
+
*
|
636 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
637 |
+
* @since 2.21.11 - 2015-03-21
|
638 |
+
* @param array $iCal iCalcreator calendar/component instance
|
639 |
+
* @param string $xml
|
640 |
+
* @uses wpsbc_XMLgetTagContent2()
|
641 |
+
* @uses vcalendar::setProperty()
|
642 |
+
* @uses calendarComponent::setproperty()
|
643 |
+
* @uses wpsbc_XMLgetTagContent1()
|
644 |
+
* @uses vcalendar::setProperty()
|
645 |
+
* @return void
|
646 |
+
*/
|
647 |
+
function wpsbc_XMLgetProps( $iCal, $xml) {
|
648 |
+
while( ! empty( $xml )) {
|
649 |
+
$xml2 = wpsbc_XMLgetTagContent2( $xml, $propName, $endIx );
|
650 |
+
$propName = strtoupper( $propName );
|
651 |
+
if( empty( $xml2 ) && ( '0' != $xml2 )) {
|
652 |
+
$iCal->setProperty( $propName );
|
653 |
+
$xml = substr( $xml, $endIx);
|
654 |
+
continue;
|
655 |
+
}
|
656 |
+
$params = array();
|
657 |
+
if( '<parameters/>' == substr( $xml2, 0, 13 ))
|
658 |
+
$xml2 = substr( $xml2, 13 );
|
659 |
+
elseif( '<parameters>' == substr( $xml2, 0, 12 )) {
|
660 |
+
$xml3 = wpsbc_XMLgetTagContent1( $xml2, 'parameters', $endIx2 );
|
661 |
+
while( ! empty( $xml3 )) {
|
662 |
+
$xml4 = wpsbc_XMLgetTagContent2( $xml3, $paramKey, $endIx3 );
|
663 |
+
$pType = FALSE; // skip parameter valueType
|
664 |
+
$paramKey = strtoupper( $paramKey );
|
665 |
+
static $mParams = array( 'DELEGATED-FROM', 'DELEGATED-TO', 'MEMBER' );
|
666 |
+
if( in_array( $paramKey, $mParams )) {
|
667 |
+
while( ! empty( $xml4 )) {
|
668 |
+
if( ! isset( $params[$paramKey] ))
|
669 |
+
$params[$paramKey] = array( wpsbc_XMLgetTagContent1( $xml4, 'cal-address', $endIx4 ));
|
670 |
+
else
|
671 |
+
$params[$paramKey][] = wpsbc_XMLgetTagContent1( $xml4, 'cal-address', $endIx4 );
|
672 |
+
$xml4 = substr( $xml4, $endIx4 );
|
673 |
+
}
|
674 |
+
}
|
675 |
+
else {
|
676 |
+
if( ! isset( $params[$paramKey] ))
|
677 |
+
$params[$paramKey] = html_entity_decode( wpsbc_XMLgetTagContent2( $xml4, $pType, $endIx4 ));
|
678 |
+
else
|
679 |
+
$params[$paramKey] .= ','.html_entity_decode( wpsbc_XMLgetTagContent2( $xml4, $pType, $endIx4 ));
|
680 |
+
}
|
681 |
+
$xml3 = substr( $xml3, $endIx3 );
|
682 |
+
}
|
683 |
+
$xml2 = substr( $xml2, $endIx2 );
|
684 |
+
} // if( '<parameters>' == substr( $xml2, 0, 12 ))
|
685 |
+
$valueType = FALSE;
|
686 |
+
$value = ( ! empty( $xml2 ) || ( '0' == $xml2 )) ? wpsbc_XMLgetTagContent2( $xml2, $valueType, $endIx3 ) : '';
|
687 |
+
switch( $propName ) {
|
688 |
+
case 'CATEGORIES':
|
689 |
+
case 'RESOURCES':
|
690 |
+
$tValue = array();
|
691 |
+
while( ! empty( $xml2 )) {
|
692 |
+
$tValue[] = html_entity_decode( wpsbc_XMLgetTagContent2( $xml2, $valueType, $endIx4 ));
|
693 |
+
$xml2 = substr( $xml2, $endIx4 );
|
694 |
+
}
|
695 |
+
$value = $tValue;
|
696 |
+
break;
|
697 |
+
case 'EXDATE': // multiple single-date(-times) may exist
|
698 |
+
case 'RDATE':
|
699 |
+
if( 'period' != $valueType ) {
|
700 |
+
if( 'date' == $valueType )
|
701 |
+
$params['VALUE'] = 'DATE';
|
702 |
+
$t = array();
|
703 |
+
while( ! empty( $xml2 ) && ( '<date' == substr( $xml2, 0, 5 ))) {
|
704 |
+
$t[] = wpsbc_XMLgetTagContent2( $xml2, $pType, $endIx4 );
|
705 |
+
$xml2 = substr( $xml2, $endIx4 );
|
706 |
+
}
|
707 |
+
$value = $t;
|
708 |
+
break;
|
709 |
+
}
|
710 |
+
case 'FREEBUSY':
|
711 |
+
if( 'RDATE' == $propName )
|
712 |
+
$params['VALUE'] = 'PERIOD';
|
713 |
+
$value = array();
|
714 |
+
while( ! empty( $xml2 ) && ( '<period>' == substr( $xml2, 0, 8 ))) {
|
715 |
+
$xml3 = wpsbc_XMLgetTagContent1( $xml2, 'period', $endIx4 ); // period
|
716 |
+
$t = array();
|
717 |
+
while( ! empty( $xml3 )) {
|
718 |
+
$t[] = wpsbc_XMLgetTagContent2( $xml3, $pType, $endIx5 ); // start - end/duration
|
719 |
+
$xml3 = substr( $xml3, $endIx5 );
|
720 |
+
}
|
721 |
+
$value[] = $t;
|
722 |
+
$xml2 = substr( $xml2, $endIx4 );
|
723 |
+
}
|
724 |
+
break;
|
725 |
+
case 'TZOFFSETTO':
|
726 |
+
case 'TZOFFSETFROM':
|
727 |
+
$value = str_replace( ':', '', $value );
|
728 |
+
break;
|
729 |
+
case 'GEO':
|
730 |
+
$tValue = array( 'latitude' => $value );
|
731 |
+
$tValue['longitude'] = wpsbc_XMLgetTagContent1( substr( $xml2, $endIx3 ), 'longitude', $endIx3 );
|
732 |
+
$value = $tValue;
|
733 |
+
break;
|
734 |
+
case 'EXRULE':
|
735 |
+
case 'RRULE':
|
736 |
+
$tValue = array( $valueType => $value );
|
737 |
+
$xml2 = substr( $xml2, $endIx3 );
|
738 |
+
$valueType = FALSE;
|
739 |
+
while( ! empty( $xml2 )) {
|
740 |
+
$t = wpsbc_XMLgetTagContent2( $xml2, $valueType, $endIx4 );
|
741 |
+
switch( $valueType ) {
|
742 |
+
case 'freq':
|
743 |
+
case 'count':
|
744 |
+
case 'until':
|
745 |
+
case 'interval':
|
746 |
+
case 'wkst':
|
747 |
+
$tValue[$valueType] = $t;
|
748 |
+
break;
|
749 |
+
case 'byday':
|
750 |
+
if( 2 == strlen( $t ))
|
751 |
+
$tValue[$valueType][] = array( 'DAY' => $t );
|
752 |
+
else {
|
753 |
+
$day = substr( $t, -2 );
|
754 |
+
$key = substr( $t, 0, ( strlen( $t ) - 2 ));
|
755 |
+
$tValue[$valueType][] = array( $key, 'DAY' => $day );
|
756 |
+
}
|
757 |
+
break;
|
758 |
+
default:
|
759 |
+
$tValue[$valueType][] = $t;
|
760 |
+
}
|
761 |
+
$xml2 = substr( $xml2, $endIx4 );
|
762 |
+
}
|
763 |
+
$value = $tValue;
|
764 |
+
break;
|
765 |
+
case 'REQUEST-STATUS':
|
766 |
+
$tValue = array();
|
767 |
+
while( ! empty( $xml2 )) {
|
768 |
+
$t = html_entity_decode( wpsbc_XMLgetTagContent2( $xml2, $valueType, $endIx4 ));
|
769 |
+
$tValue[$valueType] = $t;
|
770 |
+
$xml2 = substr( $xml2, $endIx4 );
|
771 |
+
}
|
772 |
+
if( ! empty( $tValue ))
|
773 |
+
$value = $tValue;
|
774 |
+
else
|
775 |
+
$value = array( 'code' => null, 'description' => null );
|
776 |
+
break;
|
777 |
+
default:
|
778 |
+
switch( $valueType ) {
|
779 |
+
case 'binary': $params['VALUE'] = 'BINARY'; break;
|
780 |
+
case 'date': $params['VALUE'] = 'DATE'; break;
|
781 |
+
case 'date-time': $params['VALUE'] = 'DATE-TIME'; break;
|
782 |
+
case 'text':
|
783 |
+
case 'unknown': $value = html_entity_decode( $value ); break;
|
784 |
+
}
|
785 |
+
break;
|
786 |
+
} // end switch( $propName )
|
787 |
+
if( 'FREEBUSY' == $propName ) {
|
788 |
+
$fbtype = $params['FBTYPE'];
|
789 |
+
unset( $params['FBTYPE'] );
|
790 |
+
$iCal->setProperty( $propName, $fbtype, $value, $params );
|
791 |
+
}
|
792 |
+
elseif( 'GEO' == $propName )
|
793 |
+
$iCal->setProperty( $propName, $value['latitude'], $value['longitude'], $params );
|
794 |
+
elseif( 'REQUEST-STATUS' == $propName ) {
|
795 |
+
if( !isset( $value['data'] ))
|
796 |
+
$value['data'] = FALSE;
|
797 |
+
$iCal->setProperty( $propName, $value['code'], $value['description'], $value['data'], $params );
|
798 |
+
}
|
799 |
+
else {
|
800 |
+
if( empty( $value ) && ( is_array( $value ) || ( '0' > $value )))
|
801 |
+
$value = '';
|
802 |
+
$iCal->setProperty( $propName, $value, $params );
|
803 |
+
}
|
804 |
+
$xml = substr( $xml, $endIx);
|
805 |
+
} // end while( ! empty( $xml ))
|
806 |
+
}
|
807 |
+
/**
|
808 |
+
* fetch a specific XML tag content
|
809 |
+
*
|
810 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
811 |
+
* @since 2.16.22 - 2013-06-20
|
812 |
+
* @param string $xml
|
813 |
+
* @param string $tagName
|
814 |
+
* @param int $endIx
|
815 |
+
* @return mixed
|
816 |
+
*/
|
817 |
+
function wpsbc_XMLgetTagContent1( $xml, $tagName, & $endIx=0 ) {
|
818 |
+
$strlen = strlen( $tagName );
|
819 |
+
$sx1 = 0;
|
820 |
+
while( FALSE !== substr( $xml, $sx1, 1 )) {
|
821 |
+
if(( FALSE !== substr( $xml, ( $sx1 + $strlen + 1 ), 1 )) &&
|
822 |
+
( strtolower( "<$tagName>" ) == strtolower( substr( $xml, $sx1, ( $strlen + 2 )))))
|
823 |
+
break;
|
824 |
+
if(( FALSE !== substr( $xml, ( $sx1 + $strlen + 3 ), 1 )) &&
|
825 |
+
( strtolower( "<$tagName />" ) == strtolower( substr( $xml, $sx1, ( $strlen + 4 ))))) { // empty tag
|
826 |
+
$endIx = $strlen + 5;
|
827 |
+
return '';
|
828 |
+
}
|
829 |
+
if(( FALSE !== substr( $xml, ( $sx1 + $strlen + 2 ), 1 )) &&
|
830 |
+
( strtolower( "<$tagName/>" ) == strtolower( substr( $xml, $sx1, ( $strlen + 3 ))))) { // empty tag
|
831 |
+
$endIx = $strlen + 4;
|
832 |
+
return '';
|
833 |
+
}
|
834 |
+
$sx1 += 1;
|
835 |
+
}
|
836 |
+
if( FALSE === substr( $xml, $sx1, 1 )) {
|
837 |
+
$endIx = ( empty( $sx )) ? 0 : $sx - 1;
|
838 |
+
return '';
|
839 |
+
}
|
840 |
+
if( FALSE === ( $pos = stripos( $xml, "</$tagName>" ))) { // missing end tag??
|
841 |
+
$endIx = strlen( $xml ) + 1;
|
842 |
+
return '';
|
843 |
+
}
|
844 |
+
$endIx = $pos + $strlen + 3;
|
845 |
+
return substr( $xml, ( $sx1 + $strlen + 2 ), ( $pos - $sx1 - 2 - $strlen ));
|
846 |
+
}
|
847 |
+
/**
|
848 |
+
* fetch next (unknown) XML tagname AND content
|
849 |
+
*
|
850 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
851 |
+
* @since 2.16.22 - 2013-06-20
|
852 |
+
* @param string $xml
|
853 |
+
* @param string $tagName
|
854 |
+
* @param int $endIx
|
855 |
+
* @return mixed
|
856 |
+
*/
|
857 |
+
function wpsbc_XMLgetTagContent2( $xml, & $tagName, & $endIx ) {
|
858 |
+
$endIx = strlen( $xml ) + 1; // just in case.. .
|
859 |
+
$sx1 = 0;
|
860 |
+
while( FALSE !== substr( $xml, $sx1, 1 )) {
|
861 |
+
if( '<' == substr( $xml, $sx1, 1 )) {
|
862 |
+
if(( FALSE !== substr( $xml, ( $sx1 + 3 ), 1 )) && ( '<!--' == substr( $xml, $sx1, 4 ))) // skip comment
|
863 |
+
$sx1 += 1;
|
864 |
+
else
|
865 |
+
break; // tagname start here
|
866 |
+
}
|
867 |
+
else
|
868 |
+
$sx1 += 1;
|
869 |
+
}
|
870 |
+
$sx2 = $sx1;
|
871 |
+
while( FALSE !== substr( $xml, $sx2 )) {
|
872 |
+
if(( FALSE !== substr( $xml, ( $sx2 + 1 ), 1 )) && ( '/>' == substr( $xml, $sx2, 2 ))) { // empty tag
|
873 |
+
$tagName = trim( substr( $xml, ( $sx1 + 1 ), ( $sx2 - $sx1 - 1 )));
|
874 |
+
$endIx = $sx2 + 2;
|
875 |
+
return '';
|
876 |
+
}
|
877 |
+
if( '>' == substr( $xml, $sx2, 1 )) // tagname ends here
|
878 |
+
break;
|
879 |
+
$sx2 += 1;
|
880 |
+
}
|
881 |
+
$tagName = substr( $xml, ( $sx1 + 1 ), ( $sx2 - $sx1 - 1 ));
|
882 |
+
$endIx = $sx2 + 1;
|
883 |
+
if( FALSE === substr( $xml, $sx2, 1 )) {
|
884 |
+
return '';
|
885 |
+
}
|
886 |
+
$strlen = strlen( $tagName );
|
887 |
+
if(( 'duration' == $tagName ) &&
|
888 |
+
( FALSE !== ( $pos1 = stripos( $xml, "<duration>", $sx1+1 ))) &&
|
889 |
+
( FALSE !== ( $pos2 = stripos( $xml, "</duration>", $pos1+1 ))) &&
|
890 |
+
( FALSE !== ( $pos3 = stripos( $xml, "</duration>", $pos2+1 ))) &&
|
891 |
+
( $pos1 < $pos2 ) && ( $pos2 < $pos3 ))
|
892 |
+
$pos = $pos3;
|
893 |
+
elseif( FALSE === ( $pos = stripos( $xml, "</$tagName>", $sx2 )))
|
894 |
+
return '';
|
895 |
+
$endIx = $pos + $strlen + 3;
|
896 |
+
return substr( $xml, ( $sx1 + $strlen + 2 ), ( $pos - $strlen - 2 ));
|
897 |
+
}
|
includes/libs/iCal/lib/iCal.tz.inc.php
ADDED
@@ -0,0 +1,292 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/* Additional functions to use with vtimezone components */
|
4 |
+
/*********************************************************************************/
|
5 |
+
/**
|
6 |
+
* For use with
|
7 |
+
* iCalcreator (kigkonsult.se/iCalcreator/index.php)
|
8 |
+
* copyright (c) 2011 Yitzchok Lavi
|
9 |
+
* icalcreator@onebigsystem.com
|
10 |
+
* @version 2.22
|
11 |
+
*
|
12 |
+
* This library is free software; you can redistribute it and/or
|
13 |
+
* modify it under the terms of the GNU Lesser General Public
|
14 |
+
* License as published by the Free Software Foundation; either
|
15 |
+
* version 2.1 of the License, or (at your option) any later version.
|
16 |
+
*
|
17 |
+
* This library is distributed in the hope that it will be useful,
|
18 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
20 |
+
* Lesser General Public License for more details.
|
21 |
+
*
|
22 |
+
* You should have received a copy of the GNU Lesser General Public
|
23 |
+
* License along with this library; if not, write to the Free Software
|
24 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
25 |
+
*/
|
26 |
+
/**
|
27 |
+
* Additional functions to use with vtimezone components
|
28 |
+
*
|
29 |
+
* Before calling the functions, set time zone 'GMT' ('date_default_timezone_set')!
|
30 |
+
*
|
31 |
+
* @author Yitzchok Lavi <icalcreator@onebigsystem.com>
|
32 |
+
* adjusted for iCalcreator Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @version 1.0.2 - 2011-02-24
|
34 |
+
*
|
35 |
+
*/
|
36 |
+
/**
|
37 |
+
* Returns array with the offset information from UTC for a (UTC) datetime/timestamp in the
|
38 |
+
* timezone, according to the VTIMEZONE information in the input array.
|
39 |
+
*
|
40 |
+
* @param array $timezonesarray output from function getTimezonesAsDateArrays (below)
|
41 |
+
* @param string $tzid time zone identifier
|
42 |
+
* @param mixed $timestamp timestamp or a UTC datetime (in array format)
|
43 |
+
* @return array time zone data with keys for 'offsetHis', 'offsetSec' and 'tzname'
|
44 |
+
*
|
45 |
+
*/
|
46 |
+
function wpsbc_getTzOffsetForDate($timezonesarray, $tzid, $timestamp) {
|
47 |
+
if( is_array( $timestamp )) {
|
48 |
+
//$disp = sprintf( '%04d%02d%02d %02d%02d%02d', $timestamp['year'], $timestamp['month'], $timestamp['day'], $timestamp['hour'], $timestamp['min'], $timestamp['sec'] ); // test ###
|
49 |
+
$timestamp = gmmktime(
|
50 |
+
$timestamp['hour'],
|
51 |
+
$timestamp['min'],
|
52 |
+
$timestamp['sec'],
|
53 |
+
$timestamp['month'],
|
54 |
+
$timestamp['day'],
|
55 |
+
$timestamp['year']
|
56 |
+
) ;
|
57 |
+
}
|
58 |
+
$tzoffset = array();
|
59 |
+
// something to return if all goes wrong (such as if $tzid doesn't find us an array of dates)
|
60 |
+
$tzoffset['offsetHis'] = '+0000';
|
61 |
+
$tzoffset['offsetSec'] = 0;
|
62 |
+
$tzoffset['tzname'] = '?';
|
63 |
+
if( !isset( $timezonesarray[$tzid] ))
|
64 |
+
return $tzoffset;
|
65 |
+
$tzdatearray = $timezonesarray[$tzid];
|
66 |
+
if ( is_array($tzdatearray) ) {
|
67 |
+
sort($tzdatearray); // just in case
|
68 |
+
if ( $timestamp < $tzdatearray[0]['timestamp'] ) {
|
69 |
+
// our date is before the first change
|
70 |
+
$tzoffset['offsetHis'] = $tzdatearray[0]['tzbefore']['offsetHis'] ;
|
71 |
+
$tzoffset['offsetSec'] = $tzdatearray[0]['tzbefore']['offsetSec'] ;
|
72 |
+
$tzoffset['tzname'] = $tzdatearray[0]['tzbefore']['offsetHis'] ; // we don't know the tzname in this case
|
73 |
+
} elseif ( $timestamp >= $tzdatearray[count($tzdatearray)-1]['timestamp'] ) {
|
74 |
+
// our date is after the last change (we do this so our scan can stop at the last record but one)
|
75 |
+
$tzoffset['offsetHis'] = $tzdatearray[count($tzdatearray)-1]['tzafter']['offsetHis'] ;
|
76 |
+
$tzoffset['offsetSec'] = $tzdatearray[count($tzdatearray)-1]['tzafter']['offsetSec'] ;
|
77 |
+
$tzoffset['tzname'] = $tzdatearray[count($tzdatearray)-1]['tzafter']['tzname'] ;
|
78 |
+
} else {
|
79 |
+
// our date somewhere in between
|
80 |
+
// loop through the list of dates and stop at the one where the timestamp is before our date and the next one is after it
|
81 |
+
// we don't include the last date in our loop as there isn't one after it to check
|
82 |
+
for ( $i = 0 ; $i <= count($tzdatearray)-2 ; $i++ ) {
|
83 |
+
if(( $timestamp >= $tzdatearray[$i]['timestamp'] ) && ( $timestamp < $tzdatearray[$i+1]['timestamp'] )) {
|
84 |
+
$tzoffset['offsetHis'] = $tzdatearray[$i]['tzafter']['offsetHis'] ;
|
85 |
+
$tzoffset['offsetSec'] = $tzdatearray[$i]['tzafter']['offsetSec'] ;
|
86 |
+
$tzoffset['tzname'] = $tzdatearray[$i]['tzafter']['tzname'] ;
|
87 |
+
break;
|
88 |
+
}
|
89 |
+
}
|
90 |
+
}
|
91 |
+
}
|
92 |
+
return $tzoffset;
|
93 |
+
}
|
94 |
+
/**
|
95 |
+
* Returns an array containing all the timezone data in the vcalendar object
|
96 |
+
*
|
97 |
+
* @param object $vcalendar iCalcreator calendar instance
|
98 |
+
* @return array time zone transition timestamp, array before(offsetHis, offsetSec), array after(offsetHis, offsetSec, tzname)
|
99 |
+
* based on the timezone data in the vcalendar object
|
100 |
+
*
|
101 |
+
*/
|
102 |
+
function wpsbc_getTimezonesAsDateArrays($vcalendar) {
|
103 |
+
$timezonedata = array();
|
104 |
+
while( $vtz = $vcalendar->getComponent( 'vtimezone' )) {
|
105 |
+
$tzid = $vtz->getProperty('tzid');
|
106 |
+
$alltzdates = array();
|
107 |
+
while ( $vtzc = $vtz->getComponent( 'standard' )) {
|
108 |
+
$newtzdates = expandTimezoneDates($vtzc);
|
109 |
+
$alltzdates = array_merge($alltzdates, $newtzdates);
|
110 |
+
}
|
111 |
+
while ( $vtzc = $vtz->getComponent( 'daylight' )) {
|
112 |
+
$newtzdates = expandTimezoneDates($vtzc);
|
113 |
+
$alltzdates = array_merge($alltzdates, $newtzdates);
|
114 |
+
}
|
115 |
+
sort($alltzdates);
|
116 |
+
$timezonedata[$tzid] = $alltzdates;
|
117 |
+
}
|
118 |
+
return $timezonedata;
|
119 |
+
}
|
120 |
+
/**
|
121 |
+
* Returns an array containing time zone data from vtimezone standard/daylight instances
|
122 |
+
*
|
123 |
+
* @param object $vtzc an iCalcreator calendar standard/daylight instance
|
124 |
+
* @return array time zone data; array before(offsetHis, offsetSec), array after(offsetHis, offsetSec, tzname)
|
125 |
+
*
|
126 |
+
*/
|
127 |
+
function wpsbc_expandTimezoneDates($vtzc) {
|
128 |
+
$tzdates = array();
|
129 |
+
// prepare time zone "description" to attach to each change
|
130 |
+
$tzbefore = array();
|
131 |
+
$tzbefore['offsetHis'] = $vtzc->getProperty('tzoffsetfrom') ;
|
132 |
+
$tzbefore['offsetSec'] = iCalUtilityFunctions::_tz2offset($tzbefore['offsetHis']);
|
133 |
+
if(( '-' != substr( (string) $tzbefore['offsetSec'], 0, 1 )) && ( '+' != substr( (string) $tzbefore['offsetSec'], 0, 1 )))
|
134 |
+
$tzbefore['offsetSec'] = '+'.$tzbefore['offsetSec'];
|
135 |
+
$tzafter = array();
|
136 |
+
$tzafter['offsetHis'] = $vtzc->getProperty('tzoffsetto') ;
|
137 |
+
$tzafter['offsetSec'] = iCalUtilityFunctions::_tz2offset($tzafter['offsetHis']);
|
138 |
+
if(( '-' != substr( (string) $tzafter['offsetSec'], 0, 1 )) && ( '+' != substr( (string) $tzafter['offsetSec'], 0, 1 )))
|
139 |
+
$tzafter['offsetSec'] = '+'.$tzafter['offsetSec'];
|
140 |
+
if( FALSE === ( $tzafter['tzname'] = $vtzc->getProperty('tzname')))
|
141 |
+
$tzafter['tzname'] = $tzafter['offsetHis'];
|
142 |
+
// find out where to start from
|
143 |
+
$dtstart = $vtzc->getProperty('dtstart');
|
144 |
+
$dtstarttimestamp = mktime(
|
145 |
+
$dtstart['hour'],
|
146 |
+
$dtstart['min'],
|
147 |
+
$dtstart['sec'],
|
148 |
+
$dtstart['month'],
|
149 |
+
$dtstart['day'],
|
150 |
+
$dtstart['year']
|
151 |
+
) ;
|
152 |
+
if( !isset( $dtstart['unparsedtext'] )) // ??
|
153 |
+
$dtstart['unparsedtext'] = sprintf( '%04d%02d%02dT%02d%02d%02d', $dtstart['year'], $dtstart['month'], $dtstart['day'], $dtstart['hour'], $dtstart['min'], $dtstart['sec'] );
|
154 |
+
if ( $dtstarttimestamp == 0 ) {
|
155 |
+
// it seems that the dtstart string may not have parsed correctly
|
156 |
+
// let's set a timestamp starting from 1902, using the time part of the original string
|
157 |
+
// so that the time will change at the right time of day
|
158 |
+
// at worst we'll get midnight again
|
159 |
+
$origdtstartsplit = explode('T',$dtstart['unparsedtext']) ;
|
160 |
+
$dtstarttimestamp = strtotime("19020101",0);
|
161 |
+
$dtstarttimestamp = strtotime($origdtstartsplit[1],$dtstarttimestamp);
|
162 |
+
}
|
163 |
+
// the date (in dtstart and opt RDATE/RRULE) is ALWAYS LOCAL (not utc!!), adjust from 'utc' to 'local' timestamp
|
164 |
+
$diff = -1 * $tzbefore['offsetSec'];
|
165 |
+
$dtstarttimestamp += $diff;
|
166 |
+
// add this (start) change to the array of changes
|
167 |
+
$tzdates[] = array(
|
168 |
+
'timestamp' => $dtstarttimestamp,
|
169 |
+
'tzbefore' => $tzbefore,
|
170 |
+
'tzafter' => $tzafter
|
171 |
+
);
|
172 |
+
$datearray = getdate($dtstarttimestamp);
|
173 |
+
// save original array to use time parts, because strtotime (used below) apparently loses the time
|
174 |
+
$changetime = $datearray ;
|
175 |
+
// generate dates according to an RRULE line
|
176 |
+
$rrule = $vtzc->getProperty('rrule') ;
|
177 |
+
if ( is_array($rrule) ) {
|
178 |
+
if ( $rrule['FREQ'] == 'YEARLY' ) {
|
179 |
+
// calculate transition dates starting from DTSTART
|
180 |
+
$offsetchangetimestamp = $dtstarttimestamp;
|
181 |
+
// calculate transition dates until 10 years in the future
|
182 |
+
$stoptimestamp = strtotime("+10 year",time());
|
183 |
+
// if UNTIL is set, calculate until then (however far ahead)
|
184 |
+
if ( isset( $rrule['UNTIL'] ) && ( $rrule['UNTIL'] != '' )) {
|
185 |
+
$stoptimestamp = mktime(
|
186 |
+
$rrule['UNTIL']['hour'],
|
187 |
+
$rrule['UNTIL']['min'],
|
188 |
+
$rrule['UNTIL']['sec'],
|
189 |
+
$rrule['UNTIL']['month'],
|
190 |
+
$rrule['UNTIL']['day'],
|
191 |
+
$rrule['UNTIL']['year']
|
192 |
+
) ;
|
193 |
+
}
|
194 |
+
$count = 0 ;
|
195 |
+
$stopcount = isset( $rrule['COUNT'] ) ? $rrule['COUNT'] : 0 ;
|
196 |
+
$daynames = array(
|
197 |
+
'SU' => 'Sunday',
|
198 |
+
'MO' => 'Monday',
|
199 |
+
'TU' => 'Tuesday',
|
200 |
+
'WE' => 'Wednesday',
|
201 |
+
'TH' => 'Thursday',
|
202 |
+
'FR' => 'Friday',
|
203 |
+
'SA' => 'Saturday'
|
204 |
+
);
|
205 |
+
// repeat so long as we're between DTSTART and UNTIL, or we haven't prepared COUNT dates
|
206 |
+
while ( $offsetchangetimestamp < $stoptimestamp && ( $stopcount == 0 || $count < $stopcount ) ) {
|
207 |
+
// break up the timestamp into its parts
|
208 |
+
$datearray = getdate($offsetchangetimestamp);
|
209 |
+
if ( isset( $rrule['BYMONTH'] ) && ( $rrule['BYMONTH'] != 0 )) {
|
210 |
+
// set the month
|
211 |
+
$datearray['mon'] = $rrule['BYMONTH'] ;
|
212 |
+
}
|
213 |
+
if ( isset( $rrule['BYMONTHDAY'] ) && ( $rrule['BYMONTHDAY'] != 0 )) {
|
214 |
+
// set specific day of month
|
215 |
+
$datearray['mday'] = $rrule['BYMONTHDAY'];
|
216 |
+
} elseif ( is_array($rrule['BYDAY']) ) {
|
217 |
+
// find the Xth WKDAY in the month
|
218 |
+
// the starting point for this process is the first of the month set above
|
219 |
+
$datearray['mday'] = 1 ;
|
220 |
+
// turn $datearray as it is now back into a timestamp
|
221 |
+
$offsetchangetimestamp = mktime(
|
222 |
+
$datearray['hours'],
|
223 |
+
$datearray['minutes'],
|
224 |
+
$datearray['seconds'],
|
225 |
+
$datearray['mon'],
|
226 |
+
$datearray['mday'],
|
227 |
+
$datearray['year']
|
228 |
+
);
|
229 |
+
if ($rrule['BYDAY'][0] > 0) {
|
230 |
+
// to find Xth WKDAY in month, we find last WKDAY in month before
|
231 |
+
// we do that by finding first WKDAY in this month and going back one week
|
232 |
+
// then we add X weeks (below)
|
233 |
+
$offsetchangetimestamp = strtotime($daynames[$rrule['BYDAY']['DAY']],$offsetchangetimestamp);
|
234 |
+
$offsetchangetimestamp = strtotime("-1 week",$offsetchangetimestamp);
|
235 |
+
} else {
|
236 |
+
// to find Xth WKDAY before the end of the month, we find the first WKDAY in the following month
|
237 |
+
// we do that by going forward one month and going to WKDAY there
|
238 |
+
// then we subtract X weeks (below)
|
239 |
+
$offsetchangetimestamp = strtotime("+1 month",$offsetchangetimestamp);
|
240 |
+
$offsetchangetimestamp = strtotime($daynames[$rrule['BYDAY']['DAY']],$offsetchangetimestamp);
|
241 |
+
}
|
242 |
+
// now move forward or back the appropriate number of weeks, into the month we want
|
243 |
+
$offsetchangetimestamp = strtotime($rrule['BYDAY'][0] . " week",$offsetchangetimestamp);
|
244 |
+
$datearray = getdate($offsetchangetimestamp);
|
245 |
+
}
|
246 |
+
// convert the date parts back into a timestamp, setting the time parts according to the
|
247 |
+
// original time data which we stored
|
248 |
+
$offsetchangetimestamp = mktime(
|
249 |
+
$changetime['hours'],
|
250 |
+
$changetime['minutes'],
|
251 |
+
$changetime['seconds'] + $diff,
|
252 |
+
$datearray['mon'],
|
253 |
+
$datearray['mday'],
|
254 |
+
$datearray['year']
|
255 |
+
);
|
256 |
+
// add this change to the array of changes
|
257 |
+
$tzdates[] = array(
|
258 |
+
'timestamp' => $offsetchangetimestamp,
|
259 |
+
'tzbefore' => $tzbefore,
|
260 |
+
'tzafter' => $tzafter
|
261 |
+
);
|
262 |
+
// update counters (timestamp and count)
|
263 |
+
$offsetchangetimestamp = strtotime("+" . (( isset( $rrule['INTERVAL'] ) && ( $rrule['INTERVAL'] != 0 )) ? $rrule['INTERVAL'] : 1 ) . " year",$offsetchangetimestamp);
|
264 |
+
$count += 1 ;
|
265 |
+
}
|
266 |
+
}
|
267 |
+
}
|
268 |
+
// generate dates according to RDATE lines
|
269 |
+
while ($rdates = $vtzc->getProperty('rdate')) {
|
270 |
+
if ( is_array($rdates) ) {
|
271 |
+
|
272 |
+
foreach ( $rdates as $rdate ) {
|
273 |
+
// convert the explicit change date to a timestamp
|
274 |
+
$offsetchangetimestamp = mktime(
|
275 |
+
$rdate['hour'],
|
276 |
+
$rdate['min'],
|
277 |
+
$rdate['sec'] + $diff,
|
278 |
+
$rdate['month'],
|
279 |
+
$rdate['day'],
|
280 |
+
$rdate['year']
|
281 |
+
) ;
|
282 |
+
// add this change to the array of changes
|
283 |
+
$tzdates[] = array(
|
284 |
+
'timestamp' => $offsetchangetimestamp,
|
285 |
+
'tzbefore' => $tzbefore,
|
286 |
+
'tzafter' => $tzafter
|
287 |
+
);
|
288 |
+
}
|
289 |
+
}
|
290 |
+
}
|
291 |
+
return $tzdates;
|
292 |
+
}
|
includes/libs/iCal/lib/iCal.vCard.inc.php
ADDED
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/* iCalcreator vCard helper functions */
|
30 |
+
/*********************************************************************************/
|
31 |
+
/**
|
32 |
+
* convert single ATTENDEE, CONTACT or ORGANIZER (in email format) to vCard
|
33 |
+
* returns vCard/TRUE or if directory (if set) or file write is unvalid, FALSE
|
34 |
+
*
|
35 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
36 |
+
* @since 2.12.2 - 2012-07-11
|
37 |
+
* @param string $email
|
38 |
+
* @param string $version vCard version (default 2.1)
|
39 |
+
* @param string $directory where to save vCards (default FALSE)
|
40 |
+
* @param string $ext vCard file extension (default 'vcf')
|
41 |
+
* @uses ICALCREATOR_VERSION
|
42 |
+
* @return mixed
|
43 |
+
*/
|
44 |
+
function wpsbc_iCal2vCard( $email, $version='2.1', $directory=FALSE, $ext='vcf' ) {
|
45 |
+
if( FALSE === ( $pos = strpos( $email, '@' )))
|
46 |
+
return FALSE;
|
47 |
+
if( $directory ) {
|
48 |
+
if( DIRECTORY_SEPARATOR != substr( $directory, ( 0 - strlen( DIRECTORY_SEPARATOR ))))
|
49 |
+
$directory .= DIRECTORY_SEPARATOR;
|
50 |
+
if( !is_dir( $directory ) || !is_writable( $directory ))
|
51 |
+
return FALSE;
|
52 |
+
}
|
53 |
+
/* prepare vCard */
|
54 |
+
$email = str_replace( 'MAILTO:', '', $email );
|
55 |
+
$name = $person = substr( $email, 0, $pos );
|
56 |
+
if( ctype_upper( $name ) || ctype_lower( $name ))
|
57 |
+
$name = array( $name );
|
58 |
+
else {
|
59 |
+
if( FALSE !== ( $pos = strpos( $name, '.' ))) {
|
60 |
+
$name = explode( '.', $name );
|
61 |
+
foreach( $name as $k => $part )
|
62 |
+
$name[$k] = ucfirst( $part );
|
63 |
+
}
|
64 |
+
else { // split camelCase
|
65 |
+
$chars = $name;
|
66 |
+
$name = array( $chars[0] );
|
67 |
+
$k = 0;
|
68 |
+
$x = 1;
|
69 |
+
while( FALSE !== ( $char = substr( $chars, $x, 1 ))) {
|
70 |
+
if( ctype_upper( $char )) {
|
71 |
+
$k += 1;
|
72 |
+
$name[$k] = '';
|
73 |
+
}
|
74 |
+
$name[$k] .= $char;
|
75 |
+
$x++;
|
76 |
+
}
|
77 |
+
}
|
78 |
+
}
|
79 |
+
$nl = "\r\n";
|
80 |
+
$FN = 'FN:'.implode( ' ', $name ).$nl;
|
81 |
+
$name = array_reverse( $name );
|
82 |
+
$N = 'N:'.array_shift( $name );
|
83 |
+
$scCnt = 0;
|
84 |
+
while( NULL != ( $part = array_shift( $name ))) {
|
85 |
+
if(( '4.0' != $version ) || ( 4 > $scCnt ))
|
86 |
+
$scCnt += 1;
|
87 |
+
$N .= ';'.$part;
|
88 |
+
}
|
89 |
+
while(( '4.0' == $version ) && ( 4 > $scCnt )) {
|
90 |
+
$N .= ';';
|
91 |
+
$scCnt += 1;
|
92 |
+
}
|
93 |
+
$N .= $nl;
|
94 |
+
$EMAIL = 'EMAIL:'.$email.$nl;
|
95 |
+
/* create vCard */
|
96 |
+
$vCard = 'BEGIN:VCARD'.$nl;
|
97 |
+
$vCard .= "VERSION:$version$nl";
|
98 |
+
$vCard .= 'PRODID:-//kigkonsult.se '.ICALCREATOR_VERSION."//$nl";
|
99 |
+
$vCard .= $N;
|
100 |
+
$vCard .= $FN;
|
101 |
+
$vCard .= $EMAIL;
|
102 |
+
$vCard .= 'REV:'.gmdate( 'Ymd\THis\Z' ).$nl;
|
103 |
+
$vCard .= 'END:VCARD'.$nl;
|
104 |
+
/* save each vCard as (unique) single file */
|
105 |
+
if( $directory ) {
|
106 |
+
$fname = $directory.preg_replace( '/[^a-z0-9.]/i', '', $email );
|
107 |
+
$cnt = 1;
|
108 |
+
$dbl = '';
|
109 |
+
while( is_file ( $fname.$dbl.'.'.$ext )) {
|
110 |
+
$cnt += 1;
|
111 |
+
$dbl = "_$cnt";
|
112 |
+
}
|
113 |
+
if( FALSE === file_put_contents( $fname, $fname.$dbl.'.'.$ext ))
|
114 |
+
return FALSE;
|
115 |
+
return TRUE;
|
116 |
+
}
|
117 |
+
/* return vCard */
|
118 |
+
else
|
119 |
+
return $vCard;
|
120 |
+
}
|
121 |
+
/**
|
122 |
+
* convert ATTENDEEs, CONTACTs and ORGANIZERs (in email format) to vCards
|
123 |
+
*
|
124 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
125 |
+
* @since 2.12.2 - 2012-05-07
|
126 |
+
* @param object $calendar iCalcreator vcalendar instance reference
|
127 |
+
* @param string $version vCard version (default 2.1)
|
128 |
+
* @param string $directory where to save vCards (default FALSE)
|
129 |
+
* @param string $ext vCard file extension (default 'vcf')
|
130 |
+
* @uses vcalendar::getProperty()
|
131 |
+
* @return mixed
|
132 |
+
*/
|
133 |
+
function wpsbc_iCal2vCards( & $calendar, $version='2.1', $directory=FALSE, $ext='vcf' ) {
|
134 |
+
$hits = array();
|
135 |
+
$vCardP = array( 'ATTENDEE', 'CONTACT', 'ORGANIZER' );
|
136 |
+
foreach( $vCardP as $prop ) {
|
137 |
+
$hits2 = $calendar->getProperty( $prop );
|
138 |
+
foreach( $hits2 as $propValue => $occCnt ) {
|
139 |
+
if( FALSE === ( $pos = strpos( $propValue, '@' )))
|
140 |
+
continue;
|
141 |
+
$propValue = str_replace( 'MAILTO:', '', $propValue );
|
142 |
+
if( isset( $hits[$propValue] ))
|
143 |
+
$hits[$propValue] += $occCnt;
|
144 |
+
else
|
145 |
+
$hits[$propValue] = $occCnt;
|
146 |
+
}
|
147 |
+
}
|
148 |
+
if( empty( $hits ))
|
149 |
+
return FALSE;
|
150 |
+
ksort( $hits );
|
151 |
+
$output = '';
|
152 |
+
foreach( $hits as $email => $skip ) {
|
153 |
+
$res = wpsbc_iCal2vCard( $email, $version, $directory, $ext );
|
154 |
+
if( $directory && !$res )
|
155 |
+
return FALSE;
|
156 |
+
elseif( !$res )
|
157 |
+
return $res;
|
158 |
+
else
|
159 |
+
$output .= $res;
|
160 |
+
}
|
161 |
+
if( $directory )
|
162 |
+
return TRUE;
|
163 |
+
if( !empty( $output ))
|
164 |
+
return $output;
|
165 |
+
return FALSE;
|
166 |
+
}
|
includes/libs/iCal/lib/iCalBase.class.php
ADDED
@@ -0,0 +1,427 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* iCalcreator base class
|
31 |
+
*
|
32 |
+
* properties and functions shared by vcalendar and calendarComponents
|
33 |
+
*
|
34 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
35 |
+
* @since 2.21.11 - 2015-03-31
|
36 |
+
*/
|
37 |
+
abstract class iCalBase {
|
38 |
+
/**
|
39 |
+
* @var array component property X-property value
|
40 |
+
* @access protected
|
41 |
+
*/
|
42 |
+
protected $xprop;
|
43 |
+
/** @var array container for sub-components */
|
44 |
+
public $components;
|
45 |
+
/** @var array $unparsed calendar/components in 'raw' text... */
|
46 |
+
public $unparsed;
|
47 |
+
/**
|
48 |
+
* @var bool $allowEmpty config variable
|
49 |
+
* @var string $language config variable
|
50 |
+
* @var string $nl config variable
|
51 |
+
* @var string $unique_id config variable
|
52 |
+
* @var string $format config variable
|
53 |
+
* @var string $dtzid config variable
|
54 |
+
* @access protected
|
55 |
+
*/
|
56 |
+
protected $allowEmpty;
|
57 |
+
protected $language;
|
58 |
+
protected $nl;
|
59 |
+
protected $unique_id;
|
60 |
+
protected $format;
|
61 |
+
protected $dtzid;
|
62 |
+
/**
|
63 |
+
* @var string $componentStart1 valendar/component internal variable
|
64 |
+
* @var string $componentStart2 valendar/component internal variable
|
65 |
+
* @var string $componentEnd1 valendar/component internal variable
|
66 |
+
* @var string $componentEnd2 valendar/component internal variable
|
67 |
+
* @var string $elementStart1 valendar/component internal variable
|
68 |
+
* @var string $elementStart2 valendar/component internal variable
|
69 |
+
* @var string $elementEnd1 valendar/component internal variable
|
70 |
+
* @var string $elementEnd2 valendar/component internal variable
|
71 |
+
* @var string $intAttrDelimiter valendar/component internal variable
|
72 |
+
* @var string $attributeDelimiter valendar/component internal variable
|
73 |
+
* @var string $valueInit valendar/component internal variable
|
74 |
+
* @access protected
|
75 |
+
*/
|
76 |
+
protected $componentStart1;
|
77 |
+
protected $componentStart2;
|
78 |
+
protected $componentEnd1;
|
79 |
+
protected $componentEnd2;
|
80 |
+
protected $elementStart1;
|
81 |
+
protected $elementStart2;
|
82 |
+
protected $elementEnd1;
|
83 |
+
protected $elementEnd2;
|
84 |
+
protected $intAttrDelimiter;
|
85 |
+
protected $attributeDelimiter;
|
86 |
+
protected $valueInit;
|
87 |
+
/**
|
88 |
+
* @var array $xcaldecl xCal declaration container
|
89 |
+
* @access protected
|
90 |
+
*/
|
91 |
+
protected $xcaldecl;
|
92 |
+
/**
|
93 |
+
* Property Name: x-prop
|
94 |
+
*/
|
95 |
+
/**
|
96 |
+
* creates formatted output for calendar/component property x-prop
|
97 |
+
*
|
98 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
99 |
+
* @since 2.21.11 - 2015-03-31
|
100 |
+
* @uses iCalBase::$xprop
|
101 |
+
* @uses vcalendar::getConfig()
|
102 |
+
* @uses calendarComponent::getConfig()
|
103 |
+
* @uses iCalBase::_createElement()
|
104 |
+
* @uses iCalBase::_createParams()
|
105 |
+
* @uses iCalUtilityFunctions::_strrep()
|
106 |
+
* @uses iCalBase::$format
|
107 |
+
* @uses iCalBase::$nl
|
108 |
+
* @return string
|
109 |
+
*/
|
110 |
+
public function createXprop() {
|
111 |
+
if( empty( $this->xprop ) || !is_array( $this->xprop )) return FALSE;
|
112 |
+
$output = null;
|
113 |
+
foreach( $this->xprop as $label => $xpropPart ) {
|
114 |
+
if( ! isset( $xpropPart['value']) || ( empty( $xpropPart['value'] ) && !is_numeric( $xpropPart['value'] ))) {
|
115 |
+
if( $this->getConfig( 'allowEmpty' ))
|
116 |
+
$output .= $this->_createElement( $label );
|
117 |
+
continue;
|
118 |
+
}
|
119 |
+
$attributes = $this->_createParams( $xpropPart['params'], array( 'LANGUAGE' ));
|
120 |
+
if( is_array( $xpropPart['value'] )) {
|
121 |
+
foreach( $xpropPart['value'] as $pix => $theXpart )
|
122 |
+
$xpropPart['value'][$pix] = iCalUtilityFunctions::_strrep( $theXpart, $this->format, $this->nl );
|
123 |
+
$xpropPart['value'] = implode( ',', $xpropPart['value'] );
|
124 |
+
}
|
125 |
+
else
|
126 |
+
$xpropPart['value'] = iCalUtilityFunctions::_strrep( $xpropPart['value'], $this->format, $this->nl );
|
127 |
+
$output .= $this->_createElement( $label, $attributes, $xpropPart['value'] );
|
128 |
+
}
|
129 |
+
return $output;
|
130 |
+
}
|
131 |
+
/**
|
132 |
+
* set calendar property x-prop
|
133 |
+
*
|
134 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
135 |
+
* @since 2.21.11 - 2015-03-31
|
136 |
+
* @param string $label
|
137 |
+
* @param string $value
|
138 |
+
* @param array $params optional
|
139 |
+
* @uses vcalendar::getConfig()
|
140 |
+
* @uses iCalUtilityFunctions::_setParams()
|
141 |
+
* @uses iCalBase::$xprop
|
142 |
+
* @return bool
|
143 |
+
*/
|
144 |
+
public function setXprop( $label, $value, $params=FALSE ) {
|
145 |
+
if( empty( $label ))
|
146 |
+
return FALSE;
|
147 |
+
$label = strtoupper( $label );
|
148 |
+
if( 'X-' != substr( $label, 0, 2 ))
|
149 |
+
return FALSE;
|
150 |
+
if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = ''; else return FALSE;
|
151 |
+
$xprop = array( 'value' => $value );
|
152 |
+
$xprop['params'] = iCalUtilityFunctions::_setParams( $params );
|
153 |
+
if( ! is_array( $this->xprop ))
|
154 |
+
$this->xprop = array();
|
155 |
+
$this->xprop[$label] = $xprop;
|
156 |
+
return TRUE;
|
157 |
+
}
|
158 |
+
/**
|
159 |
+
* create element format parts
|
160 |
+
*
|
161 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
162 |
+
* @since 2.21.11 - 2015-03-31
|
163 |
+
* @uses iCalBase::$format
|
164 |
+
* @uses iCalBase::$objName
|
165 |
+
* @uses iCalBase::$componentStart1
|
166 |
+
* @uses iCalBase::$elementStart1
|
167 |
+
* @uses iCalBase::$componentStart2
|
168 |
+
* @uses iCalBase::$elementStart2
|
169 |
+
* @uses iCalBase::$componentEnd1
|
170 |
+
* @uses iCalBase::$elementEnd1
|
171 |
+
* @uses iCalBase::$componentEnd2
|
172 |
+
* @uses iCalBase::$elementEnd2
|
173 |
+
* @uses iCalBase::$nl;
|
174 |
+
* @uses iCalBase::$intAttrDelimiter
|
175 |
+
* @uses iCalBase::$attributeDelimiter
|
176 |
+
* @uses iCalBase::$valueInit
|
177 |
+
* @return bool
|
178 |
+
*/
|
179 |
+
function _createFormat() {
|
180 |
+
switch( $this->format ) {
|
181 |
+
case 'xcal':
|
182 |
+
$this->componentStart1 = $this->elementStart1 = '<';
|
183 |
+
$this->componentStart2 = $this->elementStart2 = '>';
|
184 |
+
$this->componentEnd1 = $this->elementEnd1 = '</';
|
185 |
+
$this->componentEnd2 = $this->elementEnd2 = '>'.$this->nl;
|
186 |
+
$this->intAttrDelimiter = '<!-- -->';
|
187 |
+
$this->attributeDelimiter = $this->nl;
|
188 |
+
$this->valueInit = null;
|
189 |
+
break;
|
190 |
+
default:
|
191 |
+
$this->componentStart1 = 'BEGIN:';
|
192 |
+
$this->componentStart2 = null;
|
193 |
+
$this->componentEnd1 = 'END:';
|
194 |
+
$this->componentEnd2 = $this->nl;
|
195 |
+
$this->elementStart1 = null;
|
196 |
+
$this->elementStart2 = null;
|
197 |
+
$this->elementEnd1 = null;
|
198 |
+
$this->elementEnd2 = $this->nl;
|
199 |
+
$this->intAttrDelimiter = '<!-- -->';
|
200 |
+
$this->attributeDelimiter = ';';
|
201 |
+
$this->valueInit = ':';
|
202 |
+
break;
|
203 |
+
}
|
204 |
+
return TRUE;
|
205 |
+
}
|
206 |
+
/**
|
207 |
+
* creates formatted output for calendar component property
|
208 |
+
*
|
209 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
210 |
+
* @since 2.21.11 - 2015-03-31
|
211 |
+
* @param string $label property name
|
212 |
+
* @param string $attributes property attributes
|
213 |
+
* @param string $content property content (optional)
|
214 |
+
* @uses iCalBase::$format
|
215 |
+
* @uses iCalBase::$elementStart1
|
216 |
+
* @uses iCalBase::$xcaldecl
|
217 |
+
* @uses iCalBase::$intAttrDelimiter
|
218 |
+
* @uses iCalBase::$attributeDelimiter
|
219 |
+
* @uses iCalBase::_createElement()
|
220 |
+
* @uses iCalBase::$elementStart2
|
221 |
+
* @uses iCalBase::$nl
|
222 |
+
* @uses iCalBase::$valueInit
|
223 |
+
* @uses iCalUtilityFunctions::_size75()
|
224 |
+
* @uses iCalBase::$elementEnd1
|
225 |
+
* @uses iCalBase::$elementEnd2
|
226 |
+
* @access protected
|
227 |
+
* @return string
|
228 |
+
*/
|
229 |
+
protected function _createElement( $label, $attributes=null, $content=FALSE ) {
|
230 |
+
switch( $this->format ) {
|
231 |
+
case 'xcal':
|
232 |
+
$label = strtolower( $label );
|
233 |
+
break;
|
234 |
+
default:
|
235 |
+
$label = strtoupper( $label );
|
236 |
+
break;
|
237 |
+
}
|
238 |
+
$output = $this->elementStart1.$label;
|
239 |
+
$categoriesAttrLang = null;
|
240 |
+
$attachInlineBinary = FALSE;
|
241 |
+
$attachfmttype = null;
|
242 |
+
if (( 'xcal' == $this->format) && ( 'x-' == substr( $label, 0, 2 ))) {
|
243 |
+
$this->xcaldecl[] = array( 'xmldecl' => 'ELEMENT'
|
244 |
+
, 'ref' => $label
|
245 |
+
, 'type2' => '(#PCDATA)' );
|
246 |
+
}
|
247 |
+
if( !empty( $attributes )) {
|
248 |
+
$attributes = trim( $attributes );
|
249 |
+
if ( 'xcal' == $this->format ) {
|
250 |
+
$attributes2 = explode( $this->intAttrDelimiter, $attributes );
|
251 |
+
$attributes = null;
|
252 |
+
foreach( $attributes2 as $aix => $attribute ) {
|
253 |
+
$attrKVarr = explode( '=', $attribute );
|
254 |
+
if( empty( $attrKVarr[0] ))
|
255 |
+
continue;
|
256 |
+
if( !isset( $attrKVarr[1] )) {
|
257 |
+
$attrValue = $attrKVarr[0];
|
258 |
+
$attrKey = $aix;
|
259 |
+
}
|
260 |
+
elseif( 2 == count( $attrKVarr)) {
|
261 |
+
$attrKey = strtolower( $attrKVarr[0] );
|
262 |
+
$attrValue = $attrKVarr[1];
|
263 |
+
}
|
264 |
+
else {
|
265 |
+
$attrKey = strtolower( $attrKVarr[0] );
|
266 |
+
unset( $attrKVarr[0] );
|
267 |
+
$attrValue = implode( '=', $attrKVarr );
|
268 |
+
}
|
269 |
+
if(( 'attach' == $label ) && ( in_array( $attrKey, array( 'fmttype', 'encoding', 'value' )))) {
|
270 |
+
$attachInlineBinary = TRUE;
|
271 |
+
if( 'fmttype' == $attrKey )
|
272 |
+
$attachfmttype = $attrKey.'='.$attrValue;
|
273 |
+
continue;
|
274 |
+
}
|
275 |
+
elseif(( 'categories' == $label ) && ( 'language' == $attrKey ))
|
276 |
+
$categoriesAttrLang = $attrKey.'='.$attrValue;
|
277 |
+
else {
|
278 |
+
$attributes .= ( empty( $attributes )) ? ' ' : $this->attributeDelimiter.' ';
|
279 |
+
$attributes .= ( !empty( $attrKey )) ? $attrKey.'=' : null;
|
280 |
+
if(( '"' == substr( $attrValue, 0, 1 )) && ( '"' == substr( $attrValue, -1 ))) {
|
281 |
+
$attrValue = substr( $attrValue, 1, ( strlen( $attrValue ) - 2 ));
|
282 |
+
$attrValue = str_replace( '"', '', $attrValue );
|
283 |
+
}
|
284 |
+
$attributes .= '"'.htmlspecialchars( $attrValue ).'"';
|
285 |
+
}
|
286 |
+
}
|
287 |
+
}
|
288 |
+
else {
|
289 |
+
$attributes = str_replace( $this->intAttrDelimiter, $this->attributeDelimiter, $attributes );
|
290 |
+
}
|
291 |
+
}
|
292 |
+
if(( 'xcal' == $this->format) &&
|
293 |
+
((( 'attach' == $label ) && !$attachInlineBinary ) || ( in_array( $label, array( 'tzurl', 'url' ))))) {
|
294 |
+
$pos = strrpos( $content, "/" );
|
295 |
+
$docname = ( $pos !== false) ? substr( $content, (1 - strlen( $content ) + $pos )) : $content;
|
296 |
+
$this->xcaldecl[] = array( 'xmldecl' => 'ENTITY'
|
297 |
+
, 'uri' => $docname
|
298 |
+
, 'ref' => 'SYSTEM'
|
299 |
+
, 'external' => $content
|
300 |
+
, 'type' => 'NDATA'
|
301 |
+
, 'type2' => 'BINERY' );
|
302 |
+
$attributes .= ( empty( $attributes )) ? ' ' : $this->attributeDelimiter.' ';
|
303 |
+
$attributes .= 'uri="'.$docname.'"';
|
304 |
+
$content = null;
|
305 |
+
if( 'attach' == $label ) {
|
306 |
+
$attributes = str_replace( $this->attributeDelimiter, $this->intAttrDelimiter, $attributes );
|
307 |
+
$content = $this->nl.$this->_createElement( 'extref', $attributes, null );
|
308 |
+
$attributes = null;
|
309 |
+
}
|
310 |
+
}
|
311 |
+
elseif(( 'xcal' == $this->format) && ( 'attach' == $label ) && $attachInlineBinary ) {
|
312 |
+
$content = $this->nl.$this->_createElement( 'b64bin', $attachfmttype, $content ); // max one attribute
|
313 |
+
}
|
314 |
+
$output .= $attributes;
|
315 |
+
if( !$content && ( '0' != $content )) {
|
316 |
+
switch( $this->format ) {
|
317 |
+
case 'xcal':
|
318 |
+
$output .= ' /';
|
319 |
+
$output .= $this->elementStart2.$this->nl;
|
320 |
+
return $output;
|
321 |
+
break;
|
322 |
+
default:
|
323 |
+
$output .= $this->elementStart2.$this->valueInit;
|
324 |
+
return iCalUtilityFunctions::_size75( $output, $this->nl );
|
325 |
+
break;
|
326 |
+
}
|
327 |
+
}
|
328 |
+
$output .= $this->elementStart2;
|
329 |
+
$output .= $this->valueInit.$content;
|
330 |
+
switch( $this->format ) {
|
331 |
+
case 'xcal':
|
332 |
+
return $output.$this->elementEnd1.$label.$this->elementEnd2;
|
333 |
+
break;
|
334 |
+
default:
|
335 |
+
return iCalUtilityFunctions::_size75( $output, $this->nl );
|
336 |
+
break;
|
337 |
+
}
|
338 |
+
}
|
339 |
+
/**
|
340 |
+
* creates formatted output for calendar component property parameters
|
341 |
+
*
|
342 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
343 |
+
* @since 2.21.11 - 2015-03-31
|
344 |
+
* @param array $params optional
|
345 |
+
* @param array $ctrKeys optional
|
346 |
+
* @uses iCalBase::$intAttrDelimiter
|
347 |
+
* @uses vcalendar::getConfig()
|
348 |
+
* @uses calendarComponent::getConfig()
|
349 |
+
* @access protected
|
350 |
+
* @return string
|
351 |
+
*/
|
352 |
+
protected function _createParams( $params=array(), $ctrKeys=array() ) {
|
353 |
+
if( !is_array( $params ) || empty( $params ))
|
354 |
+
$params = array();
|
355 |
+
$attrLANG = $attr1 = $attr2 = $lang = null;
|
356 |
+
$CNattrKey = ( in_array( 'CN', $ctrKeys )) ? TRUE : FALSE ;
|
357 |
+
$LANGattrKey = ( in_array( 'LANGUAGE', $ctrKeys )) ? TRUE : FALSE ;
|
358 |
+
$CNattrExist = $LANGattrExist = FALSE;
|
359 |
+
$xparams = array();
|
360 |
+
$params = array_change_key_case( $params, CASE_UPPER );
|
361 |
+
foreach( $params as $paramKey => $paramValue ) {
|
362 |
+
if(( FALSE !== strpos( $paramValue, ':' )) ||
|
363 |
+
( FALSE !== strpos( $paramValue, ';' )) ||
|
364 |
+
( FALSE !== strpos( $paramValue, ',' )))
|
365 |
+
$paramValue = '"'.$paramValue.'"';
|
366 |
+
if( ctype_digit( (string) $paramKey )) {
|
367 |
+
$xparams[] = $paramValue;
|
368 |
+
continue;
|
369 |
+
}
|
370 |
+
if( !in_array( $paramKey, array( 'ALTREP', 'CN', 'DIR', 'ENCODING', 'FMTTYPE', 'LANGUAGE', 'RANGE', 'RELTYPE', 'SENT-BY', 'TZID', 'VALUE' )))
|
371 |
+
$xparams[$paramKey] = $paramValue;
|
372 |
+
else
|
373 |
+
$params[$paramKey] = $paramValue;
|
374 |
+
}
|
375 |
+
ksort( $xparams, SORT_STRING );
|
376 |
+
foreach( $xparams as $paramKey => $paramValue ) {
|
377 |
+
if( ctype_digit( (string) $paramKey ))
|
378 |
+
$attr2 .= $this->intAttrDelimiter.$paramValue;
|
379 |
+
else
|
380 |
+
$attr2 .= $this->intAttrDelimiter."$paramKey=$paramValue";
|
381 |
+
}
|
382 |
+
if( isset( $params['FMTTYPE'] ) && !in_array( 'FMTTYPE', $ctrKeys )) {
|
383 |
+
$attr1 .= $this->intAttrDelimiter.'FMTTYPE='.$params['FMTTYPE'].$attr2;
|
384 |
+
$attr2 = null;
|
385 |
+
}
|
386 |
+
if( isset( $params['ENCODING'] ) && !in_array( 'ENCODING', $ctrKeys )) {
|
387 |
+
if( !empty( $attr2 )) {
|
388 |
+
$attr1 .= $attr2;
|
389 |
+
$attr2 = null;
|
390 |
+
}
|
391 |
+
$attr1 .= $this->intAttrDelimiter.'ENCODING='.$params['ENCODING'];
|
392 |
+
}
|
393 |
+
if( isset( $params['VALUE'] ) && !in_array( 'VALUE', $ctrKeys ))
|
394 |
+
$attr1 .= $this->intAttrDelimiter.'VALUE='.$params['VALUE'];
|
395 |
+
if( isset( $params['TZID'] ) && !in_array( 'TZID', $ctrKeys )) {
|
396 |
+
$attr1 .= $this->intAttrDelimiter.'TZID='.$params['TZID'];
|
397 |
+
}
|
398 |
+
if( isset( $params['RANGE'] ) && !in_array( 'RANGE', $ctrKeys ))
|
399 |
+
$attr1 .= $this->intAttrDelimiter.'RANGE='.$params['RANGE'];
|
400 |
+
if( isset( $params['RELTYPE'] ) && !in_array( 'RELTYPE', $ctrKeys ))
|
401 |
+
$attr1 .= $this->intAttrDelimiter.'RELTYPE='.$params['RELTYPE'];
|
402 |
+
if( isset( $params['CN'] ) && $CNattrKey ) {
|
403 |
+
$attr1 = $this->intAttrDelimiter.'CN='.$params['CN'];
|
404 |
+
$CNattrExist = TRUE;
|
405 |
+
}
|
406 |
+
if( isset( $params['DIR'] ) && in_array( 'DIR', $ctrKeys )) {
|
407 |
+
$delim = ( FALSE !== strpos( $params['DIR'], '"' )) ? '' : '"';
|
408 |
+
$attr1 .= $this->intAttrDelimiter.'DIR='.$delim.$params['DIR'].$delim;
|
409 |
+
}
|
410 |
+
if( isset( $params['SENT-BY'] ) && in_array( 'SENT-BY', $ctrKeys ))
|
411 |
+
$attr1 .= $this->intAttrDelimiter.'SENT-BY='.$params['SENT-BY'];
|
412 |
+
if( isset( $params['ALTREP'] ) && in_array( 'ALTREP', $ctrKeys )) {
|
413 |
+
$delim = ( FALSE !== strpos( $params['ALTREP'], '"' )) ? '' : '"';
|
414 |
+
$attr1 .= $this->intAttrDelimiter.'ALTREP='.$delim.$params['ALTREP'].$delim;
|
415 |
+
}
|
416 |
+
if( isset( $params['LANGUAGE'] ) && $LANGattrKey ) {
|
417 |
+
$attrLANG .= $this->intAttrDelimiter.'LANGUAGE='.$params['LANGUAGE'];
|
418 |
+
$LANGattrExist = TRUE;
|
419 |
+
}
|
420 |
+
if( !$LANGattrExist ) {
|
421 |
+
$lang = $this->getConfig( 'language' );
|
422 |
+
if(( $CNattrExist || $LANGattrKey ) && $lang )
|
423 |
+
$attrLANG .= $this->intAttrDelimiter.'LANGUAGE='.$lang;
|
424 |
+
}
|
425 |
+
return $attr1.$attrLANG.$attr2;
|
426 |
+
}
|
427 |
+
}
|
includes/libs/iCal/lib/iCalUtilityFunctions.class.php
ADDED
@@ -0,0 +1,2510 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* A PHP implementation of rfc2445/rfc5545.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* moving all utility (static) functions to a utility class
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.21.11 - 2015-04-03
|
34 |
+
*/
|
35 |
+
class iCalUtilityFunctions {
|
36 |
+
/** @var string tmp line delimiter, used in convEolChar (parse) */
|
37 |
+
private static $baseDelim = null;
|
38 |
+
/** @var array protocol prefix, used in _splitContent() */
|
39 |
+
private static $parValPrefix = array ( 'MStz' => array( 'utc-', 'utc+', 'gmt-', 'gmt+' )
|
40 |
+
, 'Proto3' => array( 'fax:', 'cid:', 'sms:', 'tel:', 'urn:' )
|
41 |
+
, 'Proto4' => array( 'crid:', 'news:', 'pres:' )
|
42 |
+
, 'Proto6' => array( 'mailto:' ));
|
43 |
+
/** @var string output format for geo latitude and longitude (before rtrim) */
|
44 |
+
public static $geoLatFmt = '%09.6f';
|
45 |
+
public static $geoLongFmt = '%8.6f';
|
46 |
+
/** @var array date/datetime formats */
|
47 |
+
public static $fmt = array( 'Ymd' => '%04d%02d%02d',
|
48 |
+
'His' => '%02d%02d%02d',
|
49 |
+
'dayOfDays' => 'day %d of %d',
|
50 |
+
'durDHis' => '%a days, %h hours, %i min, %s sec',
|
51 |
+
'Ymd2' => 'Y-m-d',
|
52 |
+
'YmdHis2' => 'Y-m-d H:i:s',
|
53 |
+
'YmdHis2e' => 'Y-m-d H:i:s e',
|
54 |
+
'YmdHis3' => 'Y-m-d-H-i-s',
|
55 |
+
'YmdHise' => '%04d-%02d-%02d %02d:%02d:%02d %s',
|
56 |
+
'YmdTHisO' => 'Y-m-d\TH:i:s O',
|
57 |
+
'dateKey' => '%04d%02d%02d%02d%02d%02d000',
|
58 |
+
);
|
59 |
+
/** @var array component property UID value */
|
60 |
+
public static $vComps = array( 'vevent', 'vtodo', 'vjournal', 'vfreebusy' );
|
61 |
+
public static $mComps = array( 'vevent', 'vtodo', 'vjournal', 'vfreebusy', 'valarm', 'vtimezone' );
|
62 |
+
public static $miscComps = array( 'valarm', 'vtimezone', 'standard', 'daylight' );
|
63 |
+
public static $tzComps = array( 'vtimezone', 'standard', 'daylight' );
|
64 |
+
public static $allComps = array( 'vtimezone', 'standard', 'daylight', 'vevent', 'vtodo', 'vjournal', 'vfreebusy', 'valarm' );
|
65 |
+
/** @var array component property collections */
|
66 |
+
public static $mProps1 = array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'RELATED-TO', 'RESOURCES' );
|
67 |
+
public static $mProps2 = array( 'ATTACH', 'ATTENDEE', 'CATEGORIES', 'COMMENT', 'CONTACT', 'DESCRIPTION', 'EXDATE', 'EXRULE',
|
68 |
+
'FREEBUSY', 'RDATE', 'RELATED-TO', 'RESOURCES', 'RRULE', 'REQUEST-STATUS', 'TZNAME', 'X-PROP' );
|
69 |
+
public static $dateProps = array( 'DTSTART', 'DTEND', 'DUE', 'CREATED', 'COMPLETED', 'DTSTAMP', 'LAST-MODIFIED', 'RECURRENCE-ID' );
|
70 |
+
public static $otherProps = array( 'ATTENDEE', 'CATEGORIES', 'CONTACT', 'LOCATION', 'ORGANIZER', 'PRIORITY', 'RELATED-TO', 'RESOURCES', 'STATUS', 'SUMMARY', 'UID', 'URL' );
|
71 |
+
/** @var object Store the single instance of iCalUtilityFunctions */
|
72 |
+
private static $m_pInstance;
|
73 |
+
/**
|
74 |
+
* Private constructor to limit object instantiation to within the class
|
75 |
+
*
|
76 |
+
* @access private
|
77 |
+
*/
|
78 |
+
private function __construct() {
|
79 |
+
$m_pInstance = FALSE;
|
80 |
+
}
|
81 |
+
/** @var array component property UID value */
|
82 |
+
/**
|
83 |
+
* Getter method for creating/returning the single instance of this class
|
84 |
+
*
|
85 |
+
* @uses iCalUtilityFunctions::$m_pInstance
|
86 |
+
*/
|
87 |
+
public static function getInstance() {
|
88 |
+
if (!self::$m_pInstance)
|
89 |
+
self::$m_pInstance = new iCalUtilityFunctions();
|
90 |
+
return self::$m_pInstance;
|
91 |
+
}
|
92 |
+
/**
|
93 |
+
* ensures internal date-time/date format (keyed array) for an input date-time/date array (keyed or unkeyed)
|
94 |
+
*
|
95 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
96 |
+
* @since 2.16.24 - 2013-06-26
|
97 |
+
* @param array $datetime
|
98 |
+
* @param int $parno optional, default FALSE
|
99 |
+
* @return array
|
100 |
+
*/
|
101 |
+
public static function _chkDateArr( $datetime, $parno=FALSE ) {
|
102 |
+
$output = array();
|
103 |
+
if(( !$parno || ( 6 <= $parno )) && isset( $datetime[3] ) && !isset( $datetime[4] )) { // Y-m-d with tz
|
104 |
+
$temp = $datetime[3];
|
105 |
+
$datetime[3] = $datetime[4] = $datetime[5] = 0;
|
106 |
+
$datetime[6] = $temp;
|
107 |
+
}
|
108 |
+
foreach( $datetime as $dateKey => $datePart ) {
|
109 |
+
switch ( $dateKey ) {
|
110 |
+
case '0': case 'year': $output['year'] = $datePart; break;
|
111 |
+
case '1': case 'month': $output['month'] = $datePart; break;
|
112 |
+
case '2': case 'day': $output['day'] = $datePart; break;
|
113 |
+
}
|
114 |
+
if( 3 != $parno ) {
|
115 |
+
switch ( $dateKey ) {
|
116 |
+
case '0':
|
117 |
+
case '1':
|
118 |
+
case '2': break;
|
119 |
+
case '3': case 'hour': $output['hour'] = $datePart; break;
|
120 |
+
case '4': case 'min' : $output['min'] = $datePart; break;
|
121 |
+
case '5': case 'sec' : $output['sec'] = $datePart; break;
|
122 |
+
case '6': case 'tz' : $output['tz'] = $datePart; break;
|
123 |
+
}
|
124 |
+
}
|
125 |
+
}
|
126 |
+
if( 3 != $parno ) {
|
127 |
+
if( !isset( $output['hour'] )) $output['hour'] = 0;
|
128 |
+
if( !isset( $output['min'] )) $output['min'] = 0;
|
129 |
+
if( !isset( $output['sec'] )) $output['sec'] = 0;
|
130 |
+
if( isset( $output['tz'] ) &&
|
131 |
+
(( '+0000' == $output['tz'] ) || ( '-0000' == $output['tz'] ) || ( '+000000' == $output['tz'] ) || ( '-000000' == $output['tz'] )))
|
132 |
+
$output['tz'] = 'Z';
|
133 |
+
}
|
134 |
+
return $output;
|
135 |
+
}
|
136 |
+
/**
|
137 |
+
* check date(-time) and params arrays for an opt. timezone and if it is a DATE-TIME or DATE (updates $parno and params)
|
138 |
+
*
|
139 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
140 |
+
* @since 2.10.30 - 2012-01-16
|
141 |
+
* @param array $theDate date to check
|
142 |
+
* @param int $parno no of date parts (i.e. year, month.. .)
|
143 |
+
* @param array $params property parameters
|
144 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
145 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
146 |
+
* @return void
|
147 |
+
*/
|
148 |
+
public static function _chkdatecfg( $theDate, & $parno, & $params ) {
|
149 |
+
if( isset( $params['TZID'] ))
|
150 |
+
$parno = 6;
|
151 |
+
elseif( isset( $params['VALUE'] ) && ( 'DATE' == $params['VALUE'] ))
|
152 |
+
$parno = 3;
|
153 |
+
else {
|
154 |
+
if( isset( $params['VALUE'] ) && ( 'PERIOD' == $params['VALUE'] ))
|
155 |
+
$parno = 7;
|
156 |
+
if( is_array( $theDate )) {
|
157 |
+
if( isset( $theDate['timestamp'] ))
|
158 |
+
$tzid = ( isset( $theDate['tz'] )) ? $theDate['tz'] : null;
|
159 |
+
else
|
160 |
+
$tzid = ( isset( $theDate['tz'] )) ? $theDate['tz'] : ( 7 == count( $theDate )) ? end( $theDate ) : null;
|
161 |
+
if( !empty( $tzid )) {
|
162 |
+
$parno = 7;
|
163 |
+
if( !iCalUtilityFunctions::_isOffset( $tzid ))
|
164 |
+
$params['TZID'] = '"' . $tzid . '"'; // save only timezone
|
165 |
+
}
|
166 |
+
elseif( !$parno && ( 3 == count( $theDate )) &&
|
167 |
+
( isset( $params['VALUE'] ) && ( 'DATE' == $params['VALUE'] )))
|
168 |
+
$parno = 3;
|
169 |
+
else
|
170 |
+
$parno = 6;
|
171 |
+
}
|
172 |
+
else { // string
|
173 |
+
$date = trim( $theDate );
|
174 |
+
if( 'Z' == substr( $date, -1 ))
|
175 |
+
$parno = 7; // UTC DATE-TIME
|
176 |
+
elseif((( 8 == strlen( $date ) && ctype_digit( $date )) || ( 11 >= strlen( $date ))) &&
|
177 |
+
( !isset( $params['VALUE'] ) || !in_array( $params['VALUE'], array( 'DATE-TIME', 'PERIOD' ))))
|
178 |
+
$parno = 3; // DATE
|
179 |
+
$date = iCalUtilityFunctions::_strdate2date( $date, $parno );
|
180 |
+
unset( $date['unparsedtext'] );
|
181 |
+
if( !empty( $date['tz'] )) {
|
182 |
+
$parno = 7;
|
183 |
+
if( !iCalUtilityFunctions::_isOffset( $date['tz'] ))
|
184 |
+
$params['TZID'] = $date['tz']; // save only timezone
|
185 |
+
}
|
186 |
+
elseif( empty( $parno ))
|
187 |
+
$parno = 6;
|
188 |
+
}
|
189 |
+
if( isset( $params['TZID'] ))
|
190 |
+
$parno = 6;
|
191 |
+
}
|
192 |
+
}
|
193 |
+
/**
|
194 |
+
* vcalendar sort callback function
|
195 |
+
*
|
196 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
197 |
+
* @since 2.16.2 - 2012-12-17
|
198 |
+
* @param array $a
|
199 |
+
* @param array $b
|
200 |
+
* @uses calendarComponent::$objName
|
201 |
+
* @return int
|
202 |
+
*/
|
203 |
+
public static function _cmpfcn( $a, $b ) {
|
204 |
+
if( empty( $a )) return -1;
|
205 |
+
if( empty( $b )) return 1;
|
206 |
+
if( 'vtimezone' == $a->objName ) {
|
207 |
+
if( 'vtimezone' != $b->objName ) return -1;
|
208 |
+
elseif( $a->srtk[0] <= $b->srtk[0] ) return -1;
|
209 |
+
else return 1;
|
210 |
+
}
|
211 |
+
elseif( 'vtimezone' == $b->objName ) return 1;
|
212 |
+
$sortkeys = array( 'year', 'month', 'day', 'hour', 'min', 'sec' );
|
213 |
+
for( $k = 0; $k < 4 ; $k++ ) {
|
214 |
+
if( empty( $a->srtk[$k] )) return -1;
|
215 |
+
elseif( empty( $b->srtk[$k] )) return 1;
|
216 |
+
if( is_array( $a->srtk[$k] )) {
|
217 |
+
if( is_array( $b->srtk[$k] )) {
|
218 |
+
foreach( $sortkeys as $key ) {
|
219 |
+
if ( !isset( $a->srtk[$k][$key] )) return -1;
|
220 |
+
elseif( !isset( $b->srtk[$k][$key] )) return 1;
|
221 |
+
if ( empty( $a->srtk[$k][$key] )) return -1;
|
222 |
+
elseif( empty( $b->srtk[$k][$key] )) return 1;
|
223 |
+
if ( $a->srtk[$k][$key] == $b->srtk[$k][$key])
|
224 |
+
continue;
|
225 |
+
if (( (int) $a->srtk[$k][$key] ) < ((int) $b->srtk[$k][$key] ))
|
226 |
+
return -1;
|
227 |
+
elseif(( (int) $a->srtk[$k][$key] ) > ((int) $b->srtk[$k][$key] ))
|
228 |
+
return 1;
|
229 |
+
}
|
230 |
+
}
|
231 |
+
else return -1;
|
232 |
+
}
|
233 |
+
elseif( is_array( $b->srtk[$k] )) return 1;
|
234 |
+
elseif( $a->srtk[$k] < $b->srtk[$k] ) return -1;
|
235 |
+
elseif( $a->srtk[$k] > $b->srtk[$k] ) return 1;
|
236 |
+
}
|
237 |
+
return 0;
|
238 |
+
}
|
239 |
+
/**
|
240 |
+
* byte oriented line folding fix
|
241 |
+
*
|
242 |
+
* remove any line-endings that may include spaces or tabs
|
243 |
+
* and convert all line endings (iCal default '\r\n'),
|
244 |
+
* takes care of '\r\n', '\r' and '\n' and mixed '\r\n'+'\r', '\r\n'+'\n'
|
245 |
+
*
|
246 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
247 |
+
* @since 2.18.16 - 2014-04-04
|
248 |
+
* @param string $text
|
249 |
+
* @param string $nl
|
250 |
+
* @uses iCalUtilityFunctions::$baseDelim
|
251 |
+
* @return string
|
252 |
+
*/
|
253 |
+
public static function convEolChar( & $text, $nl ) {
|
254 |
+
/* fix dummy line separator */
|
255 |
+
if( empty( iCalUtilityFunctions::$baseDelim )) {
|
256 |
+
iCalUtilityFunctions::$baseDelim = substr( microtime(), 2, 4 );
|
257 |
+
$base = 'aAbB!cCdD"eEfF#gGhHiIjJ%kKlL&mMnN/oOpP(rRsS)tTuU=vVxX?uUvV*wWzZ-1234_5678|90';
|
258 |
+
$len = strlen( $base ) - 1;
|
259 |
+
for( $p = 0; $p < 6; $p++ )
|
260 |
+
iCalUtilityFunctions::$baseDelim .= $base{mt_rand( 0, $len )};
|
261 |
+
}
|
262 |
+
/* fix eol chars */
|
263 |
+
$text = str_replace( array( "\r\n", "\n\r", "\n", "\r" ), iCalUtilityFunctions::$baseDelim, $text );
|
264 |
+
/* fix empty lines */
|
265 |
+
$text = str_replace( iCalUtilityFunctions::$baseDelim.iCalUtilityFunctions::$baseDelim, iCalUtilityFunctions::$baseDelim.str_pad( '', 75 ).iCalUtilityFunctions::$baseDelim, $text );
|
266 |
+
/* fix line folding */
|
267 |
+
$text = str_replace( iCalUtilityFunctions::$baseDelim, $nl, $text );
|
268 |
+
$text = str_replace( array( $nl.' ', $nl."\t" ), '', $text );
|
269 |
+
/* split in component/property lines */
|
270 |
+
$text = explode( $nl, $text );
|
271 |
+
return $text;
|
272 |
+
}
|
273 |
+
/**
|
274 |
+
* create a calendar timezone and standard/daylight components
|
275 |
+
*
|
276 |
+
* Result when 'Europe/Stockholm' and no from/to arguments is used as timezone:
|
277 |
+
*
|
278 |
+
* BEGIN:VTIMEZONE
|
279 |
+
* TZID:Europe/Stockholm
|
280 |
+
* BEGIN:STANDARD
|
281 |
+
* DTSTART:20101031T020000
|
282 |
+
* TZOFFSETFROM:+0200
|
283 |
+
* TZOFFSETTO:+0100
|
284 |
+
* TZNAME:CET
|
285 |
+
* END:STANDARD
|
286 |
+
* BEGIN:DAYLIGHT
|
287 |
+
* DTSTART:20100328T030000
|
288 |
+
* TZOFFSETFROM:+0100
|
289 |
+
* TZOFFSETTO:+0200
|
290 |
+
* TZNAME:CEST
|
291 |
+
* END:DAYLIGHT
|
292 |
+
* END:VTIMEZONE
|
293 |
+
*
|
294 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
295 |
+
* @since 2.21.11 - 2015-04-03
|
296 |
+
* Generates components for all transitions in a date range, based on contribution by Yitzchok Lavi <icalcreator@onebigsystem.com>
|
297 |
+
* Additional changes jpirkey
|
298 |
+
* @param object $calendar iCalcreator calendar instance
|
299 |
+
* @param string $timezone PHP5 (DateTimeZone) valid timezone
|
300 |
+
* @param array $xProp *[x-propName => x-propValue], optional
|
301 |
+
* @param int $from unix timestamp
|
302 |
+
* @param int $to unix timestamp
|
303 |
+
* @uses vcalendar::getProperty()
|
304 |
+
* @uses iCalUtilityFunctions::$fmt
|
305 |
+
* @uses vcalendar::newComponent()
|
306 |
+
* @uses calendarComponent::setproperty()
|
307 |
+
* @uses iCalUtilityFunctions::offsetSec2His()
|
308 |
+
* @return bool
|
309 |
+
*/
|
310 |
+
public static function createTimezone( & $calendar, $timezone, $xProp=array(), $from=null, $to=null ) {
|
311 |
+
var_dump($timezone);
|
312 |
+
if( empty( $timezone ))
|
313 |
+
return FALSE;
|
314 |
+
if( !empty( $from ) && !is_int( $from ))
|
315 |
+
return FALSE;
|
316 |
+
if( !empty( $to ) && !is_int( $to ))
|
317 |
+
return FALSE;
|
318 |
+
try {
|
319 |
+
$dtz = new DateTimeZone( $timezone );
|
320 |
+
$transitions = $dtz->getTransitions();
|
321 |
+
$utcTz = new DateTimeZone( 'UTC' );
|
322 |
+
}
|
323 |
+
catch( Exception $e ) { return FALSE; }
|
324 |
+
|
325 |
+
var_dump('dasdsadsa');
|
326 |
+
if( empty( $from ) || empty( $to )) {
|
327 |
+
$dates = array_keys( $calendar->getProperty( 'dtstart' ));
|
328 |
+
if( empty( $dates ))
|
329 |
+
$dates = array( date( 'Ymd' ));
|
330 |
+
}
|
331 |
+
if( ! empty( $from )) {
|
332 |
+
$dateFrom = new DateTime( "@$from" ); // set lowest date (UTC)
|
333 |
+
$dateFrom->modify( '-7 month' ); // set $dateFrom to seven month before the lowest date
|
334 |
+
}
|
335 |
+
else {
|
336 |
+
$from = reset( $dates ); // set lowest date to the lowest dtstart date
|
337 |
+
$dateFrom = new DateTime( $from.'T000000', $dtz );
|
338 |
+
$dateFrom->modify( '-7 month' ); // set $dateFrom to seven month before the lowest date
|
339 |
+
$dateFrom->setTimezone( $utcTz ); // convert local date to UTC
|
340 |
+
}
|
341 |
+
$dateFromYmd = $dateFrom->format( iCalUtilityFunctions::$fmt['Ymd2'] );
|
342 |
+
if( ! empty( $to ))
|
343 |
+
$dateTo = new DateTime( "@$to" ); // set end date (UTC)
|
344 |
+
else {
|
345 |
+
$to = end( $dates ); // set highest date to the highest dtstart date
|
346 |
+
$dateTo = new DateTime( $to.'T235959', $dtz );
|
347 |
+
$dateTo->modify( '+18 month' ); // set $dateTo to 18 month after the highest date
|
348 |
+
$dateTo->setTimezone( $utcTz ); // convert local date to UTC
|
349 |
+
}
|
350 |
+
$dateToYmd = $dateTo->format( iCalUtilityFunctions::$fmt['Ymd2'] );
|
351 |
+
unset( $dtz );
|
352 |
+
$transTemp = array();
|
353 |
+
$prevOffsetfrom = 0;
|
354 |
+
$stdIx = $dlghtIx = null;
|
355 |
+
$prevTrans = FALSE;
|
356 |
+
foreach( $transitions as $tix => $trans ) { // all transitions in date-time order!!
|
357 |
+
$date = new DateTime( "@{$trans['ts']}" ); // set transition date (UTC)
|
358 |
+
$transDateYmd = $date->format( iCalUtilityFunctions::$fmt['Ymd2'] );
|
359 |
+
if ( $transDateYmd < $dateFromYmd ) {
|
360 |
+
$prevOffsetfrom = $trans['offset']; // previous trans offset will be 'next' trans offsetFrom
|
361 |
+
$prevTrans = $trans; // save it in case we don't find any that match
|
362 |
+
$prevTrans['offsetfrom'] = ( 0 < $tix ) ? $transitions[$tix-1]['offset'] : 0;
|
363 |
+
continue;
|
364 |
+
}
|
365 |
+
if( $transDateYmd > $dateToYmd )
|
366 |
+
break; // loop always (?) breaks here
|
367 |
+
if( !empty( $prevOffsetfrom ) || ( 0 == $prevOffsetfrom )) {
|
368 |
+
$trans['offsetfrom'] = $prevOffsetfrom; // i.e. set previous offsetto as offsetFrom
|
369 |
+
$date->modify( $trans['offsetfrom'].'seconds' ); // convert utc date to local date
|
370 |
+
$d = $date->format( iCalUtilityFunctions::$fmt['YmdHis3'] );
|
371 |
+
$d = explode( '-', $d ); // set date to array to ease up dtstart and (opt) rdate setting
|
372 |
+
$trans['time'] = array( 'year' => (int) $d[0], 'month' => (int) $d[1], 'day' => (int) $d[2], 'hour' => (int) $d[3], 'min' => (int) $d[4], 'sec' => (int) $d[5] );
|
373 |
+
}
|
374 |
+
$prevOffsetfrom = $trans['offset'];
|
375 |
+
if( TRUE !== $trans['isdst'] ) { // standard timezone
|
376 |
+
if( !empty( $stdIx ) && isset( $transTemp[$stdIx]['offsetfrom'] ) && // check for any repeating rdate's (in order)
|
377 |
+
( $transTemp[$stdIx]['abbr'] == $trans['abbr'] ) &&
|
378 |
+
( $transTemp[$stdIx]['offsetfrom'] == $trans['offsetfrom'] ) &&
|
379 |
+
( $transTemp[$stdIx]['offset'] == $trans['offset'] )) {
|
380 |
+
$transTemp[$stdIx]['rdate'][] = $trans['time'];
|
381 |
+
continue;
|
382 |
+
}
|
383 |
+
$stdIx = $tix;
|
384 |
+
} // end standard timezone
|
385 |
+
else { // daylight timezone
|
386 |
+
if( !empty( $dlghtIx ) && isset( $transTemp[$dlghtIx]['offsetfrom'] ) && // check for any repeating rdate's (in order)
|
387 |
+
( $transTemp[$dlghtIx]['abbr'] == $trans['abbr'] ) &&
|
388 |
+
( $transTemp[$dlghtIx]['offsetfrom'] == $trans['offsetfrom'] ) &&
|
389 |
+
( $transTemp[$dlghtIx]['offset'] == $trans['offset'] )) {
|
390 |
+
$transTemp[$dlghtIx]['rdate'][] = $trans['time'];
|
391 |
+
continue;
|
392 |
+
}
|
393 |
+
$dlghtIx = $tix;
|
394 |
+
} // end daylight timezone
|
395 |
+
$transTemp[$tix] = $trans;
|
396 |
+
} // end foreach( $transitions as $tix => $trans )
|
397 |
+
$tz = $calendar->newComponent( 'vtimezone' );
|
398 |
+
$tz->setproperty( 'tzid', $timezone );
|
399 |
+
if( !empty( $xProp )) {
|
400 |
+
foreach( $xProp as $xPropName => $xPropValue )
|
401 |
+
if( 'x-' == strtolower( substr( $xPropName, 0, 2 )))
|
402 |
+
$tz->setproperty( $xPropName, $xPropValue );
|
403 |
+
}
|
404 |
+
if( empty( $transTemp )) { // if no match found
|
405 |
+
if( $prevTrans ) { // then we use the last transition (before startdate) for the tz info
|
406 |
+
$date = new DateTime( "@{$prevTrans['ts']}" );// set transition date (UTC)
|
407 |
+
$date->modify( $prevTrans['offsetfrom'].'seconds' ); // convert utc date to local date
|
408 |
+
$d = $date->format( iCalUtilityFunctions::$fmt['YmdHis3'] );
|
409 |
+
$d = explode( '-', $d ); // set date to array to ease up dtstart setting
|
410 |
+
$prevTrans['time'] = array( 'year' => (int) $d[0], 'month' => (int) $d[1], 'day' => (int) $d[2], 'hour' => (int) $d[3], 'min' => (int) $d[4], 'sec' => (int) $d[5] );
|
411 |
+
$transTemp[0] = $prevTrans;
|
412 |
+
}
|
413 |
+
else { // or we use the timezone identifier to BUILD the standard tz info (?)
|
414 |
+
$date = new DateTime( 'now', new DateTimeZone( $timezone ));
|
415 |
+
$transTemp[0] = array( 'time' => $date->format( iCalUtilityFunctions::$fmt['YmdTHisO'] ),
|
416 |
+
'offset' => $date->format( 'Z' ),
|
417 |
+
'offsetfrom' => $date->format( 'Z' ),
|
418 |
+
'isdst' => FALSE );
|
419 |
+
}
|
420 |
+
}
|
421 |
+
unset( $transitions, $date, $prevTrans );
|
422 |
+
foreach( $transTemp as $tix => $trans ) { // create standard/daylight subcomponents
|
423 |
+
$type = ( TRUE !== $trans['isdst'] ) ? 'standard' : 'daylight';
|
424 |
+
$scomp = $tz->newComponent( $type );
|
425 |
+
$scomp->setProperty( 'dtstart', $trans['time'] );
|
426 |
+
// $scomp->setProperty( 'x-utc-timestamp', $tix.' : '.$trans['ts'] ); // test ###
|
427 |
+
if( !empty( $trans['abbr'] ))
|
428 |
+
$scomp->setProperty( 'tzname', $trans['abbr'] );
|
429 |
+
if( isset( $trans['offsetfrom'] ))
|
430 |
+
$scomp->setProperty( 'tzoffsetfrom', iCalUtilityFunctions::offsetSec2His( $trans['offsetfrom'] ));
|
431 |
+
$scomp->setProperty( 'tzoffsetto', iCalUtilityFunctions::offsetSec2His( $trans['offset'] ));
|
432 |
+
if( isset( $trans['rdate'] ))
|
433 |
+
$scomp->setProperty( 'RDATE', $trans['rdate'] );
|
434 |
+
}
|
435 |
+
return TRUE;
|
436 |
+
}
|
437 |
+
/**
|
438 |
+
* creates formatted output for calendar component property data value type date/date-time
|
439 |
+
*
|
440 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
441 |
+
* @since 2.21.11 - 2015-03-10
|
442 |
+
* @param array $datetime
|
443 |
+
* @param int $parno optional, default 6
|
444 |
+
* @uses iCalUtilityFunctions::$fmt
|
445 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
446 |
+
* @uses iCalUtilityFunctions::_tz2offset()
|
447 |
+
* @return string
|
448 |
+
*/
|
449 |
+
public static function _date2strdate( $datetime, $parno=6 ) {
|
450 |
+
if( !isset( $datetime['year'] ) &&
|
451 |
+
!isset( $datetime['month'] ) &&
|
452 |
+
!isset( $datetime['day'] ) &&
|
453 |
+
!isset( $datetime['hour'] ) &&
|
454 |
+
!isset( $datetime['min'] ) &&
|
455 |
+
!isset( $datetime['sec'] ))
|
456 |
+
return;
|
457 |
+
$output = null;
|
458 |
+
foreach( $datetime as $dkey => & $dvalue )
|
459 |
+
if( 'tz' != $dkey ) $dvalue = (int) $dvalue;
|
460 |
+
$output = sprintf( iCalUtilityFunctions::$fmt['Ymd'], $datetime['year'], $datetime['month'], $datetime['day'] );
|
461 |
+
if( 3 == $parno )
|
462 |
+
return $output;
|
463 |
+
if( !isset( $datetime['hour'] )) $datetime['hour'] = 0;
|
464 |
+
if( !isset( $datetime['min'] )) $datetime['min'] = 0;
|
465 |
+
if( !isset( $datetime['sec'] )) $datetime['sec'] = 0;
|
466 |
+
$output .= 'T'.sprintf( iCalUtilityFunctions::$fmt['His'], $datetime['hour'], $datetime['min'], $datetime['sec'] );
|
467 |
+
if( isset( $datetime['tz'] ) && ( '' < trim( $datetime['tz'] ))) {
|
468 |
+
$datetime['tz'] = trim( $datetime['tz'] );
|
469 |
+
if( 'Z' == $datetime['tz'] )
|
470 |
+
$parno = 7;
|
471 |
+
elseif( iCalUtilityFunctions::_isOffset( $datetime['tz'] )) {
|
472 |
+
$parno = 7;
|
473 |
+
$offset = iCalUtilityFunctions::_tz2offset( $datetime['tz'] );
|
474 |
+
try {
|
475 |
+
$d = new DateTime( $output, new DateTimeZone( 'UTC' ));
|
476 |
+
if( 0 != $offset ) // adjust för offset
|
477 |
+
$d->modify( "$offset seconds" );
|
478 |
+
$output = $d->format( 'Ymd\THis' );
|
479 |
+
}
|
480 |
+
catch( Exception $e ) {
|
481 |
+
$output = date( 'Ymd\THis', mktime( $datetime['hour'], $datetime['min'], ($datetime['sec'] - $offset), $datetime['month'], $datetime['day'], $datetime['year'] ));
|
482 |
+
}
|
483 |
+
}
|
484 |
+
if( 7 == $parno )
|
485 |
+
$output .= 'Z';
|
486 |
+
}
|
487 |
+
return $output;
|
488 |
+
}
|
489 |
+
/**
|
490 |
+
* ensures internal duration format for input in array format
|
491 |
+
*
|
492 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
493 |
+
* @since 2.19.4 - 2014-03-14
|
494 |
+
* @param array $duration
|
495 |
+
* @return array
|
496 |
+
*/
|
497 |
+
public static function _duration2arr( $duration ) {
|
498 |
+
$seconds = 0;
|
499 |
+
foreach( $duration as $durKey => $durValue ) {
|
500 |
+
if( empty( $durValue )) continue;
|
501 |
+
switch ( $durKey ) {
|
502 |
+
case '0': case 'week':
|
503 |
+
$seconds += (((int) $durValue ) * 60 * 60 * 24 * 7 );
|
504 |
+
break;
|
505 |
+
case '1': case 'day':
|
506 |
+
$seconds += (((int) $durValue ) * 60 * 60 * 24 );
|
507 |
+
break;
|
508 |
+
case '2': case 'hour':
|
509 |
+
$seconds += (((int) $durValue ) * 60 * 60 );
|
510 |
+
break;
|
511 |
+
case '3': case 'min':
|
512 |
+
$seconds += (((int) $durValue ) * 60 );
|
513 |
+
break;
|
514 |
+
case '4': case 'sec':
|
515 |
+
$seconds += (int) $durValue;
|
516 |
+
break;
|
517 |
+
}
|
518 |
+
}
|
519 |
+
$output = array();
|
520 |
+
$output['week'] = (int) floor( $seconds / ( 60 * 60 * 24 * 7 ));
|
521 |
+
if(( 0 < $output['week'] ) && ( 0 == ( $seconds % ( 60 * 60 * 24 * 7 ))))
|
522 |
+
return $output;
|
523 |
+
unset( $output['week'] );
|
524 |
+
$output['day'] = (int) floor( $seconds / ( 60 * 60 * 24 ));
|
525 |
+
$seconds = ( $seconds % ( 60 * 60 * 24 ));
|
526 |
+
$output['hour'] = (int) floor( $seconds / ( 60 * 60 ));
|
527 |
+
$seconds = ( $seconds % ( 60 * 60 ));
|
528 |
+
$output['min'] = (int) floor( $seconds / 60 );
|
529 |
+
$output['sec'] = ( $seconds % 60 );
|
530 |
+
if( empty( $output['day'] ))
|
531 |
+
unset( $output['day'] );
|
532 |
+
if(( 0 == $output['hour'] ) && ( 0 == $output['min'] ) && ( 0 == $output['sec'] ))
|
533 |
+
unset( $output['hour'], $output['min'], $output['sec'] );
|
534 |
+
return $output;
|
535 |
+
}
|
536 |
+
/**
|
537 |
+
* convert startdate+duration to a array format datetime
|
538 |
+
*
|
539 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
540 |
+
* @since 2.21.11 - 2015-03-21
|
541 |
+
* @param array $startdate
|
542 |
+
* @param array $duration
|
543 |
+
* @uses iCalUtilityFunctions::$fmt
|
544 |
+
* @return array, date format
|
545 |
+
*/
|
546 |
+
public static function _duration2date( $startdate, $duration ) {
|
547 |
+
$dateOnly = ( isset( $startdate['hour'] ) || isset( $startdate['min'] ) || isset( $startdate['sec'] )) ? FALSE : TRUE;
|
548 |
+
$startdate['hour'] = ( isset( $startdate['hour'] )) ? $startdate['hour'] : 0;
|
549 |
+
$startdate['min'] = ( isset( $startdate['min'] )) ? $startdate['min'] : 0;
|
550 |
+
$startdate['sec'] = ( isset( $startdate['sec'] )) ? $startdate['sec'] : 0;
|
551 |
+
$dtend = 0;
|
552 |
+
if( isset( $duration['week'] )) $dtend += ( $duration['week'] * 7 * 24 * 60 * 60 );
|
553 |
+
if( isset( $duration['day'] )) $dtend += ( $duration['day'] * 24 * 60 * 60 );
|
554 |
+
if( isset( $duration['hour'] )) $dtend += ( $duration['hour'] * 60 *60 );
|
555 |
+
if( isset( $duration['min'] )) $dtend += ( $duration['min'] * 60 );
|
556 |
+
if( isset( $duration['sec'] )) $dtend += $duration['sec'];
|
557 |
+
$date = date( iCalUtilityFunctions::$fmt['YmdHis3'],
|
558 |
+
mktime((int) $startdate['hour'], (int) $startdate['min'], (int) ( $startdate['sec'] + $dtend ), (int) $startdate['month'], (int) $startdate['day'], (int) $startdate['year'] ));
|
559 |
+
$d = explode( '-', $date );
|
560 |
+
$dtend2 = array( 'year' => $d[0], 'month' => $d[1], 'day' => $d[2], 'hour' => $d[3], 'min' => $d[4], 'sec' => $d[5] );
|
561 |
+
if( isset( $startdate['tz'] ))
|
562 |
+
$dtend2['tz'] = $startdate['tz'];
|
563 |
+
if( $dateOnly && (( 0 == $dtend2['hour'] ) && ( 0 == $dtend2['min'] ) && ( 0 == $dtend2['sec'] )))
|
564 |
+
unset( $dtend2['hour'], $dtend2['min'], $dtend2['sec'] );
|
565 |
+
return $dtend2;
|
566 |
+
}
|
567 |
+
/**
|
568 |
+
* ensures internal duration format for an input string (iCal) formatted duration
|
569 |
+
*
|
570 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
571 |
+
* @since 2.14.1 - 2012-09-25
|
572 |
+
* @param string $duration
|
573 |
+
* @uses iCalUtilityFunctions::_duration2arr()
|
574 |
+
* @return array
|
575 |
+
*/
|
576 |
+
public static function _durationStr2arr( $duration ) {
|
577 |
+
$duration = (string) trim( $duration );
|
578 |
+
while( 'P' != strtoupper( substr( $duration, 0, 1 ))) {
|
579 |
+
if( 0 < strlen( $duration ))
|
580 |
+
$duration = substr( $duration, 1 );
|
581 |
+
else
|
582 |
+
return false; // no leading P !?!?
|
583 |
+
}
|
584 |
+
$duration = substr( $duration, 1 ); // skip P
|
585 |
+
$duration = str_replace ( 't', 'T', $duration );
|
586 |
+
$duration = str_replace ( 'T', '', $duration );
|
587 |
+
$output = array();
|
588 |
+
$val = null;
|
589 |
+
for( $ix=0; $ix < strlen( $duration ); $ix++ ) {
|
590 |
+
switch( strtoupper( substr( $duration, $ix, 1 ))) {
|
591 |
+
case 'W':
|
592 |
+
$output['week'] = $val;
|
593 |
+
$val = null;
|
594 |
+
break;
|
595 |
+
case 'D':
|
596 |
+
$output['day'] = $val;
|
597 |
+
$val = null;
|
598 |
+
break;
|
599 |
+
case 'H':
|
600 |
+
$output['hour'] = $val;
|
601 |
+
$val = null;
|
602 |
+
break;
|
603 |
+
case 'M':
|
604 |
+
$output['min'] = $val;
|
605 |
+
$val = null;
|
606 |
+
break;
|
607 |
+
case 'S':
|
608 |
+
$output['sec'] = $val;
|
609 |
+
$val = null;
|
610 |
+
break;
|
611 |
+
default:
|
612 |
+
if( !ctype_digit( substr( $duration, $ix, 1 )))
|
613 |
+
return false; // unknown duration control character !?!?
|
614 |
+
else
|
615 |
+
$val .= substr( $duration, $ix, 1 );
|
616 |
+
}
|
617 |
+
}
|
618 |
+
return iCalUtilityFunctions::_duration2arr( $output );
|
619 |
+
}
|
620 |
+
/**
|
621 |
+
* creates formatted output for calendar component property data value type duration
|
622 |
+
*
|
623 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
624 |
+
* @since 2.15.8 - 2012-10-30
|
625 |
+
* @param array $duration, array( week, day, hour, min, sec )
|
626 |
+
* @return string
|
627 |
+
*/
|
628 |
+
public static function _duration2str( array $duration ) {
|
629 |
+
if( isset( $duration['week'] ) ||
|
630 |
+
isset( $duration['day'] ) ||
|
631 |
+
isset( $duration['hour'] ) ||
|
632 |
+
isset( $duration['min'] ) ||
|
633 |
+
isset( $duration['sec'] ))
|
634 |
+
$ok = TRUE;
|
635 |
+
else
|
636 |
+
return;
|
637 |
+
if( isset( $duration['week'] ) && ( 0 < $duration['week'] ))
|
638 |
+
return 'P'.$duration['week'].'W';
|
639 |
+
$output = 'P';
|
640 |
+
if( isset($duration['day'] ) && ( 0 < $duration['day'] ))
|
641 |
+
$output .= $duration['day'].'D';
|
642 |
+
if(( isset( $duration['hour']) && ( 0 < $duration['hour'] )) ||
|
643 |
+
( isset( $duration['min']) && ( 0 < $duration['min'] )) ||
|
644 |
+
( isset( $duration['sec']) && ( 0 < $duration['sec'] ))) {
|
645 |
+
$output .= 'T';
|
646 |
+
$output .= ( isset( $duration['hour']) && ( 0 < $duration['hour'] )) ? $duration['hour'].'H' : '0H';
|
647 |
+
$output .= ( isset( $duration['min']) && ( 0 < $duration['min'] )) ? $duration['min']. 'M' : '0M';
|
648 |
+
$output .= ( isset( $duration['sec']) && ( 0 < $duration['sec'] )) ? $duration['sec']. 'S' : '0S';
|
649 |
+
}
|
650 |
+
if( 'P' == $output )
|
651 |
+
$output = 'PT0H0M0S';
|
652 |
+
return $output;
|
653 |
+
}
|
654 |
+
/**
|
655 |
+
* removes expkey+expvalue from array and returns hitval (if found) else returns elseval
|
656 |
+
*
|
657 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
658 |
+
* @since 2.4.16 - 2008-11-08
|
659 |
+
* @param array $array iCal property parameters
|
660 |
+
* @param string $expkey expected key
|
661 |
+
* @param string $expval expected value
|
662 |
+
* @param int $hitVal return value if found
|
663 |
+
* @param int $elseVal return value if not found
|
664 |
+
* @param int $preSet return value if already preset
|
665 |
+
* @return int
|
666 |
+
*/
|
667 |
+
public static function _existRem( & $array, $expkey, $expval=FALSE, $hitVal=null, $elseVal=null, $preSet=null ) {
|
668 |
+
if( $preSet )
|
669 |
+
return $preSet;
|
670 |
+
if( !is_array( $array ) || ( 0 == count( $array )))
|
671 |
+
return $elseVal;
|
672 |
+
foreach( $array as $key => $value ) {
|
673 |
+
if( strtoupper( $expkey ) == strtoupper( $key )) {
|
674 |
+
if( !$expval || ( strtoupper( $expval ) == strtoupper( $array[$key] ))) {
|
675 |
+
unset( $array[$key] );
|
676 |
+
return $hitVal;
|
677 |
+
}
|
678 |
+
}
|
679 |
+
}
|
680 |
+
return $elseVal;
|
681 |
+
}
|
682 |
+
/**
|
683 |
+
* check if dates are in scope
|
684 |
+
*
|
685 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
686 |
+
* @since 2.21.7 - 2015-03-25
|
687 |
+
* @param object $start datetime
|
688 |
+
* @param object $scopeStart datetime
|
689 |
+
* @param object $end datetime
|
690 |
+
* @param object $scopeEnd datetime
|
691 |
+
* @param string $format
|
692 |
+
* @return bool
|
693 |
+
*/
|
694 |
+
public static function _inScope( $start, $scopeStart, $end, $scopeEnd, $format ) {
|
695 |
+
return (( $start->format( $format ) >= $scopeStart->format( $format )) &&
|
696 |
+
( $end->format( $format ) <= $scopeEnd->format( $format )));
|
697 |
+
}
|
698 |
+
/**
|
699 |
+
* mgnt geo part output
|
700 |
+
*
|
701 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
702 |
+
* @since 2.8.10 - 2013-09-02
|
703 |
+
* @param float $ll
|
704 |
+
* @param string $format
|
705 |
+
* @return string
|
706 |
+
*/
|
707 |
+
public static function _geo2str2( $ll, $format ) {
|
708 |
+
if( 0.0 < $ll )
|
709 |
+
$sign = '+';
|
710 |
+
else
|
711 |
+
$sign = ( 0.0 > $ll ) ? '-' : '';
|
712 |
+
return rtrim( rtrim( $sign.sprintf( $format, abs( $ll )), '0' ), '.' );
|
713 |
+
}
|
714 |
+
/**
|
715 |
+
* checks if input contains a (array formatted) date/time
|
716 |
+
*
|
717 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
718 |
+
* @since 2.16.24 - 2013-07-02
|
719 |
+
* @param array $input
|
720 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
721 |
+
* @return bool
|
722 |
+
*/
|
723 |
+
public static function _isArrayDate( $input ) {
|
724 |
+
if( !is_array( $input ) || isset( $input['week'] ) || isset( $input['timestamp'] ) || ( 3 > count( $input )))
|
725 |
+
return FALSE;
|
726 |
+
if( 7 == count( $input ))
|
727 |
+
return TRUE;
|
728 |
+
if( isset( $input['year'] ) && isset( $input['month'] ) && isset( $input['day'] ))
|
729 |
+
return checkdate( (int) $input['month'], (int) $input['day'], (int) $input['year'] );
|
730 |
+
if( isset( $input['day'] ) || isset( $input['hour'] ) || isset( $input['min'] ) || isset( $input['sec'] ))
|
731 |
+
return FALSE;
|
732 |
+
if(( 0 == $input[0] ) || ( 0 == $input[1] ) || ( 0 == $input[2] ))
|
733 |
+
return FALSE;
|
734 |
+
if(( 1970 > $input[0] ) || ( 12 < $input[1] ) || ( 31 < $input[2] ))
|
735 |
+
return FALSE;
|
736 |
+
if(( isset( $input[0] ) && isset( $input[1] ) && isset( $input[2] )) &&
|
737 |
+
checkdate((int) $input[1], (int) $input[2], (int) $input[0] ))
|
738 |
+
return TRUE;
|
739 |
+
$input = iCalUtilityFunctions::_strdate2date( $input[1].'/'.$input[2].'/'.$input[0], 3 ); // m - d - Y
|
740 |
+
if( isset( $input['year'] ) && isset( $input['month'] ) && isset( $input['day'] ))
|
741 |
+
return checkdate( (int) $input['month'], (int) $input['day'], (int) $input['year'] );
|
742 |
+
return FALSE;
|
743 |
+
}
|
744 |
+
/**
|
745 |
+
* checks if input array contains a timestamp date
|
746 |
+
*
|
747 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
748 |
+
* @since 2.4.16 - 2008-10-18
|
749 |
+
* @param array $input
|
750 |
+
* @return bool
|
751 |
+
*/
|
752 |
+
public static function _isArrayTimestampDate( $input ) {
|
753 |
+
return ( is_array( $input ) && isset( $input['timestamp'] )) ? TRUE : FALSE ;
|
754 |
+
}
|
755 |
+
/**
|
756 |
+
* controls if input string contains (trailing) UTC/iCal offset
|
757 |
+
*
|
758 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
759 |
+
* @since 2.14.1 - 2012-09-21
|
760 |
+
* @param string $input
|
761 |
+
* @return bool
|
762 |
+
*/
|
763 |
+
public static function _isOffset( $input ) {
|
764 |
+
$input = trim( (string) $input );
|
765 |
+
if( 'Z' == substr( $input, -1 ))
|
766 |
+
return TRUE;
|
767 |
+
elseif(( 5 <= strlen( $input )) &&
|
768 |
+
( in_array( substr( $input, -5, 1 ), array( '+', '-' ))) &&
|
769 |
+
( '0000' <= substr( $input, -4 )) && ( '9999' >= substr( $input, -4 )))
|
770 |
+
return TRUE;
|
771 |
+
elseif(( 7 <= strlen( $input )) &&
|
772 |
+
( in_array( substr( $input, -7, 1 ), array( '+', '-' ))) &&
|
773 |
+
( '000000' <= substr( $input, -6 )) && ( '999999' >= substr( $input, -6 )))
|
774 |
+
return TRUE;
|
775 |
+
return FALSE;
|
776 |
+
}
|
777 |
+
/**
|
778 |
+
* (very simple) conversion of a MS timezone to a PHP5 valid (Date-)timezone
|
779 |
+
* matching (MS) UCT offset and time zone descriptors
|
780 |
+
*
|
781 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
782 |
+
* @since 2.14.1 - 2012-09-16
|
783 |
+
* @param string $timezone to convert
|
784 |
+
* @uses iCalUtilityFunctions::_tz2offset()
|
785 |
+
* @return bool
|
786 |
+
*/
|
787 |
+
public static function ms2phpTZ( & $timezone ) {
|
788 |
+
if( empty( $timezone ))
|
789 |
+
return FALSE;
|
790 |
+
// $search = str_replace( '"', '', $timezone );
|
791 |
+
$search = str_replace( array('GMT', 'gmt', 'utc' ), 'UTC', $search );
|
792 |
+
if( '(UTC' != substr( $search, 0, 4 ))
|
793 |
+
return FALSE;
|
794 |
+
if( FALSE === ( $pos = strpos( $search, ')' )))
|
795 |
+
return FALSE;
|
796 |
+
$pos = strpos( $search, ')' );
|
797 |
+
$searchOffset = substr( $search, 4, ( $pos - 4 ));
|
798 |
+
$searchOffset = iCalUtilityFunctions::_tz2offset( str_replace( ':', '', $searchOffset ));
|
799 |
+
while( ' ' ==substr( $search, ( $pos + 1 )))
|
800 |
+
$pos += 1;
|
801 |
+
$searchText = trim( str_replace( array( '(', ')', '&', ',', ' ' ), ' ', substr( $search, ( $pos + 1 )) ));
|
802 |
+
$searchWords = explode( ' ', $searchText );
|
803 |
+
$timezone_abbreviations = DateTimeZone::listAbbreviations();
|
804 |
+
$hits = array();
|
805 |
+
foreach( $timezone_abbreviations as $name => $transitions ) {
|
806 |
+
foreach( $transitions as $cnt => $transition ) {
|
807 |
+
if( empty( $transition['offset'] ) ||
|
808 |
+
empty( $transition['timezone_id'] ) ||
|
809 |
+
( $transition['offset'] != $searchOffset ))
|
810 |
+
continue;
|
811 |
+
$cWords = explode( '/', $transition['timezone_id'] );
|
812 |
+
$cPrio = $hitCnt = $rank = 0;
|
813 |
+
foreach( $cWords as $cWord ) {
|
814 |
+
if( empty( $cWord ))
|
815 |
+
continue;
|
816 |
+
$cPrio += 1;
|
817 |
+
$sPrio = 0;
|
818 |
+
foreach( $searchWords as $sWord ) {
|
819 |
+
if( empty( $sWord ) || ( 'time' == strtolower( $sWord )))
|
820 |
+
continue;
|
821 |
+
$sPrio += 1;
|
822 |
+
if( strtolower( $cWord ) == strtolower( $sWord )) {
|
823 |
+
$hitCnt += 1;
|
824 |
+
$rank += ( $cPrio + $sPrio );
|
825 |
+
}
|
826 |
+
else
|
827 |
+
$rank += 10;
|
828 |
+
}
|
829 |
+
}
|
830 |
+
if( 0 < $hitCnt ) {
|
831 |
+
$hits[$rank][] = $transition['timezone_id'];
|
832 |
+
}
|
833 |
+
}
|
834 |
+
}
|
835 |
+
unset( $timezone_abbreviations );
|
836 |
+
if( empty( $hits ))
|
837 |
+
return FALSE;
|
838 |
+
ksort( $hits );
|
839 |
+
foreach( $hits as $rank => $tzs ) {
|
840 |
+
if( !empty( $tzs )) {
|
841 |
+
$timezone = reset( $tzs );
|
842 |
+
return TRUE;
|
843 |
+
}
|
844 |
+
}
|
845 |
+
return FALSE;
|
846 |
+
}
|
847 |
+
/**
|
848 |
+
* transforms offset in seconds to [-/+]hhmm[ss]
|
849 |
+
*
|
850 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
851 |
+
* @since 2011-05-02
|
852 |
+
* @param string $seconds
|
853 |
+
* @return string
|
854 |
+
*/
|
855 |
+
public static function offsetSec2His( $seconds ) {
|
856 |
+
if( '-' == substr( $seconds, 0, 1 )) {
|
857 |
+
$prefix = '-';
|
858 |
+
$seconds = substr( $seconds, 1 );
|
859 |
+
}
|
860 |
+
elseif( '+' == substr( $seconds, 0, 1 )) {
|
861 |
+
$prefix = '+';
|
862 |
+
$seconds = substr( $seconds, 1 );
|
863 |
+
}
|
864 |
+
else
|
865 |
+
$prefix = '+';
|
866 |
+
$output = '';
|
867 |
+
$hour = (int) floor( $seconds / 3600 );
|
868 |
+
if( 10 > $hour )
|
869 |
+
$hour = '0'.$hour;
|
870 |
+
$seconds = $seconds % 3600;
|
871 |
+
$min = (int) floor( $seconds / 60 );
|
872 |
+
if( 10 > $min )
|
873 |
+
$min = '0'.$min;
|
874 |
+
$output = $hour.$min;
|
875 |
+
$seconds = $seconds % 60;
|
876 |
+
if( 0 < $seconds) {
|
877 |
+
if( 9 < $seconds)
|
878 |
+
$output .= $seconds;
|
879 |
+
else
|
880 |
+
$output .= '0'.$seconds;
|
881 |
+
}
|
882 |
+
return $prefix.$output;
|
883 |
+
}
|
884 |
+
/**
|
885 |
+
* updates an array with dates based on a recur pattern
|
886 |
+
*
|
887 |
+
* if missing, UNTIL is set 1 year from startdate (emergency break)
|
888 |
+
*
|
889 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
890 |
+
* @since 2.21.11 - 2015-03-10
|
891 |
+
* @param array $result array to update, array([Y-m-d] => bool)
|
892 |
+
* @param array $recur pattern for recurrency (only value part, params ignored)
|
893 |
+
* @param mixed $wdate component start date, string / array / (datetime) obj
|
894 |
+
* @param mixed $fcnStart start date, string / array / (datetime) obj
|
895 |
+
* @param mixed $fcnEnd end date, string / array / (datetime) obj
|
896 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
897 |
+
* @uses iCalUtilityFunctions::$fmt
|
898 |
+
* @uses iCalUtilityFunctions::_stepdate()
|
899 |
+
* @uses iCalUtilityFunctions::_recurIntervalIx()
|
900 |
+
* @uses iCalUtilityFunctions::_recurBYcntcheck()
|
901 |
+
* @return void
|
902 |
+
* @todo BYHOUR, BYMINUTE, BYSECOND, WEEKLY at year end/start OR not at all
|
903 |
+
*/
|
904 |
+
public static function _recur2date( & $result, $recur, $wdate, $fcnStart, $fcnEnd=FALSE ) {
|
905 |
+
if( is_string( $wdate ))
|
906 |
+
iCalUtilityFunctions::_strDate2arr( $wdate );
|
907 |
+
elseif( is_a( $wdate, 'DateTime' )) {
|
908 |
+
$wdate = $wdate->format( iCalUtilityFunctions::$fmt['YmdHis2'] );
|
909 |
+
iCalUtilityFunctions::_strDate2arr( $wdate );
|
910 |
+
}
|
911 |
+
foreach( $wdate as $k => $v ) if( ctype_digit( $v )) $wdate[$k] = (int) $v;
|
912 |
+
$wdateYMD = sprintf( iCalUtilityFunctions::$fmt['Ymd'], $wdate['year'], $wdate['month'], $wdate['day'] );
|
913 |
+
$wdateHis = sprintf( iCalUtilityFunctions::$fmt['His'], $wdate['hour'], $wdate['min'], $wdate['sec'] );
|
914 |
+
$untilHis = $wdateHis;
|
915 |
+
if( is_string( $fcnStart ))
|
916 |
+
iCalUtilityFunctions::_strDate2arr( $fcnStart );
|
917 |
+
elseif( is_a( $fcnStart, 'DateTime' )) {
|
918 |
+
$fcnStart = $fcnStart->format( iCalUtilityFunctions::$fmt['YmdHis2'] );
|
919 |
+
iCalUtilityFunctions::_strDate2arr( $fcnStart );
|
920 |
+
}
|
921 |
+
foreach( $fcnStart as $k => $v ) if( ctype_digit( $v )) $fcnStart[$k] = (int) $v;
|
922 |
+
$fcnStartYMD = sprintf( iCalUtilityFunctions::$fmt['Ymd'], $fcnStart['year'], $fcnStart['month'], $fcnStart['day'] );
|
923 |
+
if( is_string( $fcnEnd ))
|
924 |
+
iCalUtilityFunctions::_strDate2arr( $fcnEnd );
|
925 |
+
elseif( is_a( $fcnEnd, 'DateTime' )) {
|
926 |
+
$fcnEnd = $fcnEnd->format( iCalUtilityFunctions::$fmt['YmdHis2'] );
|
927 |
+
iCalUtilityFunctions::_strDate2arr( $fcnEnd );
|
928 |
+
}
|
929 |
+
if( !$fcnEnd ) {
|
930 |
+
$fcnEnd = $fcnStart;
|
931 |
+
$fcnEnd['year'] += 1;
|
932 |
+
}
|
933 |
+
foreach( $fcnEnd as $k => $v ) if( ctype_digit( $v )) $fcnEnd[$k] = (int) $v;
|
934 |
+
$fcnEndYMD = sprintf( iCalUtilityFunctions::$fmt['Ymd'], $fcnEnd['year'], $fcnEnd['month'], $fcnEnd['day'] );
|
935 |
+
// echo "<b>recur _in_ comp</b> start ".implode('-',$wdate)." period start ".implode('-',$fcnStart)." period end ".implode('-',$fcnEnd)."<br>\n";
|
936 |
+
// echo 'recur='.str_replace( array( PHP_EOL, ' ' ), '', var_export( $recur, TRUE ))."<br> \n"; // test ###
|
937 |
+
if( !isset( $recur['COUNT'] ) && !isset( $recur['UNTIL'] ))
|
938 |
+
$recur['UNTIL'] = $fcnEnd; // create break
|
939 |
+
if( isset( $recur['UNTIL'] )) {
|
940 |
+
foreach( $recur['UNTIL'] as $k => $v ) if( ctype_digit( $v )) $recur['UNTIL'][$k] = (int) $v;
|
941 |
+
unset( $recur['UNTIL']['tz'] );
|
942 |
+
if( $fcnEnd > $recur['UNTIL'] ) {
|
943 |
+
$fcnEnd = $recur['UNTIL']; // emergency break
|
944 |
+
$fcnEndYMD = sprintf( iCalUtilityFunctions::$fmt['Ymd'], $fcnEnd['year'], $fcnEnd['month'], $fcnEnd['day'] );
|
945 |
+
}
|
946 |
+
if( isset( $recur['UNTIL']['hour'] ))
|
947 |
+
$untilHis = sprintf( iCalUtilityFunctions::$fmt['His'], $recur['UNTIL']['hour'], $recur['UNTIL']['min'], $recur['UNTIL']['sec'] );
|
948 |
+
else
|
949 |
+
$untilHis = sprintf( iCalUtilityFunctions::$fmt['His'], 23, 59, 59 );
|
950 |
+
// echo 'recurUNTIL='.str_replace( array( PHP_EOL, ' ' ), '', var_export( $recur['UNTIL'], TRUE )).", untilHis={$untilHis}<br> \n"; // test ###
|
951 |
+
}
|
952 |
+
// echo 'fcnEnd:'.$fcnEndYMD.$untilHis."<br>\n";//test
|
953 |
+
if( $wdateYMD > $fcnEndYMD ) {
|
954 |
+
// echo 'recur out of date, '.implode('-',$wdate).', end='.implode('-',$fcnEnd)."<br>\n";//test
|
955 |
+
return array(); // nothing to do.. .
|
956 |
+
}
|
957 |
+
if( !isset( $recur['FREQ'] )) // "MUST be specified.. ."
|
958 |
+
$recur['FREQ'] = 'DAILY'; // ??
|
959 |
+
$wkst = ( isset( $recur['WKST'] ) && ( 'SU' == $recur['WKST'] )) ? 24*60*60 : 0; // ??
|
960 |
+
if( !isset( $recur['INTERVAL'] ))
|
961 |
+
$recur['INTERVAL'] = 1;
|
962 |
+
$countcnt = ( !isset( $recur['BYSETPOS'] )) ? 1 : 0; // DTSTART counts as the first occurrence
|
963 |
+
/* find out how to step up dates and set index for interval count */
|
964 |
+
$step = array();
|
965 |
+
if( 'YEARLY' == $recur['FREQ'] )
|
966 |
+
$step['year'] = 1;
|
967 |
+
elseif( 'MONTHLY' == $recur['FREQ'] )
|
968 |
+
$step['month'] = 1;
|
969 |
+
elseif( 'WEEKLY' == $recur['FREQ'] )
|
970 |
+
$step['day'] = 7;
|
971 |
+
else
|
972 |
+
$step['day'] = 1;
|
973 |
+
if( isset( $step['year'] ) && isset( $recur['BYMONTH'] ))
|
974 |
+
$step = array( 'month' => 1 );
|
975 |
+
if( empty( $step ) && isset( $recur['BYWEEKNO'] )) // ??
|
976 |
+
$step = array( 'day' => 7 );
|
977 |
+
if( isset( $recur['BYYEARDAY'] ) || isset( $recur['BYMONTHDAY'] ) || isset( $recur['BYDAY'] ))
|
978 |
+
$step = array( 'day' => 1 );
|
979 |
+
$intervalarr = array();
|
980 |
+
if( 1 < $recur['INTERVAL'] ) {
|
981 |
+
$intervalix = iCalUtilityFunctions::_recurIntervalIx( $recur['FREQ'], $wdate, $wkst );
|
982 |
+
$intervalarr = array( $intervalix => 0 );
|
983 |
+
}
|
984 |
+
if( isset( $recur['BYSETPOS'] )) { // save start date + weekno
|
985 |
+
$bysetposymd1 = $bysetposymd2 = $bysetposw1 = $bysetposw2 = array();
|
986 |
+
// echo "bysetposXold_start=$bysetposYold $bysetposMold $bysetposDold<br>\n"; // test ###
|
987 |
+
if( is_array( $recur['BYSETPOS'] )) {
|
988 |
+
foreach( $recur['BYSETPOS'] as $bix => $bval )
|
989 |
+
$recur['BYSETPOS'][$bix] = (int) $bval;
|
990 |
+
}
|
991 |
+
else
|
992 |
+
$recur['BYSETPOS'] = array( (int) $recur['BYSETPOS'] );
|
993 |
+
if( 'YEARLY' == $recur['FREQ'] ) {
|
994 |
+
$wdate['month'] = $wdate['day'] = 1; // start from beginning of year
|
995 |
+
$wdateYMD = sprintf( iCalUtilityFunctions::$fmt['Ymd'], $wdate['year'], $wdate['month'], $wdate['day'] );
|
996 |
+
iCalUtilityFunctions::_stepdate( $fcnEnd, $fcnEndYMD, array( 'year' => 1 )); // make sure to count whole last year
|
997 |
+
}
|
998 |
+
elseif( 'MONTHLY' == $recur['FREQ'] ) {
|
999 |
+
$wdate['day'] = 1; // start from beginning of month
|
1000 |
+
$wdateYMD = sprintf( iCalUtilityFunctions::$fmt['Ymd'], $wdate['year'], $wdate['month'], $wdate['day'] );
|
1001 |
+
iCalUtilityFunctions::_stepdate( $fcnEnd, $fcnEndYMD, array( 'month' => 1 )); // make sure to count whole last month
|
1002 |
+
}
|
1003 |
+
else
|
1004 |
+
iCalUtilityFunctions::_stepdate( $fcnEnd, $fcnEndYMD, $step); // make sure to count whole last period
|
1005 |
+
// echo "BYSETPOS endDat =".implode('-',$fcnEnd).' step='.var_export($step,TRUE)."<br>\n";//test###
|
1006 |
+
$bysetposWold = (int) date( 'W', mktime( 0, 0, $wkst, $wdate['month'], $wdate['day'], $wdate['year'] ));
|
1007 |
+
$bysetposYold = $wdate['year'];
|
1008 |
+
$bysetposMold = $wdate['month'];
|
1009 |
+
$bysetposDold = $wdate['day'];
|
1010 |
+
}
|
1011 |
+
else
|
1012 |
+
iCalUtilityFunctions::_stepdate( $wdate, $wdateYMD, $step);
|
1013 |
+
$year_old = null;
|
1014 |
+
static $daynames = array( 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA' );
|
1015 |
+
/* MAIN LOOP */
|
1016 |
+
// echo "recur start:$wdateYMD, end:$fcnEndYMD<br>\n";//test
|
1017 |
+
while( TRUE ) {
|
1018 |
+
// echo "recur while:$wdateYMD, end:$fcnEndYMD<br>\n";//test
|
1019 |
+
if( $wdateYMD.$wdateHis > $fcnEndYMD.$untilHis )
|
1020 |
+
break;
|
1021 |
+
if( isset( $recur['COUNT'] ) && ( $countcnt >= $recur['COUNT'] ))
|
1022 |
+
break;
|
1023 |
+
if( $year_old != $wdate['year'] ) {
|
1024 |
+
$year_old = $wdate['year'];
|
1025 |
+
$daycnts = array();
|
1026 |
+
$yeardays = $weekno = 0;
|
1027 |
+
$yeardaycnt = array();
|
1028 |
+
foreach( $daynames as $dn )
|
1029 |
+
$yeardaycnt[$dn] = 0;
|
1030 |
+
for( $m = 1; $m <= 12; $m++ ) { // count up and update up-counters
|
1031 |
+
$daycnts[$m] = array();
|
1032 |
+
$weekdaycnt = array();
|
1033 |
+
foreach( $daynames as $dn )
|
1034 |
+
$weekdaycnt[$dn] = 0;
|
1035 |
+
$mcnt = date( 't', mktime( 0, 0, 0, $m, 1, $wdate['year'] ));
|
1036 |
+
for( $d = 1; $d <= $mcnt; $d++ ) {
|
1037 |
+
$daycnts[$m][$d] = array();
|
1038 |
+
if( isset( $recur['BYYEARDAY'] )) {
|
1039 |
+
$yeardays++;
|
1040 |
+
$daycnts[$m][$d]['yearcnt_up'] = $yeardays;
|
1041 |
+
}
|
1042 |
+
if( isset( $recur['BYDAY'] )) {
|
1043 |
+
$day = date( 'w', mktime( 0, 0, 0, $m, $d, $wdate['year'] ));
|
1044 |
+
$day = $daynames[$day];
|
1045 |
+
$daycnts[$m][$d]['DAY'] = $day;
|
1046 |
+
$weekdaycnt[$day]++;
|
1047 |
+
$daycnts[$m][$d]['monthdayno_up'] = $weekdaycnt[$day];
|
1048 |
+
$yeardaycnt[$day]++;
|
1049 |
+
$daycnts[$m][$d]['yeardayno_up'] = $yeardaycnt[$day];
|
1050 |
+
}
|
1051 |
+
if( isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' ))
|
1052 |
+
$daycnts[$m][$d]['weekno_up'] =(int)date('W',mktime(0,0,$wkst,$m,$d,$wdate['year']));
|
1053 |
+
} // end for( $d = 1; $d <= $mcnt; $d++ )
|
1054 |
+
} // end for( $m = 1; $m <= 12; $m++ )
|
1055 |
+
$daycnt = 0;
|
1056 |
+
$yeardaycnt = array();
|
1057 |
+
if( isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' )) {
|
1058 |
+
$weekno = null;
|
1059 |
+
for( $d=31; $d > 25; $d-- ) { // get last weekno for year
|
1060 |
+
if( !$weekno )
|
1061 |
+
$weekno = $daycnts[12][$d]['weekno_up'];
|
1062 |
+
elseif( $weekno < $daycnts[12][$d]['weekno_up'] ) {
|
1063 |
+
$weekno = $daycnts[12][$d]['weekno_up'];
|
1064 |
+
break;
|
1065 |
+
}
|
1066 |
+
}
|
1067 |
+
}
|
1068 |
+
for( $m = 12; $m > 0; $m-- ) { // count down and update down-counters
|
1069 |
+
$weekdaycnt = array();
|
1070 |
+
foreach( $daynames as $dn )
|
1071 |
+
$yeardaycnt[$dn] = $weekdaycnt[$dn] = 0;
|
1072 |
+
$monthcnt = 0;
|
1073 |
+
$mcnt = date( 't', mktime( 0, 0, 0, $m, 1, $wdate['year'] ));
|
1074 |
+
for( $d = $mcnt; $d > 0; $d-- ) {
|
1075 |
+
if( isset( $recur['BYYEARDAY'] )) {
|
1076 |
+
$daycnt -= 1;
|
1077 |
+
$daycnts[$m][$d]['yearcnt_down'] = $daycnt;
|
1078 |
+
}
|
1079 |
+
if( isset( $recur['BYMONTHDAY'] )) {
|
1080 |
+
$monthcnt -= 1;
|
1081 |
+
$daycnts[$m][$d]['monthcnt_down'] = $monthcnt;
|
1082 |
+
}
|
1083 |
+
if( isset( $recur['BYDAY'] )) {
|
1084 |
+
$day = $daycnts[$m][$d]['DAY'];
|
1085 |
+
$weekdaycnt[$day] -= 1;
|
1086 |
+
$daycnts[$m][$d]['monthdayno_down'] = $weekdaycnt[$day];
|
1087 |
+
$yeardaycnt[$day] -= 1;
|
1088 |
+
$daycnts[$m][$d]['yeardayno_down'] = $yeardaycnt[$day];
|
1089 |
+
}
|
1090 |
+
if( isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' ))
|
1091 |
+
$daycnts[$m][$d]['weekno_down'] = ($daycnts[$m][$d]['weekno_up'] - $weekno - 1);
|
1092 |
+
}
|
1093 |
+
} // end for( $m = 12; $m > 0; $m-- )
|
1094 |
+
} // end if( $year_old != $wdate['year'] )
|
1095 |
+
/* check interval */
|
1096 |
+
if( 1 < $recur['INTERVAL'] ) {
|
1097 |
+
/* create interval index */
|
1098 |
+
$intervalix = iCalUtilityFunctions::_recurIntervalIx( $recur['FREQ'], $wdate, $wkst );
|
1099 |
+
/* check interval */
|
1100 |
+
$currentKey = array_keys( $intervalarr );
|
1101 |
+
$currentKey = end( $currentKey ); // get last index
|
1102 |
+
if( $currentKey != $intervalix )
|
1103 |
+
$intervalarr = array( $intervalix => ( $intervalarr[$currentKey] + 1 ));
|
1104 |
+
if(( $recur['INTERVAL'] != $intervalarr[$intervalix] ) &&
|
1105 |
+
( 0 != $intervalarr[$intervalix] )) {
|
1106 |
+
/* step up date */
|
1107 |
+
// echo "skip: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br>\n";//test
|
1108 |
+
iCalUtilityFunctions::_stepdate( $wdate, $wdateYMD, $step);
|
1109 |
+
continue;
|
1110 |
+
}
|
1111 |
+
else // continue within the selected interval
|
1112 |
+
$intervalarr[$intervalix] = 0;
|
1113 |
+
// echo "cont: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br>\n";//test
|
1114 |
+
} // endif( 1 < $recur['INTERVAL'] )
|
1115 |
+
$updateOK = TRUE;
|
1116 |
+
if( $updateOK && isset( $recur['BYMONTH'] ))
|
1117 |
+
$updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYMONTH']
|
1118 |
+
, $wdate['month']
|
1119 |
+
,($wdate['month'] - 13));
|
1120 |
+
if( $updateOK && isset( $recur['BYWEEKNO'] ))
|
1121 |
+
$updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYWEEKNO']
|
1122 |
+
, $daycnts[$wdate['month']][$wdate['day']]['weekno_up']
|
1123 |
+
, $daycnts[$wdate['month']][$wdate['day']]['weekno_down'] );
|
1124 |
+
if( $updateOK && isset( $recur['BYYEARDAY'] ))
|
1125 |
+
$updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYYEARDAY']
|
1126 |
+
, $daycnts[$wdate['month']][$wdate['day']]['yearcnt_up']
|
1127 |
+
, $daycnts[$wdate['month']][$wdate['day']]['yearcnt_down'] );
|
1128 |
+
if( $updateOK && isset( $recur['BYMONTHDAY'] ))
|
1129 |
+
$updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYMONTHDAY']
|
1130 |
+
, $wdate['day']
|
1131 |
+
, $daycnts[$wdate['month']][$wdate['day']]['monthcnt_down'] );
|
1132 |
+
// echo "efter BYMONTHDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br>\n";//test###
|
1133 |
+
if( $updateOK && isset( $recur['BYDAY'] )) {
|
1134 |
+
$updateOK = FALSE;
|
1135 |
+
$m = $wdate['month'];
|
1136 |
+
$d = $wdate['day'];
|
1137 |
+
if( isset( $recur['BYDAY']['DAY'] )) { // single day, opt with year/month day order no
|
1138 |
+
$daynoexists = $daynosw = $daynamesw = FALSE;
|
1139 |
+
if( $recur['BYDAY']['DAY'] == $daycnts[$m][$d]['DAY'] )
|
1140 |
+
$daynamesw = TRUE;
|
1141 |
+
if( isset( $recur['BYDAY'][0] )) {
|
1142 |
+
$daynoexists = TRUE;
|
1143 |
+
if(( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'MONTHLY' )) || isset( $recur['BYMONTH'] ))
|
1144 |
+
$daynosw = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYDAY'][0]
|
1145 |
+
, $daycnts[$m][$d]['monthdayno_up']
|
1146 |
+
, $daycnts[$m][$d]['monthdayno_down'] );
|
1147 |
+
elseif( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'YEARLY' ))
|
1148 |
+
$daynosw = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYDAY'][0]
|
1149 |
+
, $daycnts[$m][$d]['yeardayno_up']
|
1150 |
+
, $daycnts[$m][$d]['yeardayno_down'] );
|
1151 |
+
}
|
1152 |
+
if(( $daynoexists && $daynosw && $daynamesw ) ||
|
1153 |
+
( !$daynoexists && !$daynosw && $daynamesw )) {
|
1154 |
+
$updateOK = TRUE;
|
1155 |
+
// echo "m=$m d=$d day=".$daycnts[$m][$d]['DAY']." yeardayno_up=".$daycnts[$m][$d]['yeardayno_up']." daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw updateOK:$updateOK<br>\n"; // test ###
|
1156 |
+
}
|
1157 |
+
// echo "m=$m d=$d day=".$daycnts[$m][$d]['DAY']." yeardayno_up=".$daycnts[$m][$d]['yeardayno_up']." daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw updateOK:$updateOK<br>\n"; // test ###
|
1158 |
+
}
|
1159 |
+
else {
|
1160 |
+
foreach( $recur['BYDAY'] as $bydayvalue ) {
|
1161 |
+
$daynoexists = $daynosw = $daynamesw = FALSE;
|
1162 |
+
if( isset( $bydayvalue['DAY'] ) &&
|
1163 |
+
( $bydayvalue['DAY'] == $daycnts[$m][$d]['DAY'] ))
|
1164 |
+
$daynamesw = TRUE;
|
1165 |
+
if( isset( $bydayvalue[0] )) {
|
1166 |
+
$daynoexists = TRUE;
|
1167 |
+
if(( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'MONTHLY' )) ||
|
1168 |
+
isset( $recur['BYMONTH'] ))
|
1169 |
+
$daynosw = iCalUtilityFunctions::_recurBYcntcheck( $bydayvalue['0']
|
1170 |
+
, $daycnts[$m][$d]['monthdayno_up']
|
1171 |
+
, $daycnts[$m][$d]['monthdayno_down'] );
|
1172 |
+
elseif( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'YEARLY' ))
|
1173 |
+
$daynosw = iCalUtilityFunctions::_recurBYcntcheck( $bydayvalue['0']
|
1174 |
+
, $daycnts[$m][$d]['yeardayno_up']
|
1175 |
+
, $daycnts[$m][$d]['yeardayno_down'] );
|
1176 |
+
}
|
1177 |
+
// echo "daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw<br>\n"; // test ###
|
1178 |
+
if(( $daynoexists && $daynosw && $daynamesw ) ||
|
1179 |
+
( !$daynoexists && !$daynosw && $daynamesw )) {
|
1180 |
+
$updateOK = TRUE;
|
1181 |
+
break;
|
1182 |
+
}
|
1183 |
+
}
|
1184 |
+
}
|
1185 |
+
}
|
1186 |
+
// echo "efter BYDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br>\n"; // test ###
|
1187 |
+
/* check BYSETPOS */
|
1188 |
+
if( $updateOK ) {
|
1189 |
+
if( isset( $recur['BYSETPOS'] ) &&
|
1190 |
+
( in_array( $recur['FREQ'], array( 'YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY' )))) {
|
1191 |
+
if( isset( $recur['WEEKLY'] )) {
|
1192 |
+
if( $bysetposWold == $daycnts[$wdate['month']][$wdate['day']]['weekno_up'] )
|
1193 |
+
$bysetposw1[] = $wdateYMD;
|
1194 |
+
else
|
1195 |
+
$bysetposw2[] = $wdateYMD;
|
1196 |
+
}
|
1197 |
+
else {
|
1198 |
+
if(( isset( $recur['FREQ'] ) && ( 'YEARLY' == $recur['FREQ'] ) &&
|
1199 |
+
( $bysetposYold == $wdate['year'] )) ||
|
1200 |
+
( isset( $recur['FREQ'] ) && ( 'MONTHLY' == $recur['FREQ'] ) &&
|
1201 |
+
(( $bysetposYold == $wdate['year'] ) &&
|
1202 |
+
( $bysetposMold == $wdate['month'] ))) ||
|
1203 |
+
( isset( $recur['FREQ'] ) && ( 'DAILY' == $recur['FREQ'] ) &&
|
1204 |
+
(( $bysetposYold == $wdate['year'] ) &&
|
1205 |
+
( $bysetposMold == $wdate['month']) &&
|
1206 |
+
( $bysetposDold == $wdate['day'] )))) {
|
1207 |
+
// echo "bysetposymd1[]=".date('Y-m-d H:i:s',$wdatets)."<br>\n";//test
|
1208 |
+
$bysetposymd1[] = $wdateYMD;
|
1209 |
+
}
|
1210 |
+
else {
|
1211 |
+
// echo "bysetposymd2[]=".date('Y-m-d H:i:s',$wdatets)."<br>\n";//test
|
1212 |
+
$bysetposymd2[] = $wdateYMD;
|
1213 |
+
}
|
1214 |
+
}
|
1215 |
+
}
|
1216 |
+
else {
|
1217 |
+
if( checkdate($wdate['month'], $wdate['day'], $wdate['year'] )) {
|
1218 |
+
/* update result array if BYSETPOS is not set */
|
1219 |
+
$countcnt++;
|
1220 |
+
if( $fcnStartYMD <= $wdateYMD ) { // only output within period
|
1221 |
+
$result[$wdateYMD] = TRUE;
|
1222 |
+
// echo "recur $wdateYMD<br>\n";//test
|
1223 |
+
}
|
1224 |
+
}
|
1225 |
+
// else echo "recur, no date $wdateYMD<br>\n";//test
|
1226 |
+
$updateOK = FALSE;
|
1227 |
+
}
|
1228 |
+
}
|
1229 |
+
/* step up date */
|
1230 |
+
iCalUtilityFunctions::_stepdate( $wdate, $wdateYMD, $step);
|
1231 |
+
/* check if BYSETPOS is set for updating result array */
|
1232 |
+
if( $updateOK && isset( $recur['BYSETPOS'] )) {
|
1233 |
+
$bysetpos = FALSE;
|
1234 |
+
if( isset( $recur['FREQ'] ) && ( 'YEARLY' == $recur['FREQ'] ) &&
|
1235 |
+
( $bysetposYold != $wdate['year'] )) {
|
1236 |
+
$bysetpos = TRUE;
|
1237 |
+
$bysetposYold = $wdate['year'];
|
1238 |
+
}
|
1239 |
+
elseif( isset( $recur['FREQ'] ) && ( 'MONTHLY' == $recur['FREQ'] &&
|
1240 |
+
(( $bysetposYold != $wdate['year'] ) || ( $bysetposMold != $wdate['month'] )))) {
|
1241 |
+
$bysetpos = TRUE;
|
1242 |
+
$bysetposYold = $wdate['year'];
|
1243 |
+
$bysetposMold = $wdate['month'];
|
1244 |
+
}
|
1245 |
+
elseif( isset( $recur['FREQ'] ) && ( 'WEEKLY' == $recur['FREQ'] )) {
|
1246 |
+
$weekno = (int) date( 'W', mktime( 0, 0, $wkst, $wdate['month'], $wdate['day'], $wdate['year']));
|
1247 |
+
if( $bysetposWold != $weekno ) {
|
1248 |
+
$bysetposWold = $weekno;
|
1249 |
+
$bysetpos = TRUE;
|
1250 |
+
}
|
1251 |
+
}
|
1252 |
+
elseif( isset( $recur['FREQ'] ) && ( 'DAILY' == $recur['FREQ'] ) &&
|
1253 |
+
(( $bysetposYold != $wdate['year'] ) ||
|
1254 |
+
( $bysetposMold != $wdate['month'] ) ||
|
1255 |
+
( $bysetposDold != $wdate['day'] ))) {
|
1256 |
+
$bysetpos = TRUE;
|
1257 |
+
$bysetposYold = $wdate['year'];
|
1258 |
+
$bysetposMold = $wdate['month'];
|
1259 |
+
$bysetposDold = $wdate['day'];
|
1260 |
+
}
|
1261 |
+
if( $bysetpos ) {
|
1262 |
+
if( isset( $recur['BYWEEKNO'] )) {
|
1263 |
+
$bysetposarr1 = & $bysetposw1;
|
1264 |
+
$bysetposarr2 = & $bysetposw2;
|
1265 |
+
}
|
1266 |
+
else {
|
1267 |
+
$bysetposarr1 = & $bysetposymd1;
|
1268 |
+
$bysetposarr2 = & $bysetposymd2;
|
1269 |
+
}
|
1270 |
+
|
1271 |
+
foreach( $recur['BYSETPOS'] as $ix ) {
|
1272 |
+
if( 0 > $ix ) // both positive and negative BYSETPOS allowed
|
1273 |
+
$ix = ( count( $bysetposarr1 ) + $ix + 1);
|
1274 |
+
$ix--;
|
1275 |
+
if( isset( $bysetposarr1[$ix] )) {
|
1276 |
+
if( $fcnStartYMD <= $bysetposarr1[$ix] ) { // only output within period
|
1277 |
+
// $testweekno = (int) date( 'W', mktime( 0, 0, $wkst, (int) substr( $bysetposarr1[$ix], 4, 2 ), (int) substr( $bysetposarr1[$ix], 6, 2 ), (int) substr( $bysetposarr1[$ix], 0, 3 ))); // test ###
|
1278 |
+
// echo " testYMD (weekno)=$bysetposarr1[$ix] ($testweekno)"; // test ###
|
1279 |
+
$result[$bysetposarr1[$ix]] = TRUE;
|
1280 |
+
}
|
1281 |
+
$countcnt++;
|
1282 |
+
}
|
1283 |
+
if( isset( $recur['COUNT'] ) && ( $countcnt >= $recur['COUNT'] ))
|
1284 |
+
break;
|
1285 |
+
}
|
1286 |
+
// echo "<br>\n"; // test ###
|
1287 |
+
$bysetposarr1 = $bysetposarr2;
|
1288 |
+
$bysetposarr2 = array();
|
1289 |
+
} // end if( $bysetpos )
|
1290 |
+
} // end if( $updateOK && isset( $recur['BYSETPOS'] ))
|
1291 |
+
} // end while( TRUE )
|
1292 |
+
// echo 'output='.str_replace( array( PHP_EOL, ' ' ), '', var_export( $result, TRUE ))."<br> \n"; // test ###
|
1293 |
+
}
|
1294 |
+
/**
|
1295 |
+
* _recur2date help function, checking BYDAY (etc) hits
|
1296 |
+
*
|
1297 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1298 |
+
* @since 2.6.12 - 2011-01-03
|
1299 |
+
* @param array $BYvalue
|
1300 |
+
* @param int $upValue
|
1301 |
+
* @param int $downValue
|
1302 |
+
* @return bool
|
1303 |
+
*/
|
1304 |
+
public static function _recurBYcntcheck( $BYvalue, $upValue, $downValue ) {
|
1305 |
+
if( is_array( $BYvalue ) &&
|
1306 |
+
( in_array( $upValue, $BYvalue ) || in_array( $downValue, $BYvalue )))
|
1307 |
+
return TRUE;
|
1308 |
+
elseif(( $BYvalue == $upValue ) || ( $BYvalue == $downValue ))
|
1309 |
+
return TRUE;
|
1310 |
+
else
|
1311 |
+
return FALSE;
|
1312 |
+
}
|
1313 |
+
/**
|
1314 |
+
* _recur2date help function, (re-)calculate internal index
|
1315 |
+
*
|
1316 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1317 |
+
* @since 2.6.12 - 2011-01-03
|
1318 |
+
* @param string $freq
|
1319 |
+
* @param array $date
|
1320 |
+
* @param int $wkst
|
1321 |
+
* @return bool
|
1322 |
+
*/
|
1323 |
+
public static function _recurIntervalIx( $freq, $date, $wkst ) {
|
1324 |
+
/* create interval index */
|
1325 |
+
switch( $freq ) {
|
1326 |
+
case 'YEARLY':
|
1327 |
+
$intervalix = $date['year'];
|
1328 |
+
break;
|
1329 |
+
case 'MONTHLY':
|
1330 |
+
$intervalix = $date['year'].'-'.$date['month'];
|
1331 |
+
break;
|
1332 |
+
case 'WEEKLY':
|
1333 |
+
$intervalix = (int) date( 'W', mktime( 0, 0, $wkst, (int) $date['month'], (int) $date['day'], (int) $date['year'] ));
|
1334 |
+
break;
|
1335 |
+
case 'DAILY':
|
1336 |
+
default:
|
1337 |
+
$intervalix = $date['year'].'-'.$date['month'].'-'.$date['day'];
|
1338 |
+
break;
|
1339 |
+
}
|
1340 |
+
return $intervalix;
|
1341 |
+
}
|
1342 |
+
/**
|
1343 |
+
* sort recur dates
|
1344 |
+
*
|
1345 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1346 |
+
* @since 2.6.12 - 2011-01-03
|
1347 |
+
* @param array $bydaya
|
1348 |
+
* @param array $bydayb
|
1349 |
+
* @return int
|
1350 |
+
*/
|
1351 |
+
public static function _recurBydaySort( $bydaya, $bydayb ) {
|
1352 |
+
static $days = array( 'SU' => 0, 'MO' => 1, 'TU' => 2, 'WE' => 3, 'TH' => 4, 'FR' => 5, 'SA' => 6 );
|
1353 |
+
return ( $days[substr( $bydaya, -2 )] < $days[substr( $bydayb, -2 )] ) ? -1 : 1;
|
1354 |
+
}
|
1355 |
+
/**
|
1356 |
+
* convert input format for exrule and rrule to internal format
|
1357 |
+
*
|
1358 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1359 |
+
* @since 2.21.11 - 2015-03-10
|
1360 |
+
* @param array $rexrule
|
1361 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
1362 |
+
* @uses iCalUtilityFunctions::_isArrayTimestampDate()
|
1363 |
+
* @uses iCalUtilityFunctions::_timestamp2date()
|
1364 |
+
* @uses iCalUtilityFunctions::_chkDateArr()
|
1365 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
1366 |
+
* @uses iCalUtilityFunctions::$fmt
|
1367 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
1368 |
+
* @return array
|
1369 |
+
*/
|
1370 |
+
public static function _setRexrule( $rexrule ) {
|
1371 |
+
$input = array();
|
1372 |
+
if( empty( $rexrule ))
|
1373 |
+
return $input;
|
1374 |
+
$rexrule = array_change_key_case( $rexrule, CASE_UPPER );
|
1375 |
+
foreach( $rexrule as $rexrulelabel => $rexrulevalue ) {
|
1376 |
+
if( 'UNTIL' != $rexrulelabel )
|
1377 |
+
$input[$rexrulelabel] = $rexrulevalue;
|
1378 |
+
else {
|
1379 |
+
iCalUtilityFunctions::_strDate2arr( $rexrulevalue );
|
1380 |
+
if( iCalUtilityFunctions::_isArrayTimestampDate( $rexrulevalue )) // timestamp, always date-time UTC
|
1381 |
+
$input[$rexrulelabel] = iCalUtilityFunctions::_timestamp2date( $rexrulevalue, 7, 'UTC' );
|
1382 |
+
elseif( iCalUtilityFunctions::_isArrayDate( $rexrulevalue )) { // date or UTC date-time
|
1383 |
+
$parno = ( isset( $rexrulevalue['hour'] ) || isset( $rexrulevalue[4] )) ? 7 : 3;
|
1384 |
+
$d = iCalUtilityFunctions::_chkDateArr( $rexrulevalue, $parno );
|
1385 |
+
if(( 3 < $parno ) && isset( $d['tz'] ) && ( 'Z' != $d['tz'] ) && iCalUtilityFunctions::_isOffset( $d['tz'] )) {
|
1386 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $d['tz'] );
|
1387 |
+
$input[$rexrulelabel] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1388 |
+
unset( $input[$rexrulelabel]['unparsedtext'] );
|
1389 |
+
}
|
1390 |
+
else
|
1391 |
+
$input[$rexrulelabel] = $d;
|
1392 |
+
}
|
1393 |
+
elseif( 8 <= strlen( trim( $rexrulevalue ))) { // ex. textual date-time 2006-08-03 10:12:18 => UTC
|
1394 |
+
$input[$rexrulelabel] = iCalUtilityFunctions::_strdate2date( $rexrulevalue );
|
1395 |
+
unset( $input['$rexrulelabel']['unparsedtext'] );
|
1396 |
+
}
|
1397 |
+
if(( 3 < count( $input[$rexrulelabel] )) && !isset( $input[$rexrulelabel]['tz'] ))
|
1398 |
+
$input[$rexrulelabel]['tz'] = 'Z';
|
1399 |
+
}
|
1400 |
+
}
|
1401 |
+
/* set recurrence rule specification in rfc2445 order */
|
1402 |
+
$input2 = array();
|
1403 |
+
if( isset( $input['FREQ'] ))
|
1404 |
+
$input2['FREQ'] = $input['FREQ'];
|
1405 |
+
if( isset( $input['UNTIL'] ))
|
1406 |
+
$input2['UNTIL'] = $input['UNTIL'];
|
1407 |
+
elseif( isset( $input['COUNT'] ))
|
1408 |
+
$input2['COUNT'] = $input['COUNT'];
|
1409 |
+
if( isset( $input['INTERVAL'] ))
|
1410 |
+
$input2['INTERVAL'] = $input['INTERVAL'];
|
1411 |
+
if( isset( $input['BYSECOND'] ))
|
1412 |
+
$input2['BYSECOND'] = $input['BYSECOND'];
|
1413 |
+
if( isset( $input['BYMINUTE'] ))
|
1414 |
+
$input2['BYMINUTE'] = $input['BYMINUTE'];
|
1415 |
+
if( isset( $input['BYHOUR'] ))
|
1416 |
+
$input2['BYHOUR'] = $input['BYHOUR'];
|
1417 |
+
if( isset( $input['BYDAY'] )) {
|
1418 |
+
if( !is_array( $input['BYDAY'] )) // ensure upper case.. .
|
1419 |
+
$input2['BYDAY'] = strtoupper( $input['BYDAY'] );
|
1420 |
+
else {
|
1421 |
+
foreach( $input['BYDAY'] as $BYDAYx => $BYDAYv ) {
|
1422 |
+
if( 'DAY' == strtoupper( $BYDAYx ))
|
1423 |
+
$input2['BYDAY']['DAY'] = strtoupper( $BYDAYv );
|
1424 |
+
elseif( !is_array( $BYDAYv )) {
|
1425 |
+
$input2['BYDAY'][$BYDAYx] = $BYDAYv;
|
1426 |
+
}
|
1427 |
+
else {
|
1428 |
+
foreach( $BYDAYv as $BYDAYx2 => $BYDAYv2 ) {
|
1429 |
+
if( 'DAY' == strtoupper( $BYDAYx2 ))
|
1430 |
+
$input2['BYDAY'][$BYDAYx]['DAY'] = strtoupper( $BYDAYv2 );
|
1431 |
+
else
|
1432 |
+
$input2['BYDAY'][$BYDAYx][$BYDAYx2] = $BYDAYv2;
|
1433 |
+
}
|
1434 |
+
}
|
1435 |
+
}
|
1436 |
+
}
|
1437 |
+
}
|
1438 |
+
if( isset( $input['BYMONTHDAY'] ))
|
1439 |
+
$input2['BYMONTHDAY'] = $input['BYMONTHDAY'];
|
1440 |
+
if( isset( $input['BYYEARDAY'] ))
|
1441 |
+
$input2['BYYEARDAY'] = $input['BYYEARDAY'];
|
1442 |
+
if( isset( $input['BYWEEKNO'] ))
|
1443 |
+
$input2['BYWEEKNO'] = $input['BYWEEKNO'];
|
1444 |
+
if( isset( $input['BYMONTH'] ))
|
1445 |
+
$input2['BYMONTH'] = $input['BYMONTH'];
|
1446 |
+
if( isset( $input['BYSETPOS'] ))
|
1447 |
+
$input2['BYSETPOS'] = $input['BYSETPOS'];
|
1448 |
+
if( isset( $input['WKST'] ))
|
1449 |
+
$input2['WKST'] = $input['WKST'];
|
1450 |
+
return $input2;
|
1451 |
+
}
|
1452 |
+
/**
|
1453 |
+
* convert format for input date to internal date with parameters
|
1454 |
+
*
|
1455 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1456 |
+
* @since 2.21.11 - 2015-03-21
|
1457 |
+
* @param mixed $year
|
1458 |
+
* @param mixed $month optional
|
1459 |
+
* @param int $day optional
|
1460 |
+
* @param int $hour optional
|
1461 |
+
* @param int $min optional
|
1462 |
+
* @param int $sec optional
|
1463 |
+
* @param string $tz optional
|
1464 |
+
* @param array $params optional
|
1465 |
+
* @param string $caller optional
|
1466 |
+
* @param string $objName optional
|
1467 |
+
* @param string $tzid optional
|
1468 |
+
* @uses iCalUtilityFunctions::$tzComps
|
1469 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
1470 |
+
* @uses iCalUtilityFunctions::_isArrayDate()
|
1471 |
+
* @uses iCalUtilityFunctions::_chkDateArr()
|
1472 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
1473 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1474 |
+
* @uses iCalUtilityFunctions::_existRem()
|
1475 |
+
* @uses iCalUtilityFunctions::$fmt
|
1476 |
+
* @uses iCalUtilityFunctions::_isArrayTimestampDate()
|
1477 |
+
* @uses iCalUtilityFunctions::_timestamp2date()
|
1478 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
1479 |
+
* @return array
|
1480 |
+
*/
|
1481 |
+
public static function _setDate( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE, $caller=null, $objName=null, $tzid=FALSE ) {
|
1482 |
+
$input = $parno = null;
|
1483 |
+
$localtime = (( 'dtstart' == $caller ) && in_array( $objName, iCalUtilityFunctions::$tzComps )) ? TRUE : FALSE;
|
1484 |
+
iCalUtilityFunctions::_strDate2arr( $year );
|
1485 |
+
if( iCalUtilityFunctions::_isArrayDate( $year )) {
|
1486 |
+
$input['value'] = iCalUtilityFunctions::_chkDateArr( $year, FALSE ); //$parno );
|
1487 |
+
if( 100 > $input['value']['year'] )
|
1488 |
+
$input['value']['year'] += 2000;
|
1489 |
+
if( $localtime )
|
1490 |
+
unset( $month['VALUE'], $month['TZID'] );
|
1491 |
+
elseif( !isset( $month['TZID'] ) && isset( $tzid ))
|
1492 |
+
$month['TZID'] = $tzid;
|
1493 |
+
if( isset( $input['value']['tz'] ) && iCalUtilityFunctions::_isOffset( $input['value']['tz'] ))
|
1494 |
+
unset( $month['TZID'] );
|
1495 |
+
elseif( !isset( $input['value']['tz'] ) && isset( $month['TZID'] ) && iCalUtilityFunctions::_isOffset( $month['TZID'] )) {
|
1496 |
+
$input['value']['tz'] = $month['TZID'];
|
1497 |
+
unset( $month['TZID'] );
|
1498 |
+
}
|
1499 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
|
1500 |
+
$hitval = ( isset( $input['value']['tz'] )) ? 7 : 6;
|
1501 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval );
|
1502 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3, count( $input['value'] ), $parno );
|
1503 |
+
if( 6 > $parno )
|
1504 |
+
unset( $input['value']['tz'], $input['params']['TZID'], $tzid );
|
1505 |
+
if(( 6 <= $parno ) && isset( $input['value']['tz'] ) && ( 'Z' != $input['value']['tz'] ) && iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
|
1506 |
+
$d = $input['value'];
|
1507 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $d['tz'] );
|
1508 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, $parno );
|
1509 |
+
unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
|
1510 |
+
}
|
1511 |
+
if( isset( $input['value']['tz'] ) && !iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
|
1512 |
+
$input['params']['TZID'] = $input['value']['tz'];
|
1513 |
+
unset( $input['value']['tz'] );
|
1514 |
+
}
|
1515 |
+
} // end if( iCalUtilityFunctions::_isArrayDate( $year ))
|
1516 |
+
elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year )) {
|
1517 |
+
if( $localtime ) unset ( $month['VALUE'], $month['TZID'] );
|
1518 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
|
1519 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3 );
|
1520 |
+
$hitval = 7;
|
1521 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval, $parno );
|
1522 |
+
if( isset( $year['tz'] ) && !empty( $year['tz'] )) {
|
1523 |
+
if( !iCalUtilityFunctions::_isOffset( $year['tz'] )) {
|
1524 |
+
$input['params']['TZID'] = $year['tz'];
|
1525 |
+
unset( $year['tz'], $tzid );
|
1526 |
+
}
|
1527 |
+
else {
|
1528 |
+
if( isset( $input['params']['TZID'] ) && !empty( $input['params']['TZID'] )) {
|
1529 |
+
if( !iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
|
1530 |
+
unset( $tzid );
|
1531 |
+
else
|
1532 |
+
unset( $input['params']['TZID']);
|
1533 |
+
}
|
1534 |
+
elseif( isset( $tzid ) && !iCalUtilityFunctions::_isOffset( $tzid ))
|
1535 |
+
$input['params']['TZID'] = $tzid;
|
1536 |
+
}
|
1537 |
+
}
|
1538 |
+
elseif( isset( $input['params']['TZID'] ) && !empty( $input['params']['TZID'] )) {
|
1539 |
+
if( iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
|
1540 |
+
$year['tz'] = $input['params']['TZID'];
|
1541 |
+
unset( $input['params']['TZID']);
|
1542 |
+
if( isset( $tzid ) && !empty( $tzid ) && !iCalUtilityFunctions::_isOffset( $tzid ))
|
1543 |
+
$input['params']['TZID'] = $tzid;
|
1544 |
+
}
|
1545 |
+
}
|
1546 |
+
elseif( isset( $tzid ) && !empty( $tzid )) {
|
1547 |
+
if( iCalUtilityFunctions::_isOffset( $tzid )) {
|
1548 |
+
$year['tz'] = $tzid;
|
1549 |
+
unset( $input['params']['TZID']);
|
1550 |
+
}
|
1551 |
+
else
|
1552 |
+
$input['params']['TZID'] = $tzid;
|
1553 |
+
}
|
1554 |
+
$input['value'] = iCalUtilityFunctions::_timestamp2date( $year, $parno );
|
1555 |
+
} // end elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year ))
|
1556 |
+
elseif( 8 <= strlen( trim((string) $year ))) { // ex. 2006-08-03 10:12:18 [[[+/-]1234[56]] / timezone]
|
1557 |
+
if( $localtime )
|
1558 |
+
unset( $month['VALUE'], $month['TZID'] );
|
1559 |
+
elseif( !isset( $month['TZID'] ) && !empty( $tzid ))
|
1560 |
+
$month['TZID'] = $tzid;
|
1561 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
|
1562 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', 7, $parno );
|
1563 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3, $parno, $parno );
|
1564 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $year, $parno );
|
1565 |
+
if( 3 == $parno )
|
1566 |
+
unset( $input['value']['tz'], $input['params']['TZID'] );
|
1567 |
+
unset( $input['value']['unparsedtext'] );
|
1568 |
+
if( isset( $input['value']['tz'] )) {
|
1569 |
+
if( iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
|
1570 |
+
$d = $input['value'];
|
1571 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $d['tz'] );
|
1572 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1573 |
+
unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
|
1574 |
+
}
|
1575 |
+
else {
|
1576 |
+
$input['params']['TZID'] = $input['value']['tz'];
|
1577 |
+
unset( $input['value']['tz'] );
|
1578 |
+
}
|
1579 |
+
}
|
1580 |
+
elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
|
1581 |
+
$d = $input['value'];
|
1582 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $input['params']['TZID'] );
|
1583 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1584 |
+
unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
|
1585 |
+
}
|
1586 |
+
} // end elseif( 8 <= strlen( trim((string) $year )))
|
1587 |
+
else {
|
1588 |
+
if( is_array( $params ))
|
1589 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' ));
|
1590 |
+
elseif( is_array( $tz )) {
|
1591 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $tz, array( 'VALUE' => 'DATE-TIME' ));
|
1592 |
+
$tz = FALSE;
|
1593 |
+
}
|
1594 |
+
elseif( is_array( $hour )) {
|
1595 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $hour, array( 'VALUE' => 'DATE-TIME' ));
|
1596 |
+
$hour = $min = $sec = $tz = FALSE;
|
1597 |
+
}
|
1598 |
+
if( $localtime )
|
1599 |
+
unset ( $input['params']['VALUE'], $input['params']['TZID'] );
|
1600 |
+
elseif( !isset( $tz ) && !isset( $input['params']['TZID'] ) && !empty( $tzid ))
|
1601 |
+
$input['params']['TZID'] = $tzid;
|
1602 |
+
elseif( isset( $tz ) && iCalUtilityFunctions::_isOffset( $tz ))
|
1603 |
+
unset( $input['params']['TZID'] );
|
1604 |
+
elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
|
1605 |
+
$tz = $input['params']['TZID'];
|
1606 |
+
unset( $input['params']['TZID'] );
|
1607 |
+
}
|
1608 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3 );
|
1609 |
+
$hitval = ( iCalUtilityFunctions::_isOffset( $tz )) ? 7 : 6;
|
1610 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval, $parno, $parno );
|
1611 |
+
$input['value'] = array( 'year' => $year, 'month' => $month, 'day' => $day );
|
1612 |
+
if( 3 != $parno ) {
|
1613 |
+
$input['value']['hour'] = ( $hour ) ? $hour : '0';
|
1614 |
+
$input['value']['min'] = ( $min ) ? $min : '0';
|
1615 |
+
$input['value']['sec'] = ( $sec ) ? $sec : '0';
|
1616 |
+
if( !empty( $tz ))
|
1617 |
+
$input['value']['tz'] = $tz;
|
1618 |
+
$strdate = iCalUtilityFunctions::_date2strdate( $input['value'], $parno );
|
1619 |
+
if( !empty( $tz ) && !iCalUtilityFunctions::_isOffset( $tz ))
|
1620 |
+
$strdate .= ( 'Z' == $tz ) ? $tz : ' '.$tz;
|
1621 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, $parno );
|
1622 |
+
unset( $input['value']['unparsedtext'] );
|
1623 |
+
if( isset( $input['value']['tz'] )) {
|
1624 |
+
if( iCalUtilityFunctions::_isOffset( $input['value']['tz'] )) {
|
1625 |
+
$d = $input['value'];
|
1626 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $d['tz'] );
|
1627 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1628 |
+
unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
|
1629 |
+
}
|
1630 |
+
else {
|
1631 |
+
$input['params']['TZID'] = $input['value']['tz'];
|
1632 |
+
unset( $input['value']['tz'] );
|
1633 |
+
}
|
1634 |
+
}
|
1635 |
+
elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
|
1636 |
+
$d = $input['value'];
|
1637 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $input['params']['TZID'] );
|
1638 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1639 |
+
unset( $input['value']['unparsedtext'], $input['params']['TZID'] );
|
1640 |
+
}
|
1641 |
+
}
|
1642 |
+
} // end else (i.e. using all arguments)
|
1643 |
+
if(( 3 == $parno ) || ( isset( $input['params']['VALUE'] ) && ( 'DATE' == $input['params']['VALUE'] ))) {
|
1644 |
+
$input['params']['VALUE'] = 'DATE';
|
1645 |
+
unset( $input['value']['hour'], $input['value']['min'], $input['value']['sec'], $input['value']['tz'], $input['params']['TZID'] );
|
1646 |
+
}
|
1647 |
+
elseif( isset( $input['params']['TZID'] )) {
|
1648 |
+
if(( 'UTC' == strtoupper( $input['params']['TZID'] )) || ( 'GMT' == strtoupper( $input['params']['TZID'] ))) {
|
1649 |
+
$input['value']['tz'] = 'Z';
|
1650 |
+
unset( $input['params']['TZID'] );
|
1651 |
+
}
|
1652 |
+
else
|
1653 |
+
unset( $input['value']['tz'] );
|
1654 |
+
}
|
1655 |
+
elseif( isset( $input['value']['tz'] )) {
|
1656 |
+
if(( 'UTC' == strtoupper( $input['value']['tz'] )) || ( 'GMT' == strtoupper( $input['value']['tz'] )))
|
1657 |
+
$input['value']['tz'] = 'Z';
|
1658 |
+
if( 'Z' != $input['value']['tz'] ) {
|
1659 |
+
$input['params']['TZID'] = $input['value']['tz'];
|
1660 |
+
unset( $input['value']['tz'] );
|
1661 |
+
}
|
1662 |
+
else
|
1663 |
+
unset( $input['params']['TZID'] );
|
1664 |
+
}
|
1665 |
+
if( $localtime )
|
1666 |
+
unset( $input['value']['tz'], $input['params']['TZID'] );
|
1667 |
+
return $input;
|
1668 |
+
}
|
1669 |
+
/**
|
1670 |
+
* convert format for input date (UTC) to internal date with parameters
|
1671 |
+
*
|
1672 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1673 |
+
* @since 2.21.11 - 2015-03-10
|
1674 |
+
* @param mixed $year
|
1675 |
+
* @param mixed $month optional
|
1676 |
+
* @param int $day optional
|
1677 |
+
* @param int $hour optional
|
1678 |
+
* @param int $min optional
|
1679 |
+
* @param int $sec optional
|
1680 |
+
* @param array $params optional
|
1681 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
1682 |
+
* @uses iCalUtilityFunctions::_isArrayDate()
|
1683 |
+
* @uses iCalUtilityFunctions::_chkDateArr()
|
1684 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1685 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
1686 |
+
* @uses iCalUtilityFunctions::$fmt
|
1687 |
+
* @uses iCalUtilityFunctions::_strdate2date()
|
1688 |
+
* @uses iCalUtilityFunctions::_isArrayTimestampDate()
|
1689 |
+
* @uses iCalUtilityFunctions::_timestamp2date()
|
1690 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
1691 |
+
* @uses iCalUtilityFunctions::_existRem()
|
1692 |
+
* @return array
|
1693 |
+
*/
|
1694 |
+
public static function _setDate2( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
|
1695 |
+
$input = null;
|
1696 |
+
iCalUtilityFunctions::_strDate2arr( $year );
|
1697 |
+
if( iCalUtilityFunctions::_isArrayDate( $year )) {
|
1698 |
+
$input['value'] = iCalUtilityFunctions::_chkDateArr( $year, 7 );
|
1699 |
+
if( isset( $input['value']['year'] ) && ( 100 > $input['value']['year'] ))
|
1700 |
+
$input['value']['year'] += 2000;
|
1701 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
|
1702 |
+
unset( $input['params']['VALUE'] );
|
1703 |
+
if( isset( $input['value']['tz'] ) && iCalUtilityFunctions::_isOffset( $input['value']['tz'] ))
|
1704 |
+
$tzid = $input['value']['tz'];
|
1705 |
+
elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
|
1706 |
+
$tzid = $input['params']['TZID'];
|
1707 |
+
else
|
1708 |
+
$tzid = '';
|
1709 |
+
unset( $input['params']['VALUE'], $input['params']['TZID'] );
|
1710 |
+
if( !empty( $tzid ) && ( 'Z' != $tzid ) && iCalUtilityFunctions::_isOffset( $tzid )) {
|
1711 |
+
$d = $input['value'];
|
1712 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $tzid );
|
1713 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1714 |
+
unset( $input['value']['unparsedtext'] );
|
1715 |
+
}
|
1716 |
+
}
|
1717 |
+
elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year )) {
|
1718 |
+
if( isset( $year['tz'] ) && ! iCalUtilityFunctions::_isOffset( $year['tz'] ))
|
1719 |
+
$year['tz'] = 'UTC';
|
1720 |
+
elseif( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
|
1721 |
+
$year['tz'] = $input['params']['TZID'];
|
1722 |
+
else
|
1723 |
+
$year['tz'] = 'UTC';
|
1724 |
+
$input['value'] = iCalUtilityFunctions::_timestamp2date( $year, 7 );
|
1725 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
|
1726 |
+
unset( $input['params']['VALUE'], $input['params']['TZID'] );
|
1727 |
+
}
|
1728 |
+
elseif( 8 <= strlen( trim((string) $year ))) { // ex. 2006-08-03 10:12:18
|
1729 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $year, 7 );
|
1730 |
+
unset( $input['value']['unparsedtext'] );
|
1731 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
|
1732 |
+
if(( !isset( $input['value']['tz'] ) || empty( $input['value']['tz'] )) && isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] )) {
|
1733 |
+
$d = $input['value'];
|
1734 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['YmdHise'], (int) $d['year'], (int) $d['month'], (int) $d['day'], (int) $d['hour'], (int) $d['min'], (int) $d['sec'], $input['params']['TZID'] );
|
1735 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1736 |
+
unset( $input['value']['unparsedtext'] );
|
1737 |
+
}
|
1738 |
+
unset( $input['params']['VALUE'], $input['params']['TZID'] );
|
1739 |
+
}
|
1740 |
+
else {
|
1741 |
+
$input['value'] = array( 'year' => $year
|
1742 |
+
, 'month' => $month
|
1743 |
+
, 'day' => $day
|
1744 |
+
, 'hour' => $hour
|
1745 |
+
, 'min' => $min
|
1746 |
+
, 'sec' => $sec );
|
1747 |
+
if( isset( $tz )) $input['value']['tz'] = $tz;
|
1748 |
+
if(( isset( $tz ) && iCalUtilityFunctions::_isOffset( $tz )) ||
|
1749 |
+
( isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))) {
|
1750 |
+
if( !isset( $tz ) && isset( $input['params']['TZID'] ) && iCalUtilityFunctions::_isOffset( $input['params']['TZID'] ))
|
1751 |
+
$input['value']['tz'] = $input['params']['TZID'];
|
1752 |
+
unset( $input['params']['TZID'] );
|
1753 |
+
$strdate = iCalUtilityFunctions::_date2strdate( $input['value'], 7 );
|
1754 |
+
$input['value'] = iCalUtilityFunctions::_strdate2date( $strdate, 7 );
|
1755 |
+
unset( $input['value']['unparsedtext'] );
|
1756 |
+
}
|
1757 |
+
$input['params'] = iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' ));
|
1758 |
+
unset( $input['params']['VALUE'] );
|
1759 |
+
}
|
1760 |
+
$parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', 7 ); // remove default
|
1761 |
+
if( !isset( $input['value']['hour'] )) $input['value']['hour'] = 0;
|
1762 |
+
if( !isset( $input['value']['min'] )) $input['value']['min'] = 0;
|
1763 |
+
if( !isset( $input['value']['sec'] )) $input['value']['sec'] = 0;
|
1764 |
+
$input['value']['tz'] = 'Z';
|
1765 |
+
return $input;
|
1766 |
+
}
|
1767 |
+
/**
|
1768 |
+
* check index and set (an indexed) content in multiple value array
|
1769 |
+
*
|
1770 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1771 |
+
* @since 2.6.12 - 2011-01-03
|
1772 |
+
* @param array $valArr
|
1773 |
+
* @param mixed $value
|
1774 |
+
* @param array $params
|
1775 |
+
* @param array $defaults
|
1776 |
+
* @param int $index
|
1777 |
+
* @uses iCalUtilityFunctions::_setParams()
|
1778 |
+
* @return void
|
1779 |
+
*/
|
1780 |
+
public static function _setMval( & $valArr, $value, $params=FALSE, $defaults=FALSE, $index=FALSE ) {
|
1781 |
+
if( !is_array( $valArr )) $valArr = array();
|
1782 |
+
if( $index )
|
1783 |
+
$index = $index - 1;
|
1784 |
+
elseif( 0 < count( $valArr )) {
|
1785 |
+
$keys = array_keys( $valArr );
|
1786 |
+
$index = end( $keys ) + 1;
|
1787 |
+
}
|
1788 |
+
else
|
1789 |
+
$index = 0;
|
1790 |
+
$valArr[$index] = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params, $defaults ));
|
1791 |
+
ksort( $valArr );
|
1792 |
+
}
|
1793 |
+
/**
|
1794 |
+
* set input (formatted) parameters- component property attributes
|
1795 |
+
*
|
1796 |
+
* default parameters can be set, if missing
|
1797 |
+
*
|
1798 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1799 |
+
* @since 2.18.10 - 2013-09-04
|
1800 |
+
* @param array $params
|
1801 |
+
* @param array $defaults
|
1802 |
+
* @return array
|
1803 |
+
*/
|
1804 |
+
public static function _setParams( $params, $defaults=FALSE ) {
|
1805 |
+
if( !is_array( $params))
|
1806 |
+
$params = array();
|
1807 |
+
$input = array();
|
1808 |
+
$params = array_change_key_case( $params, CASE_UPPER );
|
1809 |
+
foreach( $params as $paramKey => $paramValue ) {
|
1810 |
+
if( is_array( $paramValue )) {
|
1811 |
+
foreach( $paramValue as $pkey => $pValue ) {
|
1812 |
+
if(( '"' == substr( $pValue, 0, 1 )) && ( '"' == substr( $pValue, -1 )))
|
1813 |
+
$paramValue[$pkey] = substr( $pValue, 1, ( strlen( $pValue ) - 2 ));
|
1814 |
+
}
|
1815 |
+
}
|
1816 |
+
elseif(( '"' == substr( $paramValue, 0, 1 )) && ( '"' == substr( $paramValue, -1 )))
|
1817 |
+
$paramValue = substr( $paramValue, 1, ( strlen( $paramValue ) - 2 ));
|
1818 |
+
if( 'VALUE' == $paramKey )
|
1819 |
+
$input['VALUE'] = strtoupper( $paramValue );
|
1820 |
+
else
|
1821 |
+
$input[$paramKey] = $paramValue;
|
1822 |
+
}
|
1823 |
+
if( is_array( $defaults )) {
|
1824 |
+
foreach( $defaults as $paramKey => $paramValue ) {
|
1825 |
+
if( !isset( $input[$paramKey] ))
|
1826 |
+
$input[$paramKey] = $paramValue;
|
1827 |
+
}
|
1828 |
+
}
|
1829 |
+
return (0 < count( $input )) ? $input : null;
|
1830 |
+
}
|
1831 |
+
/**
|
1832 |
+
* set sort arguments/parameters in component
|
1833 |
+
*
|
1834 |
+
*
|
1835 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1836 |
+
* @since 2.21.11 - 2015-03-21
|
1837 |
+
* @param object $c valendar component
|
1838 |
+
* @param string $sortArg
|
1839 |
+
* @uses calendarComponent::$srtk
|
1840 |
+
* @uses calendarComponent::$objName
|
1841 |
+
* @uses calendarComponent::$getProperty()
|
1842 |
+
* @uses iCalUtilityFunctions::$mProps1
|
1843 |
+
* @uses calendarComponent::_getProperties()
|
1844 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
1845 |
+
* @return void
|
1846 |
+
*/
|
1847 |
+
public static function _setSortArgs( $c, $sortArg=FALSE ) {
|
1848 |
+
$c->srtk = array( '0', '0', '0', '0' );
|
1849 |
+
if( 'vtimezone' == $c->objName ) {
|
1850 |
+
if( FALSE === ( $c->srtk[0] = $c->getProperty( 'tzid' )))
|
1851 |
+
$c->srtk[0] = 0;
|
1852 |
+
return;
|
1853 |
+
}
|
1854 |
+
elseif( $sortArg ) {
|
1855 |
+
if( in_array( $sortArg, iCalUtilityFunctions::$mProps1 )) {
|
1856 |
+
$propValues = array();
|
1857 |
+
$c->_getProperties( $sortArg, $propValues );
|
1858 |
+
if( !empty( $propValues )) {
|
1859 |
+
$sk = array_keys( $propValues );
|
1860 |
+
$c->srtk[0] = $sk[0];
|
1861 |
+
if( 'RELATED-TO' == $sortArg )
|
1862 |
+
$c->srtk[0] .= $c->getProperty( 'uid' );
|
1863 |
+
}
|
1864 |
+
elseif( 'RELATED-TO' == $sortArg )
|
1865 |
+
$c->srtk[0] = $c->getProperty( 'uid' );
|
1866 |
+
}
|
1867 |
+
elseif( FALSE !== ( $d = $c->getProperty( $sortArg ))) {
|
1868 |
+
$c->srtk[0] = $d;
|
1869 |
+
if( 'UID' == $sortArg ) {
|
1870 |
+
if( FALSE !== ( $d = $c->getProperty( 'recurrence-id' ))) {
|
1871 |
+
$c->srtk[1] = iCalUtilityFunctions::_date2strdate( $d );
|
1872 |
+
if( FALSE === ( $c->srtk[2] = $c->getProperty( 'sequence' )))
|
1873 |
+
$c->srtk[2] = PHP_INT_MAX;
|
1874 |
+
}
|
1875 |
+
else
|
1876 |
+
$c->srtk[1] = $c->srtk[2] = PHP_INT_MAX;
|
1877 |
+
}
|
1878 |
+
}
|
1879 |
+
return;
|
1880 |
+
} // end elseif( $sortArg )
|
1881 |
+
if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DTSTART' ))) {
|
1882 |
+
$c->srtk[0] = iCalUtilityFunctions::_strdate2date( $d[1] );
|
1883 |
+
unset( $c->srtk[0]['unparsedtext'] );
|
1884 |
+
}
|
1885 |
+
elseif( FALSE === ( $c->srtk[0] = $c->getProperty( 'dtstart' )))
|
1886 |
+
$c->srtk[0] = 0; // sortkey 0 : dtstart
|
1887 |
+
if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DTEND' ))) {
|
1888 |
+
$c->srtk[1] = iCalUtilityFunctions::_strdate2date( $d[1] ); // sortkey 1 : dtend/due(/duration)
|
1889 |
+
unset( $c->srtk[1]['unparsedtext'] );
|
1890 |
+
}
|
1891 |
+
elseif( FALSE === ( $c->srtk[1] = $c->getProperty( 'dtend' ))) {
|
1892 |
+
if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DUE' ))) {
|
1893 |
+
$c->srtk[1] = iCalUtilityFunctions::_strdate2date( $d[1] );
|
1894 |
+
unset( $c->srtk[1]['unparsedtext'] );
|
1895 |
+
}
|
1896 |
+
elseif( FALSE === ( $c->srtk[1] = $c->getProperty( 'due' )))
|
1897 |
+
if( FALSE === ( $c->srtk[1] = $c->getProperty( 'duration', FALSE, FALSE, TRUE )))
|
1898 |
+
$c->srtk[1] = 0;
|
1899 |
+
}
|
1900 |
+
if( FALSE === ( $c->srtk[2] = $c->getProperty( 'created' ))) // sortkey 2 : created/dtstamp
|
1901 |
+
if( FALSE === ( $c->srtk[2] = $c->getProperty( 'dtstamp' )))
|
1902 |
+
$c->srtk[2] = 0;
|
1903 |
+
if( FALSE === ( $c->srtk[3] = $c->getProperty( 'uid' ))) // sortkey 3 : uid
|
1904 |
+
$c->srtk[3] = 0;
|
1905 |
+
}
|
1906 |
+
/**
|
1907 |
+
* break lines at pos 75
|
1908 |
+
*
|
1909 |
+
* Lines of text SHOULD NOT be longer than 75 octets, excluding the line
|
1910 |
+
* break. Long content lines SHOULD be split into a multiple line
|
1911 |
+
* representations using a line "folding" technique. That is, a long
|
1912 |
+
* line can be split between any two characters by inserting a CRLF
|
1913 |
+
* immediately followed by a single linear white space character (i.e.,
|
1914 |
+
* SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9). Any sequence
|
1915 |
+
* of CRLF followed immediately by a single linear white space character
|
1916 |
+
* is ignored (i.e., removed) when processing the content type.
|
1917 |
+
*
|
1918 |
+
* Edited 2007-08-26 by Anders Litzell, anders@litzell.se to fix bug where
|
1919 |
+
* the reserved expression "\n" in the arg $string could be broken up by the
|
1920 |
+
* folding of lines, causing ambiguity in the return string.
|
1921 |
+
*
|
1922 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1923 |
+
* @since 2.16.2 - 2012-12-18
|
1924 |
+
* @param string $string
|
1925 |
+
* @param string $nl
|
1926 |
+
* @return string
|
1927 |
+
*/
|
1928 |
+
public static function _size75( $string, $nl ) {
|
1929 |
+
$tmp = $string;
|
1930 |
+
$string = '';
|
1931 |
+
$cCnt = $x = 0;
|
1932 |
+
while( TRUE ) {
|
1933 |
+
if( !isset( $tmp[$x] )) {
|
1934 |
+
$string .= $nl; // loop breakes here
|
1935 |
+
break;
|
1936 |
+
}
|
1937 |
+
elseif(( 74 <= $cCnt ) && ( '\\' == $tmp[$x] ) && ( 'n' == $tmp[$x+1] )) {
|
1938 |
+
$string .= $nl.' \n'; // don't break lines inside '\n'
|
1939 |
+
$x += 2;
|
1940 |
+
if( !isset( $tmp[$x] )) {
|
1941 |
+
$string .= $nl;
|
1942 |
+
break;
|
1943 |
+
}
|
1944 |
+
$cCnt = 3;
|
1945 |
+
}
|
1946 |
+
elseif( 75 <= $cCnt ) {
|
1947 |
+
$string .= $nl.' ';
|
1948 |
+
$cCnt = 1;
|
1949 |
+
}
|
1950 |
+
$byte = ord( $tmp[$x] );
|
1951 |
+
$string .= $tmp[$x];
|
1952 |
+
switch( TRUE ) { // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
1953 |
+
case(( $byte >= 0x20 ) && ( $byte <= 0x7F )): // characters U-00000000 - U-0000007F (same as ASCII)
|
1954 |
+
$cCnt += 1;
|
1955 |
+
break; // add a one byte character
|
1956 |
+
case(( $byte & 0xE0) == 0xC0 ): // characters U-00000080 - U-000007FF, mask 110XXXXX
|
1957 |
+
if( isset( $tmp[$x+1] )) {
|
1958 |
+
$cCnt += 1;
|
1959 |
+
$string .= $tmp[$x+1];
|
1960 |
+
$x += 1; // add a two bytes character
|
1961 |
+
}
|
1962 |
+
break;
|
1963 |
+
case(( $byte & 0xF0 ) == 0xE0 ): // characters U-00000800 - U-0000FFFF, mask 1110XXXX
|
1964 |
+
if( isset( $tmp[$x+2] )) {
|
1965 |
+
$cCnt += 1;
|
1966 |
+
$string .= $tmp[$x+1].$tmp[$x+2];
|
1967 |
+
$x += 2; // add a three bytes character
|
1968 |
+
}
|
1969 |
+
break;
|
1970 |
+
case(( $byte & 0xF8 ) == 0xF0 ): // characters U-00010000 - U-001FFFFF, mask 11110XXX
|
1971 |
+
if( isset( $tmp[$x+3] )) {
|
1972 |
+
$cCnt += 1;
|
1973 |
+
$string .= $tmp[$x+1].$tmp[$x+2].$tmp[$x+3];
|
1974 |
+
$x += 3; // add a four bytes character
|
1975 |
+
}
|
1976 |
+
break;
|
1977 |
+
case(( $byte & 0xFC ) == 0xF8 ): // characters U-00200000 - U-03FFFFFF, mask 111110XX
|
1978 |
+
if( isset( $tmp[$x+4] )) {
|
1979 |
+
$cCnt += 1;
|
1980 |
+
$string .= $tmp[$x+1].$tmp[$x+2].$tmp[$x+3].$tmp[$x+4];
|
1981 |
+
$x += 4; // add a five bytes character
|
1982 |
+
}
|
1983 |
+
break;
|
1984 |
+
case(( $byte & 0xFE ) == 0xFC ): // characters U-04000000 - U-7FFFFFFF, mask 1111110X
|
1985 |
+
if( isset( $tmp[$x+5] )) {
|
1986 |
+
$cCnt += 1;
|
1987 |
+
$string .= $tmp[$x+1].$tmp[$x+2].$tmp[$x+3].$tmp[$x+4].$tmp[$x+5];
|
1988 |
+
$x += 5; // add a six bytes character
|
1989 |
+
}
|
1990 |
+
default: // add any other byte without counting up $cCnt
|
1991 |
+
break;
|
1992 |
+
} // end switch( TRUE )
|
1993 |
+
$x += 1; // next 'byte' to test
|
1994 |
+
} // end while( TRUE ) {
|
1995 |
+
return $string;
|
1996 |
+
}
|
1997 |
+
/**
|
1998 |
+
* sort callback function for exdate
|
1999 |
+
*
|
2000 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2001 |
+
* @since 2.21.11 - 2015-03-07
|
2002 |
+
* @param array $a
|
2003 |
+
* @param array $b
|
2004 |
+
* @uses iCalUtilityFunctions::$fmt
|
2005 |
+
* @return int
|
2006 |
+
*/
|
2007 |
+
public static function _sortExdate1( $a, $b ) {
|
2008 |
+
$as = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $a['year'], (int) $a['month'], (int) $a['day'] );
|
2009 |
+
$as .= ( isset( $a['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $a['hour'], (int) $a['min'], (int) $a['sec'] ) : '';
|
2010 |
+
$bs = sprintf( iCalUtilityFunctions::$fmt['His'], (int) $b['year'], (int) $b['month'], (int) $b['day'] );
|
2011 |
+
$bs .= ( isset( $b['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $b['hour'], (int) $b['min'], (int) $b['sec'] ) : '';
|
2012 |
+
return strcmp( $as, $bs );
|
2013 |
+
}
|
2014 |
+
/**
|
2015 |
+
* sort callback function for exdate
|
2016 |
+
*
|
2017 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2018 |
+
* @since 2.21.11 - 2015-03-07
|
2019 |
+
* @param array $a
|
2020 |
+
* @param array $b
|
2021 |
+
* @uses iCalUtilityFunctions::$fmt
|
2022 |
+
* @return int
|
2023 |
+
*/
|
2024 |
+
public static function _sortExdate2( $a, $b ) {
|
2025 |
+
$val = reset( $a['value'] );
|
2026 |
+
$as = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $val['year'], (int) $val['month'], (int) $val['day'] );
|
2027 |
+
$as .= ( isset( $val['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $val['hour'], (int) $val['min'], (int) $val['sec'] ) : '';
|
2028 |
+
$val = reset( $b['value'] );
|
2029 |
+
$bs = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $val['year'], (int) $val['month'], (int) $val['day'] );
|
2030 |
+
$bs .= ( isset( $val['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $val['hour'], (int) $val['min'], (int) $val['sec'] ) : '';
|
2031 |
+
return strcmp( $as, $bs );
|
2032 |
+
}
|
2033 |
+
/**
|
2034 |
+
* sort callback function for rdate
|
2035 |
+
*
|
2036 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2037 |
+
* @since 2.21.11 - 2015-03-07
|
2038 |
+
* @param array $a
|
2039 |
+
* @param array $b
|
2040 |
+
* @uses iCalUtilityFunctions::$fmt
|
2041 |
+
* @return int
|
2042 |
+
*/
|
2043 |
+
public static function _sortRdate1( $a, $b ) {
|
2044 |
+
$val = isset( $a['year'] ) ? $a : $a[0];
|
2045 |
+
$as = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $val['year'], (int) $val['month'], (int) $val['day'] );
|
2046 |
+
$as .= ( isset( $val['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $val['hour'], (int) $val['min'], (int) $val['sec'] ) : '';
|
2047 |
+
$val = isset( $b['year'] ) ? $b : $b[0];
|
2048 |
+
$bs = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $val['year'], (int) $val['month'], (int) $val['day'] );
|
2049 |
+
$bs .= ( isset( $val['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $val['hour'], (int) $val['min'], (int) $val['sec'] ) : '';
|
2050 |
+
return strcmp( $as, $bs );
|
2051 |
+
}
|
2052 |
+
/**
|
2053 |
+
* sort callback function for rdate
|
2054 |
+
*
|
2055 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2056 |
+
* @since 2.21.11 - 2015-03-07
|
2057 |
+
* @param array $a
|
2058 |
+
* @param array $b
|
2059 |
+
* @uses iCalUtilityFunctions::$fmt
|
2060 |
+
* @return int
|
2061 |
+
*/
|
2062 |
+
public static function _sortRdate2( $a, $b ) {
|
2063 |
+
$val = isset( $a['value'][0]['year'] ) ? $a['value'][0] : $a['value'][0][0];
|
2064 |
+
if( empty( $val ))
|
2065 |
+
$as = '';
|
2066 |
+
else {
|
2067 |
+
$as = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $val['year'], (int) $val['month'], (int) $val['day'] );
|
2068 |
+
$as .= ( isset( $val['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $val['hour'], (int) $val['min'], (int) $val['sec'] ) : '';
|
2069 |
+
}
|
2070 |
+
$val = isset( $b['value'][0]['year'] ) ? $b['value'][0] : $b['value'][0][0];
|
2071 |
+
if( empty( $val ))
|
2072 |
+
$bs = '';
|
2073 |
+
else {
|
2074 |
+
$bs = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $val['year'], (int) $val['month'], (int) $val['day'] );
|
2075 |
+
$bs .= ( isset( $val['hour'] )) ? sprintf( iCalUtilityFunctions::$fmt['His'], (int) $val['hour'], (int) $val['min'], (int) $val['sec'] ) : '';
|
2076 |
+
}
|
2077 |
+
return strcmp( $as, $bs );
|
2078 |
+
}
|
2079 |
+
/**
|
2080 |
+
* separate property attributes from property value
|
2081 |
+
*
|
2082 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2083 |
+
* @since 2.18.6 - 2013-08-29
|
2084 |
+
* @param string $line property content
|
2085 |
+
* @param array $propAttr property parameters
|
2086 |
+
* @uses iCalUtilityFunctions::$parValPrefix
|
2087 |
+
* @return void
|
2088 |
+
*/
|
2089 |
+
public static function _splitContent( & $line, & $propAttr=null ) {
|
2090 |
+
$attr = array();
|
2091 |
+
$attrix = -1;
|
2092 |
+
$clen = strlen( $line );
|
2093 |
+
$WithinQuotes = FALSE;
|
2094 |
+
$cix = 0;
|
2095 |
+
while( FALSE !== substr( $line, $cix, 1 )) {
|
2096 |
+
if( ! $WithinQuotes && ( ':' == $line[$cix] ) &&
|
2097 |
+
( substr( $line,$cix, 3 ) != '://' ) &&
|
2098 |
+
( ! in_array( strtolower( substr( $line,$cix - 6, 4 )), iCalUtilityFunctions::$parValPrefix['MStz'] )) &&
|
2099 |
+
( ! in_array( strtolower( substr( $line,$cix - 3, 4 )), iCalUtilityFunctions::$parValPrefix['Proto3'] )) &&
|
2100 |
+
( ! in_array( strtolower( substr( $line,$cix - 4, 5 )), iCalUtilityFunctions::$parValPrefix['Proto4'] )) &&
|
2101 |
+
( ! in_array( strtolower( substr( $line,$cix - 6, 7 )), iCalUtilityFunctions::$parValPrefix['Proto6'] ))) {
|
2102 |
+
$attrEnd = TRUE;
|
2103 |
+
if(( $cix < ( $clen - 4 )) &&
|
2104 |
+
ctype_digit( substr( $line, $cix+1, 4 ))) { // an URI with a (4pos) portnr??
|
2105 |
+
for( $c2ix = $cix; 3 < $c2ix; $c2ix-- ) {
|
2106 |
+
if( '://' == substr( $line, $c2ix - 2, 3 )) {
|
2107 |
+
$attrEnd = FALSE;
|
2108 |
+
break; // an URI with a portnr!!
|
2109 |
+
}
|
2110 |
+
}
|
2111 |
+
}
|
2112 |
+
if( $attrEnd) {
|
2113 |
+
$line = substr( $line, ( $cix + 1 ));
|
2114 |
+
break;
|
2115 |
+
}
|
2116 |
+
$cix++;
|
2117 |
+
}
|
2118 |
+
if( '"' == $line[$cix] )
|
2119 |
+
$WithinQuotes = ! $WithinQuotes;
|
2120 |
+
if( ';' == $line[$cix] )
|
2121 |
+
$attr[++$attrix] = null;
|
2122 |
+
else
|
2123 |
+
$attr[$attrix] .= $line[$cix];
|
2124 |
+
$cix++;
|
2125 |
+
}
|
2126 |
+
/* make attributes in array format */
|
2127 |
+
$propAttr = array();
|
2128 |
+
foreach( $attr as $attribute ) {
|
2129 |
+
$attrsplit = explode( '=', $attribute, 2 );
|
2130 |
+
if( 1 < count( $attrsplit ))
|
2131 |
+
$propAttr[$attrsplit[0]] = $attrsplit[1];
|
2132 |
+
}
|
2133 |
+
}
|
2134 |
+
/**
|
2135 |
+
* step date, return updated date, array and timpstamp
|
2136 |
+
*
|
2137 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2138 |
+
* @since 2.21.11 - 2015-03-10
|
2139 |
+
* @param array $date date to step
|
2140 |
+
* @param string $dateYMD date YMD
|
2141 |
+
* @param array $step default array( 'day' => 1 )
|
2142 |
+
* @uses iCalUtilityFunctions::$fmt
|
2143 |
+
* @return void
|
2144 |
+
*/
|
2145 |
+
public static function _stepdate( & $date, & $dateYMD, $step=array( 'day' => 1 )) {
|
2146 |
+
if( !isset( $date['hour'] )) $date['hour'] = 0;
|
2147 |
+
if( !isset( $date['min'] )) $date['min'] = 0;
|
2148 |
+
if( !isset( $date['sec'] )) $date['sec'] = 0;
|
2149 |
+
if( isset( $step['day'] ))
|
2150 |
+
$mcnt = date( 't', mktime( (int) $date['hour'], (int) $date['min'], (int) $date['sec'], (int) $date['month'], (int) $date['day'], (int) $date['year'] ));
|
2151 |
+
foreach( $step as $stepix => $stepvalue )
|
2152 |
+
$date[$stepix] += $stepvalue;
|
2153 |
+
if( isset( $step['month'] )) {
|
2154 |
+
if( 12 < $date['month'] ) {
|
2155 |
+
$date['year'] += 1;
|
2156 |
+
$date['month'] -= 12;
|
2157 |
+
}
|
2158 |
+
}
|
2159 |
+
elseif( isset( $step['day'] )) {
|
2160 |
+
if( $mcnt < $date['day'] ) {
|
2161 |
+
$date['day'] -= $mcnt;
|
2162 |
+
$date['month'] += 1;
|
2163 |
+
if( 12 < $date['month'] ) {
|
2164 |
+
$date['year'] += 1;
|
2165 |
+
$date['month'] -= 12;
|
2166 |
+
}
|
2167 |
+
}
|
2168 |
+
}
|
2169 |
+
$dateYMD = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $date['year'], (int) $date['month'], (int) $date['day'] );
|
2170 |
+
unset( $mcnt );
|
2171 |
+
}
|
2172 |
+
/**
|
2173 |
+
* convert a date from specific string to array format
|
2174 |
+
*
|
2175 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2176 |
+
* @since 2.11.8 - 2012-01-27
|
2177 |
+
* @param mixed $input
|
2178 |
+
* @return bool, TRUE on success
|
2179 |
+
*/
|
2180 |
+
public static function _strDate2arr( & $input ) {
|
2181 |
+
if( is_array( $input ))
|
2182 |
+
return FALSE;
|
2183 |
+
if( 5 > strlen( (string) $input ))
|
2184 |
+
return FALSE;
|
2185 |
+
$work = $input;
|
2186 |
+
if( 2 == substr_count( $work, '-' ))
|
2187 |
+
$work = str_replace( '-', '', $work );
|
2188 |
+
if( 2 == substr_count( $work, '/' ))
|
2189 |
+
$work = str_replace( '/', '', $work );
|
2190 |
+
if( !ctype_digit( substr( $work, 0, 8 )))
|
2191 |
+
return FALSE;
|
2192 |
+
$temp = array( 'year' => (int) substr( $work, 0, 4 )
|
2193 |
+
, 'month' => (int) substr( $work, 4, 2 )
|
2194 |
+
, 'day' => (int) substr( $work, 6, 2 ));
|
2195 |
+
if( !checkdate( $temp['month'], $temp['day'], $temp['year'] ))
|
2196 |
+
return FALSE;
|
2197 |
+
if( 8 == strlen( $work )) {
|
2198 |
+
$input = $temp;
|
2199 |
+
return TRUE;
|
2200 |
+
}
|
2201 |
+
if(( ' ' == substr( $work, 8, 1 )) || ( 'T' == substr( $work, 8, 1 )) || ( 't' == substr( $work, 8, 1 )))
|
2202 |
+
$work = substr( $work, 9 );
|
2203 |
+
elseif( ctype_digit( substr( $work, 8, 1 )))
|
2204 |
+
$work = substr( $work, 8 );
|
2205 |
+
else
|
2206 |
+
return FALSE;
|
2207 |
+
if( 2 == substr_count( $work, ':' ))
|
2208 |
+
$work = str_replace( ':', '', $work );
|
2209 |
+
if( !ctype_digit( substr( $work, 0, 4 )))
|
2210 |
+
return FALSE;
|
2211 |
+
$temp['hour'] = substr( $work, 0, 2 );
|
2212 |
+
$temp['min'] = substr( $work, 2, 2 );
|
2213 |
+
if((( 0 > $temp['hour'] ) || ( $temp['hour'] > 23 )) ||
|
2214 |
+
(( 0 > $temp['min'] ) || ( $temp['min'] > 59 )))
|
2215 |
+
return FALSE;
|
2216 |
+
if( ctype_digit( substr( $work, 4, 2 ))) {
|
2217 |
+
$temp['sec'] = substr( $work, 4, 2 );
|
2218 |
+
if(( 0 > $temp['sec'] ) || ( $temp['sec'] > 59 ))
|
2219 |
+
return FALSE;
|
2220 |
+
$len = 6;
|
2221 |
+
}
|
2222 |
+
else {
|
2223 |
+
$temp['sec'] = 0;
|
2224 |
+
$len = 4;
|
2225 |
+
}
|
2226 |
+
if( $len < strlen( $work))
|
2227 |
+
$temp['tz'] = trim( substr( $work, 6 ));
|
2228 |
+
$input = $temp;
|
2229 |
+
return TRUE;
|
2230 |
+
}
|
2231 |
+
/**
|
2232 |
+
* ensures internal date-time/date format for input date-time/date in string fromat
|
2233 |
+
*
|
2234 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2235 |
+
* @since 2.21.11 - 2015-03-15
|
2236 |
+
* Modified to also return original string value by Yitzchok Lavi <icalcreator@onebigsystem.com>
|
2237 |
+
* @param array $datetime
|
2238 |
+
* @param int $parno optional, default FALSE
|
2239 |
+
* @param moxed $wtz optional, default null
|
2240 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
2241 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
2242 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
2243 |
+
* @uses iCalUtilityFunctions::_tz2offset()
|
2244 |
+
* @uses iCalUtilityFunctions::$fmt
|
2245 |
+
* @return array
|
2246 |
+
*/
|
2247 |
+
public static function _strdate2date( $datetime, $parno=FALSE, $wtz=null ) {
|
2248 |
+
$unparseddatetime = $datetime;
|
2249 |
+
$datetime = (string) trim( $datetime );
|
2250 |
+
$tz = null;
|
2251 |
+
$offset = 0;
|
2252 |
+
$tzSts = FALSE;
|
2253 |
+
$len = strlen( $datetime );
|
2254 |
+
if( 'Z' == substr( $datetime, -1 )) {
|
2255 |
+
$tz = 'Z';
|
2256 |
+
$datetime = trim( substr( $datetime, 0, ( $len - 1 )));
|
2257 |
+
$tzSts = TRUE;
|
2258 |
+
}
|
2259 |
+
if( iCalUtilityFunctions::_isOffset( substr( $datetime, -5, 5 ))) { // [+/-]NNNN offset
|
2260 |
+
$tz = substr( $datetime, -5, 5 );
|
2261 |
+
$datetime = trim( substr( $datetime, 0, ($len - 5)));
|
2262 |
+
}
|
2263 |
+
elseif( iCalUtilityFunctions::_isOffset( substr( $datetime, -7, 7 ))) { // [+/-]NNNNNN offset
|
2264 |
+
$tz = substr( $datetime, -7, 7 );
|
2265 |
+
$datetime = trim( substr( $datetime, 0, ($len - 7)));
|
2266 |
+
}
|
2267 |
+
elseif( empty( $wtz ) && ctype_digit( substr( $datetime, 0, 4 )) && ctype_digit( substr( $datetime, -2, 2 )) && iCalUtilityFunctions::_strDate2arr( $datetime )) {
|
2268 |
+
$output = $datetime;
|
2269 |
+
if( !empty( $tz ))
|
2270 |
+
$output['tz'] = 'Z';
|
2271 |
+
$output['unparsedtext'] = $unparseddatetime;
|
2272 |
+
return $output;
|
2273 |
+
}
|
2274 |
+
else {
|
2275 |
+
$cx = $tx = 0; // find any trailing timezone or offset
|
2276 |
+
$len = strlen( $datetime );
|
2277 |
+
for( $cx = -1; $cx > ( 9 - $len ); $cx-- ) {
|
2278 |
+
$char = substr( $datetime, $cx, 1 );
|
2279 |
+
if(( ' ' == $char ) || ctype_digit( $char ))
|
2280 |
+
break; // if exists, tz ends here.. . ?
|
2281 |
+
else
|
2282 |
+
$tx--; // tz length counter
|
2283 |
+
}
|
2284 |
+
if( 0 > $tx ) { // if any
|
2285 |
+
$tz = substr( $datetime, $tx );
|
2286 |
+
$datetime = trim( substr( $datetime, 0, $len + $tx ));
|
2287 |
+
}
|
2288 |
+
if(( ctype_digit( substr( $datetime, 0, 8 )) && ( 'T' == substr( $datetime, 8, 1 )) && ctype_digit( substr( $datetime, -6, 6 ))) ||
|
2289 |
+
( ctype_digit( substr( $datetime, 0, 14 ))))
|
2290 |
+
$tzSts = TRUE;
|
2291 |
+
}
|
2292 |
+
if( empty( $tz ) && !empty( $wtz ))
|
2293 |
+
$tz = $wtz;
|
2294 |
+
if( 3 == $parno )
|
2295 |
+
$tz = null;
|
2296 |
+
if( !empty( $tz )) { // tz set
|
2297 |
+
if(( 'Z' != $tz ) && ( iCalUtilityFunctions::_isOffset( $tz ))) {
|
2298 |
+
$offset = (string) iCalUtilityFunctions::_tz2offset( $tz ) * -1;
|
2299 |
+
$tz = 'UTC';
|
2300 |
+
$tzSts = TRUE;
|
2301 |
+
}
|
2302 |
+
elseif( !empty( $wtz ))
|
2303 |
+
$tzSts = TRUE;
|
2304 |
+
$tz = trim( $tz );
|
2305 |
+
if(( 'Z' == $tz ) || ( 'GMT' == strtoupper( $tz )))
|
2306 |
+
$tz = 'UTC';
|
2307 |
+
if( 0 < substr_count( $datetime, '-' ))
|
2308 |
+
$datetime = str_replace( '-', '/', $datetime );
|
2309 |
+
try {
|
2310 |
+
$d = new DateTime( $datetime, new DateTimeZone( $tz ));
|
2311 |
+
if( 0 != $offset ) // adjust for offset
|
2312 |
+
$d->modify( $offset.' seconds' );
|
2313 |
+
$datestring = $d->format( iCalUtilityFunctions::$fmt['YmdHis3'] );
|
2314 |
+
unset( $d );
|
2315 |
+
}
|
2316 |
+
catch( Exception $e ) {
|
2317 |
+
$datestring = date( iCalUtilityFunctions::$fmt['YmdHis3'], strtotime( $datetime ));
|
2318 |
+
}
|
2319 |
+
} // end if( !empty( $tz ))
|
2320 |
+
else
|
2321 |
+
$datestring = date( iCalUtilityFunctions::$fmt['YmdHis3'], strtotime( $datetime ));
|
2322 |
+
if( 'UTC' == $tz )
|
2323 |
+
$tz = 'Z';
|
2324 |
+
$d = explode( '-', $datestring );
|
2325 |
+
$output = array( 'year' => $d[0], 'month' => $d[1], 'day' => $d[2] );
|
2326 |
+
if( !$parno || ( 3 != $parno )) { // parno is set to 6 or 7
|
2327 |
+
$output['hour'] = $d[3];
|
2328 |
+
$output['min'] = $d[4];
|
2329 |
+
$output['sec'] = $d[5];
|
2330 |
+
if(( $tzSts || ( 7 == $parno )) && !empty( $tz ))
|
2331 |
+
$output['tz'] = $tz;
|
2332 |
+
}
|
2333 |
+
// return original string in the array in case strtotime failed to make sense of it
|
2334 |
+
$output['unparsedtext'] = $unparseddatetime;
|
2335 |
+
return $output;
|
2336 |
+
}
|
2337 |
+
/********************************************************************************/
|
2338 |
+
/**
|
2339 |
+
* special characters management output
|
2340 |
+
*
|
2341 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2342 |
+
* @since 2.16.2 - 2012-12-18
|
2343 |
+
* @param string $string
|
2344 |
+
* @param string $format
|
2345 |
+
* @param string $nl
|
2346 |
+
* @return string
|
2347 |
+
*/
|
2348 |
+
public static function _strrep( $string, $format, $nl ) {
|
2349 |
+
switch( $format ) {
|
2350 |
+
case 'xcal':
|
2351 |
+
$string = str_replace( '\n', $nl, $string);
|
2352 |
+
$string = htmlspecialchars( strip_tags( stripslashes( urldecode ( $string ))));
|
2353 |
+
break;
|
2354 |
+
default:
|
2355 |
+
$pos = 0;
|
2356 |
+
$specChars = array( 'n', 'N', 'r', ',', ';' );
|
2357 |
+
while( isset( $string[$pos] )) {
|
2358 |
+
if( FALSE === ( $pos = strpos( $string, "\\", $pos )))
|
2359 |
+
break;
|
2360 |
+
if( !in_array( substr( $string, $pos, 1 ), $specChars )) {
|
2361 |
+
$string = substr( $string, 0, $pos )."\\".substr( $string, ( $pos + 1 ));
|
2362 |
+
$pos += 1;
|
2363 |
+
}
|
2364 |
+
$pos += 1;
|
2365 |
+
}
|
2366 |
+
if( FALSE !== strpos( $string, '"' ))
|
2367 |
+
$string = str_replace('"', "'", $string);
|
2368 |
+
if( FALSE !== strpos( $string, ',' ))
|
2369 |
+
$string = str_replace(',', '\,', $string);
|
2370 |
+
if( FALSE !== strpos( $string, ';' ))
|
2371 |
+
$string = str_replace(';', '\;', $string);
|
2372 |
+
if( FALSE !== strpos( $string, "\r\n" ))
|
2373 |
+
$string = str_replace( "\r\n", '\n', $string);
|
2374 |
+
elseif( FALSE !== strpos( $string, "\r" ))
|
2375 |
+
$string = str_replace( "\r", '\n', $string);
|
2376 |
+
elseif( FALSE !== strpos( $string, "\n" ))
|
2377 |
+
$string = str_replace( "\n", '\n', $string);
|
2378 |
+
if( FALSE !== strpos( $string, '\N' ))
|
2379 |
+
$string = str_replace( '\N', '\n', $string);
|
2380 |
+
// if( FALSE !== strpos( $string, $nl ))
|
2381 |
+
$string = str_replace( $nl, '\n', $string);
|
2382 |
+
break;
|
2383 |
+
}
|
2384 |
+
return $string;
|
2385 |
+
}
|
2386 |
+
/**
|
2387 |
+
* special characters management input (from iCal file)
|
2388 |
+
*
|
2389 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2390 |
+
* @since 2.16.2 - 2012-12-18
|
2391 |
+
* @param string $string
|
2392 |
+
* @return string
|
2393 |
+
*/
|
2394 |
+
public static function _strunrep( $string ) {
|
2395 |
+
$string = str_replace( '\\\\', '\\', $string);
|
2396 |
+
$string = str_replace( '\,', ',', $string);
|
2397 |
+
$string = str_replace( '\;', ';', $string);
|
2398 |
+
// $string = str_replace( '\n', $nl, $string); // ??
|
2399 |
+
return $string;
|
2400 |
+
}
|
2401 |
+
/**
|
2402 |
+
* convert timestamp to date array, default UTC or adjusted for offset/timezone
|
2403 |
+
*
|
2404 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2405 |
+
* @since 2.21.11 - 2015-03-07
|
2406 |
+
* @param mixed $timestamp
|
2407 |
+
* @param int $parno
|
2408 |
+
* @param string $wtz
|
2409 |
+
* @uses iCalUtilityFunctions::_isOffset()
|
2410 |
+
* @uses iCalUtilityFunctions::_tz2offset()
|
2411 |
+
* @uses iCalUtilityFunctions::$fmt
|
2412 |
+
* @return array
|
2413 |
+
*/
|
2414 |
+
public static function _timestamp2date( $timestamp, $parno=6, $wtz=null ) {
|
2415 |
+
if( is_array( $timestamp )) {
|
2416 |
+
$tz = ( isset( $timestamp['tz'] )) ? $timestamp['tz'] : $wtz;
|
2417 |
+
$timestamp = $timestamp['timestamp'];
|
2418 |
+
}
|
2419 |
+
$tz = ( isset( $tz )) ? $tz : $wtz;
|
2420 |
+
$offset = 0;
|
2421 |
+
if( empty( $tz ) || ( 'Z' == $tz ) || ( 'GMT' == strtoupper( $tz )))
|
2422 |
+
$tz = 'UTC';
|
2423 |
+
elseif( iCalUtilityFunctions::_isOffset( $tz )) {
|
2424 |
+
$offset = iCalUtilityFunctions::_tz2offset( $tz );
|
2425 |
+
}
|
2426 |
+
try {
|
2427 |
+
$d = new DateTime( "@$timestamp" ); // set UTC date
|
2428 |
+
if( 0 != $offset ) // adjust for offset
|
2429 |
+
$d->modify( $offset.' seconds' );
|
2430 |
+
elseif( 'UTC' != $tz )
|
2431 |
+
$d->setTimezone( new DateTimeZone( $tz )); // convert to local date
|
2432 |
+
$date = $d->format( iCalUtilityFunctions::$fmt['YmdHis3'] );
|
2433 |
+
unset( $d );
|
2434 |
+
}
|
2435 |
+
catch( Exception $e ) {
|
2436 |
+
$date = date( iCalUtilityFunctions::$fmt['YmdHis3'], $timestamp );
|
2437 |
+
}
|
2438 |
+
$date = explode( '-', $date );
|
2439 |
+
$output = array( 'year' => $date[0], 'month' => $date[1], 'day' => $date[2] );
|
2440 |
+
if( 3 != $parno ) {
|
2441 |
+
$output['hour'] = $date[3];
|
2442 |
+
$output['min'] = $date[4];
|
2443 |
+
$output['sec'] = $date[5];
|
2444 |
+
if(( 'UTC' == $tz ) || ( 0 == $offset ))
|
2445 |
+
$output['tz'] = 'Z';
|
2446 |
+
}
|
2447 |
+
return $output;
|
2448 |
+
}
|
2449 |
+
/**
|
2450 |
+
* transforms a dateTime from a timezone to another using PHP DateTime and DateTimeZone class (PHP >= PHP 5.2.0)
|
2451 |
+
*
|
2452 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2453 |
+
* @since 2.15.1 - 2012-10-17
|
2454 |
+
* @param mixed $date date to alter
|
2455 |
+
* @param string $tzFrom PHP valid 'from' timezone
|
2456 |
+
* @param string $tzTo PHP valid 'to' timezone, default 'UTC'
|
2457 |
+
* @param string $format date output format, default 'Ymd\THis'
|
2458 |
+
* @uses iCalUtilityFunctions::_isArrayDate()
|
2459 |
+
* @uses iCalUtilityFunctions::_date2strdate()
|
2460 |
+
* @uses iCalUtilityFunctions::_chkDateArr()
|
2461 |
+
* @return bool
|
2462 |
+
*/
|
2463 |
+
public static function transformDateTime( & $date, $tzFrom, $tzTo='UTC', $format = 'Ymd\THis' ) {
|
2464 |
+
if( is_array( $date ) && isset( $date['timestamp'] )) {
|
2465 |
+
try {
|
2466 |
+
$d = new DateTime( "@{$date['timestamp']}" ); // set UTC date
|
2467 |
+
$d->setTimezone(new DateTimeZone( $tzFrom )); // convert to 'from' date
|
2468 |
+
}
|
2469 |
+
catch( Exception $e ) { return FALSE; }
|
2470 |
+
}
|
2471 |
+
else {
|
2472 |
+
if( iCalUtilityFunctions::_isArrayDate( $date )) {
|
2473 |
+
if( isset( $date['tz'] ))
|
2474 |
+
unset( $date['tz'] );
|
2475 |
+
$date = iCalUtilityFunctions::_date2strdate( iCalUtilityFunctions::_chkDateArr( $date ));
|
2476 |
+
}
|
2477 |
+
if( 'Z' == substr( $date, -1 ))
|
2478 |
+
$date = substr( $date, 0, ( strlen( $date ) - 2 ));
|
2479 |
+
try { $d = new DateTime( $date, new DateTimeZone( $tzFrom )); }
|
2480 |
+
catch( Exception $e ) { return FALSE; }
|
2481 |
+
}
|
2482 |
+
try { $d->setTimezone( new DateTimeZone( $tzTo )); }
|
2483 |
+
catch( Exception $e ) { return FALSE; }
|
2484 |
+
$date = $d->format( $format );
|
2485 |
+
return TRUE;
|
2486 |
+
}
|
2487 |
+
/**
|
2488 |
+
* convert offset, [+/-]HHmm[ss], to seconds, used when correcting UTC to localtime or v.v.
|
2489 |
+
*
|
2490 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2491 |
+
* @since 2.11.4 - 2012-01-11
|
2492 |
+
* @param string $tz
|
2493 |
+
* @return integer
|
2494 |
+
*/
|
2495 |
+
public static function _tz2offset( $tz ) {
|
2496 |
+
$tz = trim( (string) $tz );
|
2497 |
+
$offset = 0;
|
2498 |
+
if((( 5 != strlen( $tz )) && ( 7 != strlen( $tz ))) ||
|
2499 |
+
(( '+' != substr( $tz, 0, 1 )) && ( '-' != substr( $tz, 0, 1 ))) ||
|
2500 |
+
(( '0000' >= substr( $tz, 1, 4 )) && ( '9999' < substr( $tz, 1, 4 ))) ||
|
2501 |
+
(( 7 == strlen( $tz )) && ( '00' > substr( $tz, 5, 2 )) && ( '99' < substr( $tz, 5, 2 ))))
|
2502 |
+
return $offset;
|
2503 |
+
$hours2sec = (int) substr( $tz, 1, 2 ) * 3600;
|
2504 |
+
$min2sec = (int) substr( $tz, 3, 2 ) * 60;
|
2505 |
+
$sec = ( 7 == strlen( $tz )) ? (int) substr( $tz, -2 ) : '00';
|
2506 |
+
$offset = $hours2sec + $min2sec + $sec;
|
2507 |
+
$offset = ('-' == substr( $tz, 0, 1 )) ? $offset * -1 : $offset;
|
2508 |
+
return $offset;
|
2509 |
+
}
|
2510 |
+
}
|
includes/libs/iCal/lib/iCaldateTime.class.php
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* selectComponent help class
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.21.7 - 2015-03-10
|
34 |
+
*/
|
35 |
+
class iCaldateTime extends dateTime {
|
36 |
+
/** @var string default date[-time] format */
|
37 |
+
public $dateFormat = 'Y-m-d H:i:s e';
|
38 |
+
/** @var string default object instance date[-time] 'key' */
|
39 |
+
public $key = null;
|
40 |
+
/** @var array date[-time] origin */
|
41 |
+
public $SCbools = array();
|
42 |
+
/**
|
43 |
+
* return time (His) array
|
44 |
+
*
|
45 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
46 |
+
* @since 2.21.7 - 2015-03-07
|
47 |
+
* @return array
|
48 |
+
*/
|
49 |
+
public function getTime() {
|
50 |
+
return explode( ':', $this->format( 'H:i:s' ));
|
51 |
+
}
|
52 |
+
/**
|
53 |
+
* return the timezone name
|
54 |
+
*
|
55 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
56 |
+
* @since 2.21.7 - 2015-03-07
|
57 |
+
* @return string
|
58 |
+
*/
|
59 |
+
public function getTimezoneName() {
|
60 |
+
$tz = $this->getTimezone();
|
61 |
+
return $tz->getName();
|
62 |
+
}
|
63 |
+
/**
|
64 |
+
* return formatted date
|
65 |
+
*
|
66 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
67 |
+
* @since 2.21.7 - 2015-03-07
|
68 |
+
* @param string $format
|
69 |
+
* @uses iCaldateTime::$dateFormat
|
70 |
+
* @return string
|
71 |
+
*/
|
72 |
+
public function format( $format=null ) {
|
73 |
+
if( empty( $format ) && isset( $this->dateFormat ))
|
74 |
+
$format = $this->dateFormat;
|
75 |
+
return parent::format( $format );
|
76 |
+
}
|
77 |
+
/**
|
78 |
+
* return iCaldateTime object instance based on date array and timezone(s)
|
79 |
+
*
|
80 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
81 |
+
* @since 2.21.11 - 2015-03-28
|
82 |
+
* @param array $date
|
83 |
+
* @param array $params
|
84 |
+
* @param array $tz
|
85 |
+
* @param string $dtstartTz
|
86 |
+
* @uses iCalUtilityFunctions::$fmt
|
87 |
+
* @uses iCaldateTime::getTimezoneName()
|
88 |
+
* @uses iCaldateTime::$dateFormat
|
89 |
+
* @uses iCaldateTime::$key
|
90 |
+
* @return object instance
|
91 |
+
*/
|
92 |
+
public static function factory( array $date, $params=null, $tz=null, $dtstartTz=null ) {
|
93 |
+
if( isset( $params['TZID'] ) && ! empty( $params['TZID'] ))
|
94 |
+
$tz = ( 'Z' == $params['TZID'] ) ? 'UTC' : $params['TZID'];
|
95 |
+
elseif( isset( $tz['tz'] ) && ! empty( $tz['tz'] ))
|
96 |
+
$tz = ( 'Z' == $tz['tz'] ) ? 'UTC' : $tz['tz'];
|
97 |
+
else
|
98 |
+
$tz = ini_get( 'date_default_timezone_set' );
|
99 |
+
$strdate = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $date['year'], (int) $date['month'], (int) $date['day'] );
|
100 |
+
if( isset( $date['hour'] ))
|
101 |
+
$strdate .= 'T'.sprintf( iCalUtilityFunctions::$fmt['His'], (int) $date['hour'], (int) $date['min'], (int) $date['sec'] );
|
102 |
+
try {
|
103 |
+
$timezone = new DateTimeZone( $tz );
|
104 |
+
$d = new iCaldateTime( $strdate, $timezone );
|
105 |
+
}
|
106 |
+
catch( Exception $e ) {
|
107 |
+
$d = new iCaldateTime( $strdate );
|
108 |
+
}
|
109 |
+
if( ! empty( $dtstartTz )) {
|
110 |
+
if( 'Z' == $dtstartTz )
|
111 |
+
$dtstartTz = 'UTC';
|
112 |
+
if( $dtstartTz != $d->getTimezoneName()) { // set the same timezone as dtstart
|
113 |
+
try {
|
114 |
+
$timezone = new DateTimeZone( $dtstartTz );
|
115 |
+
$d->setTimezone( $timezone );
|
116 |
+
}
|
117 |
+
catch( Exception $e ) {}
|
118 |
+
}
|
119 |
+
}
|
120 |
+
unset( $timezone, $strdate );
|
121 |
+
if( isset( $params['VALUE'] ) && ( 'DATE' == $params['VALUE'] )) {
|
122 |
+
$d->dateFormat = 'Y-m-d';
|
123 |
+
$d->key = $d->format( 'Ymd' );
|
124 |
+
}
|
125 |
+
else
|
126 |
+
$d->key = $d->format( 'YmdHis' );
|
127 |
+
return $d;
|
128 |
+
}
|
129 |
+
}
|
includes/libs/iCal/lib/valarm.class.php
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* class for calendar component VALARM
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.5.1 - 2008-10-12
|
34 |
+
*/
|
35 |
+
class valarm extends calendarComponent {
|
36 |
+
/**
|
37 |
+
* @var array $action component property value
|
38 |
+
* @var array $attach component property value
|
39 |
+
* @var array $attendee component property value
|
40 |
+
* @var array $description component property value
|
41 |
+
* @var array $duration component property value
|
42 |
+
* @var array $repeat component property value
|
43 |
+
* @var array $summary component property value
|
44 |
+
* @var array $trigger component property value
|
45 |
+
* @access protected
|
46 |
+
*/
|
47 |
+
protected $action;
|
48 |
+
protected $attach;
|
49 |
+
protected $attendee;
|
50 |
+
protected $description;
|
51 |
+
protected $duration;
|
52 |
+
protected $repeat;
|
53 |
+
protected $summary;
|
54 |
+
protected $trigger;
|
55 |
+
/**
|
56 |
+
* constructor for calendar component VALARM object
|
57 |
+
*
|
58 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
59 |
+
* @since 2.8.2 - 2011-05-01
|
60 |
+
* @param array $config
|
61 |
+
* @uses valarm::calendarComponent()
|
62 |
+
* @uses valarm::$action
|
63 |
+
* @uses valarm::$attach
|
64 |
+
* @uses valarm::$attendee
|
65 |
+
* @uses valarm::$description
|
66 |
+
* @uses valarm::$duration
|
67 |
+
* @uses valarm::$repeat
|
68 |
+
* @uses valarm::$summary
|
69 |
+
* @uses valarm::$trigger
|
70 |
+
* @uses valarm::$xprop
|
71 |
+
* @uses calendarComponent::setConfig()
|
72 |
+
*/
|
73 |
+
function __construct( $config = array()) {
|
74 |
+
$this->calendarComponent();
|
75 |
+
$this->action = '';
|
76 |
+
$this->attach = '';
|
77 |
+
$this->attendee = '';
|
78 |
+
$this->description = '';
|
79 |
+
$this->duration = '';
|
80 |
+
$this->repeat = '';
|
81 |
+
$this->summary = '';
|
82 |
+
$this->trigger = '';
|
83 |
+
$this->xprop = '';
|
84 |
+
if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
|
85 |
+
$config['language'] = ICAL_LANG;
|
86 |
+
if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
|
87 |
+
if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
|
88 |
+
if( !isset( $config['format'] )) $config['format'] = 'iCal';
|
89 |
+
if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
|
90 |
+
$this->setConfig( $config );
|
91 |
+
}
|
92 |
+
/**
|
93 |
+
* create formatted output for calendar component VALARM object instance
|
94 |
+
*
|
95 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
96 |
+
* @since 2.5.1 - 2008-10-22
|
97 |
+
* @param array $xcaldecl
|
98 |
+
* @uses calendarComponent::_createFormat()
|
99 |
+
* @uses calendarComponent::$componentStart1
|
100 |
+
* @uses calendarComponent::$componentStart2
|
101 |
+
* @uses calendarComponent::$nl
|
102 |
+
* @uses calendarComponent::createAction()
|
103 |
+
* @uses calendarComponent::createAttach()
|
104 |
+
* @uses calendarComponent::createAttendee()
|
105 |
+
* @uses calendarComponent::createDescription()
|
106 |
+
* @uses calendarComponent::createDuration()
|
107 |
+
* @uses calendarComponent::createRepeat()
|
108 |
+
* @uses calendarComponent::createSummary()
|
109 |
+
* @uses calendarComponent::createTrigger()
|
110 |
+
* @uses calendarComponent::createXprop()
|
111 |
+
* @uses calendarComponent::$componentEnd1
|
112 |
+
* @uses calendarComponent::$componentEnd2
|
113 |
+
* @uses calendarComponent::$xcaldecl
|
114 |
+
* @return string
|
115 |
+
*/
|
116 |
+
function createComponent( & $xcaldecl ) {
|
117 |
+
$objectname = $this->_createFormat();
|
118 |
+
$component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
|
119 |
+
$component .= $this->createAction();
|
120 |
+
$component .= $this->createAttach();
|
121 |
+
$component .= $this->createAttendee();
|
122 |
+
$component .= $this->createDescription();
|
123 |
+
$component .= $this->createDuration();
|
124 |
+
$component .= $this->createRepeat();
|
125 |
+
$component .= $this->createSummary();
|
126 |
+
$component .= $this->createTrigger();
|
127 |
+
$component .= $this->createXprop();
|
128 |
+
$component .= $this->componentEnd1.$objectname.$this->componentEnd2;
|
129 |
+
if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
|
130 |
+
foreach( $this->xcaldecl as $localxcaldecl )
|
131 |
+
$xcaldecl[] = $localxcaldecl;
|
132 |
+
}
|
133 |
+
return $component;
|
134 |
+
}
|
135 |
+
}
|
includes/libs/iCal/lib/vcalendar.class.php
ADDED
@@ -0,0 +1,2132 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* vcalendar class
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.21.11 - 2015-03-31
|
34 |
+
*/
|
35 |
+
class vcalendar extends iCalBase {
|
36 |
+
/**
|
37 |
+
* @var array $calscale calendar property variable
|
38 |
+
* @var array $method calendar property variable
|
39 |
+
* @var array $prodid calendar property variable
|
40 |
+
* @var array $version calendar property variable
|
41 |
+
* @access private
|
42 |
+
*/
|
43 |
+
private $calscale;
|
44 |
+
private $method;
|
45 |
+
private $prodid;
|
46 |
+
private $version;
|
47 |
+
/**
|
48 |
+
* @var array $directory calendar config variable
|
49 |
+
* @var array $filename calendar config variable
|
50 |
+
* @var array $url calendar config variable
|
51 |
+
* @access private
|
52 |
+
*/
|
53 |
+
private $directory;
|
54 |
+
private $filename;
|
55 |
+
private $url;
|
56 |
+
/**
|
57 |
+
* redirect headers
|
58 |
+
*
|
59 |
+
* @var array $headers
|
60 |
+
* @access private
|
61 |
+
* @static
|
62 |
+
*/
|
63 |
+
private static $headers = array( 'Content-Encoding: gzip',
|
64 |
+
'Vary: *',
|
65 |
+
'Content-Length: %s',
|
66 |
+
'Content-Type: application/calendar+xml; charset=utf-8',
|
67 |
+
'Content-Type: text/calendar; charset=utf-8',
|
68 |
+
'Content-Disposition: attachment; filename="%s"',
|
69 |
+
'Content-Disposition: inline; filename="%s"',
|
70 |
+
'Cache-Control: max-age=10',
|
71 |
+
);
|
72 |
+
/**
|
73 |
+
* constructor for calendar object
|
74 |
+
*
|
75 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
76 |
+
* @since 2.21.15 - 2015-04-04
|
77 |
+
* @param array $config
|
78 |
+
* @uses vcalendar::_makeVersion()
|
79 |
+
* @uses vcalendar::$calscale
|
80 |
+
* @uses vcalendar::$method
|
81 |
+
* @uses vcalendar::_makeUnique_id()
|
82 |
+
* @uses vcalendar::$prodid
|
83 |
+
* @uses vcalendar::$xprop
|
84 |
+
* @uses vcalendar::$language
|
85 |
+
* @uses vcalendar::$directory
|
86 |
+
* @uses vcalendar::$filename
|
87 |
+
* @uses vcalendar::$url
|
88 |
+
* @uses vcalendar::$dtzid
|
89 |
+
* @uses vcalendar::setConfig()
|
90 |
+
* @uses vcalendar::$xcaldecl
|
91 |
+
* @uses vcalendar::$components
|
92 |
+
*/
|
93 |
+
function __construct( $config = array()) {
|
94 |
+
$this->_makeVersion();
|
95 |
+
$this->calscale = null;
|
96 |
+
$this->method = null;
|
97 |
+
$this->_makeUnique_id();
|
98 |
+
$this->prodid = null;
|
99 |
+
$this->xprop = array();
|
100 |
+
$this->language = null;
|
101 |
+
$this->directory = '.';
|
102 |
+
$this->filename = null;
|
103 |
+
$this->url = null;
|
104 |
+
$this->dtzid = null;
|
105 |
+
/**
|
106 |
+
* language = <Text identifying a language, as defined in [RFC 1766]>
|
107 |
+
*/
|
108 |
+
if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
|
109 |
+
$config['language'] = ICAL_LANG;
|
110 |
+
if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
|
111 |
+
if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
|
112 |
+
if( !isset( $config['format'] )) $config['format'] = 'iCal';
|
113 |
+
if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
|
114 |
+
$this->setConfig( $config );
|
115 |
+
$this->xcaldecl = array();
|
116 |
+
$this->components = array();
|
117 |
+
}
|
118 |
+
/**
|
119 |
+
* return iCalcreator version number
|
120 |
+
*
|
121 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
122 |
+
* @since 2.18.5 - 2013-08-29
|
123 |
+
* @uses ICALCREATOR_VERSION
|
124 |
+
* @return string
|
125 |
+
*/
|
126 |
+
public static function iCalcreatorVersion() {
|
127 |
+
return trim( substr( ICALCREATOR_VERSION, strpos( ICALCREATOR_VERSION, ' ' )));
|
128 |
+
}
|
129 |
+
/*********************************************************************************/
|
130 |
+
/**
|
131 |
+
* Property Name: CALSCALE
|
132 |
+
*/
|
133 |
+
/**
|
134 |
+
* creates formatted output for calendar property calscale
|
135 |
+
*
|
136 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
137 |
+
* @since 2.10.16 - 2011-10-28
|
138 |
+
* @uses vcalendar::$calscale
|
139 |
+
* @uses vcalendar::$format
|
140 |
+
* @uses vcalendar::$nl
|
141 |
+
* @return string
|
142 |
+
*/
|
143 |
+
function createCalscale() {
|
144 |
+
if( empty( $this->calscale )) return FALSE;
|
145 |
+
switch( $this->format ) {
|
146 |
+
case 'xcal':
|
147 |
+
return $this->nl.' calscale="'.$this->calscale.'"';
|
148 |
+
break;
|
149 |
+
default:
|
150 |
+
return 'CALSCALE:'.$this->calscale.$this->nl;
|
151 |
+
break;
|
152 |
+
}
|
153 |
+
}
|
154 |
+
/**
|
155 |
+
* set calendar property calscale
|
156 |
+
*
|
157 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
158 |
+
* @since 2.4.8 - 2008-10-21
|
159 |
+
* @param string $value
|
160 |
+
* @uses vcalendar::$calscale
|
161 |
+
* @return void
|
162 |
+
*/
|
163 |
+
function setCalscale( $value ) {
|
164 |
+
if( empty( $value )) return FALSE;
|
165 |
+
$this->calscale = $value;
|
166 |
+
}
|
167 |
+
/*********************************************************************************/
|
168 |
+
/**
|
169 |
+
* Property Name: METHOD
|
170 |
+
*/
|
171 |
+
/**
|
172 |
+
* creates formatted output for calendar property method
|
173 |
+
*
|
174 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
175 |
+
* @since 2.10.16 - 2011-10-28
|
176 |
+
* @uses vcalendar::$method
|
177 |
+
* @uses vcalendar::$format
|
178 |
+
* @uses vcalendar::$nl
|
179 |
+
* @return string
|
180 |
+
*/
|
181 |
+
function createMethod() {
|
182 |
+
if( empty( $this->method )) return FALSE;
|
183 |
+
switch( $this->format ) {
|
184 |
+
case 'xcal':
|
185 |
+
return $this->nl.' method="'.$this->method.'"';
|
186 |
+
break;
|
187 |
+
default:
|
188 |
+
return 'METHOD:'.$this->method.$this->nl;
|
189 |
+
break;
|
190 |
+
}
|
191 |
+
}
|
192 |
+
/**
|
193 |
+
* set calendar property method
|
194 |
+
*
|
195 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
196 |
+
* @since 2.4.8 - 2008-20-23
|
197 |
+
* @param string $value
|
198 |
+
* @uses vcalendar::$method
|
199 |
+
* @return bool
|
200 |
+
*/
|
201 |
+
function setMethod( $value ) {
|
202 |
+
if( empty( $value )) return FALSE;
|
203 |
+
$this->method = $value;
|
204 |
+
return TRUE;
|
205 |
+
}
|
206 |
+
/*********************************************************************************/
|
207 |
+
/**
|
208 |
+
* Property Name: PRODID
|
209 |
+
*
|
210 |
+
*/
|
211 |
+
/**
|
212 |
+
* creates formatted output for calendar property prodid
|
213 |
+
*
|
214 |
+
* @copyright copyright (c) 2007-2013 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
215 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
216 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
217 |
+
* @since 2.21.11 - 2015-03-31
|
218 |
+
* @uses vcalendar::$prodid
|
219 |
+
* @uses vcalendar::_makeProdid()
|
220 |
+
* @uses vcalendar::$format
|
221 |
+
* @uses vcalendar::$nl
|
222 |
+
* @uses vcalendar::_createElement()
|
223 |
+
* @return string
|
224 |
+
*/
|
225 |
+
function createProdid() {
|
226 |
+
if( !isset( $this->prodid ))
|
227 |
+
$this->_makeProdid();
|
228 |
+
switch( $this->format ) {
|
229 |
+
case 'xcal':
|
230 |
+
return $this->nl.' prodid="'.$this->prodid.'"';
|
231 |
+
break;
|
232 |
+
default:
|
233 |
+
return $this->_createElement( 'PRODID', '', $this->prodid );
|
234 |
+
break;
|
235 |
+
}
|
236 |
+
}
|
237 |
+
/**
|
238 |
+
* make default value for calendar prodid, do NOT alter or remove this method or invoke of this method
|
239 |
+
*
|
240 |
+
* @copyright copyright (c) 2007-2013 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
241 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
242 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
243 |
+
* @since 2.6.8 - 2009-12-30
|
244 |
+
* @uses vcalendar::$prodid
|
245 |
+
* @uses vcalendar::$unique_id
|
246 |
+
* @uses ICALCREATOR_VERSION
|
247 |
+
* @uses vcalendar::$language
|
248 |
+
* @return void
|
249 |
+
*/
|
250 |
+
function _makeProdid() {
|
251 |
+
$this->prodid = $this->unique_id.strtoupper( $this->language );
|
252 |
+
}
|
253 |
+
/**
|
254 |
+
* Conformance: The property MUST be specified once in an iCalendar object.
|
255 |
+
* Description: The vendor of the implementation SHOULD assure that this
|
256 |
+
* is a globally unique identifier; using some technique such as an FPI
|
257 |
+
* value, as defined in [ISO 9070].
|
258 |
+
*/
|
259 |
+
/**
|
260 |
+
* make default unique_id for calendar prodid
|
261 |
+
*
|
262 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
263 |
+
* @since 0.3.0 - 2006-08-10
|
264 |
+
* @uses vcalendar::$unique_id
|
265 |
+
* @return void
|
266 |
+
*/
|
267 |
+
function _makeUnique_id() {
|
268 |
+
$this->unique_id = ( isset( $_SERVER['SERVER_NAME'] )) ? gethostbyname( $_SERVER['SERVER_NAME'] ) : 'localhost';
|
269 |
+
}
|
270 |
+
/*********************************************************************************/
|
271 |
+
/**
|
272 |
+
* Property Name: VERSION
|
273 |
+
*
|
274 |
+
* Description: A value of "2.0" corresponds to this memo.
|
275 |
+
*/
|
276 |
+
/**
|
277 |
+
* creates formatted output for calendar property version
|
278 |
+
|
279 |
+
*
|
280 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
281 |
+
* @since 2.10.16 - 2011-10-28
|
282 |
+
* @uses vcalendar::$version
|
283 |
+
* @uses vcalendar::$format
|
284 |
+
* @uses vcalendar::$nl
|
285 |
+
* @return string
|
286 |
+
*/
|
287 |
+
function createVersion() {
|
288 |
+
if( empty( $this->version ))
|
289 |
+
$this->_makeVersion();
|
290 |
+
switch( $this->format ) {
|
291 |
+
case 'xcal':
|
292 |
+
return $this->nl.' version="'.$this->version.'"';
|
293 |
+
break;
|
294 |
+
default:
|
295 |
+
return 'VERSION:'.$this->version.$this->nl;
|
296 |
+
break;
|
297 |
+
}
|
298 |
+
}
|
299 |
+
/**
|
300 |
+
* set default calendar version
|
301 |
+
*
|
302 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
303 |
+
* @since 0.3.0 - 2006-08-10
|
304 |
+
* @uses vcalendar::$version
|
305 |
+
* @return void
|
306 |
+
*/
|
307 |
+
function _makeVersion() {
|
308 |
+
$this->version = '2.0';
|
309 |
+
}
|
310 |
+
/**
|
311 |
+
* set calendar version
|
312 |
+
*
|
313 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
314 |
+
* @since 2.4.8 - 2008-10-23
|
315 |
+
* @param string $value
|
316 |
+
* @uses vcalendar::$version
|
317 |
+
* @return void
|
318 |
+
*/
|
319 |
+
function setVersion( $value ) {
|
320 |
+
if( empty( $value )) return FALSE;
|
321 |
+
$this->version = $value;
|
322 |
+
return TRUE;
|
323 |
+
}
|
324 |
+
/*********************************************************************************/
|
325 |
+
/*********************************************************************************/
|
326 |
+
/**
|
327 |
+
* delete calendar property value
|
328 |
+
*
|
329 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
330 |
+
* @since 2.8.8 - 2011-03-15
|
331 |
+
* @param mixed $propName bool FALSE => X-property
|
332 |
+
* @param int $propix specific property in case of multiply occurences
|
333 |
+
* @uses vcalendar::$propdelix
|
334 |
+
* @uses vcalendar::$calscale
|
335 |
+
* @uses vcalendar::$method
|
336 |
+
* @uses vcalendar::$xprop
|
337 |
+
* @return bool, if successfull delete
|
338 |
+
*/
|
339 |
+
function deleteProperty( $propName=FALSE, $propix=FALSE ) {
|
340 |
+
$propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
|
341 |
+
if( !$propix )
|
342 |
+
$propix = ( isset( $this->propdelix[$propName] ) && ( 'X-PROP' != $propName )) ? $this->propdelix[$propName] + 2 : 1;
|
343 |
+
$this->propdelix[$propName] = --$propix;
|
344 |
+
$return = FALSE;
|
345 |
+
switch( $propName ) {
|
346 |
+
case 'CALSCALE':
|
347 |
+
if( isset( $this->calscale )) {
|
348 |
+
$this->calscale = null;
|
349 |
+
$return = TRUE;
|
350 |
+
}
|
351 |
+
break;
|
352 |
+
case 'METHOD':
|
353 |
+
if( isset( $this->method )) {
|
354 |
+
$this->method = null;
|
355 |
+
$return = TRUE;
|
356 |
+
}
|
357 |
+
break;
|
358 |
+
default:
|
359 |
+
$reduced = array();
|
360 |
+
if( $propName != 'X-PROP' ) {
|
361 |
+
if( !isset( $this->xprop[$propName] )) { unset( $this->propdelix[$propName] ); return FALSE; }
|
362 |
+
foreach( $this->xprop as $k => $a ) {
|
363 |
+
if(( $k != $propName ) && !empty( $a ))
|
364 |
+
$reduced[$k] = $a;
|
365 |
+
}
|
366 |
+
}
|
367 |
+
else {
|
368 |
+
if( count( $this->xprop ) <= $propix ) return FALSE;
|
369 |
+
$xpropno = 0;
|
370 |
+
foreach( $this->xprop as $xpropkey => $xpropvalue ) {
|
371 |
+
if( $propix != $xpropno )
|
372 |
+
$reduced[$xpropkey] = $xpropvalue;
|
373 |
+
$xpropno++;
|
374 |
+
}
|
375 |
+
}
|
376 |
+
$this->xprop = $reduced;
|
377 |
+
if( empty( $this->xprop )) {
|
378 |
+
unset( $this->propdelix[$propName] );
|
379 |
+
return FALSE;
|
380 |
+
}
|
381 |
+
return TRUE;
|
382 |
+
}
|
383 |
+
return $return;
|
384 |
+
}
|
385 |
+
/**
|
386 |
+
* get calendar property value/params
|
387 |
+
*
|
388 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
389 |
+
* @since 2.21.09 - 2015-03-29
|
390 |
+
* @param string $propName
|
391 |
+
* @param int $propix specific property in case of multiply occurences
|
392 |
+
* @param bool $inclParam
|
393 |
+
* @uses vcalendar::$propix
|
394 |
+
* @uses vcalendar::$components
|
395 |
+
* @uses calendarComponent::$objName
|
396 |
+
* @uses iCalUtilityFunctions::$vComps
|
397 |
+
* @uses iCalUtilityFunctions::$mProps1
|
398 |
+
* @uses calendarComponent::_getProperties()
|
399 |
+
* @uses calendarComponent::getProperty()
|
400 |
+
* @uses iCalUtilityFunctions::_geo2str2()
|
401 |
+
* @uses iCalUtilityFunctions::$geoLatFmt
|
402 |
+
* @uses iCalUtilityFunctions::$geoLongFmt
|
403 |
+
* @uses iCalUtilityFunctions::$fmt
|
404 |
+
* @uses vcalendar::$calscale
|
405 |
+
* @uses vcalendar::$method
|
406 |
+
* @uses vcalendar::$prodid
|
407 |
+
* @uses vcalendar::_makeProdid()
|
408 |
+
* @uses vcalendar::$version
|
409 |
+
* @uses vcalendar::$xprop
|
410 |
+
* @return mixed
|
411 |
+
*/
|
412 |
+
function getProperty( $propName=FALSE, $propix=FALSE, $inclParam=FALSE ) {
|
413 |
+
$propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
|
414 |
+
if( 'X-PROP' == $propName ) {
|
415 |
+
if( empty( $propix ))
|
416 |
+
$propix = ( isset( $this->propix[$propName] )) ? $this->propix[$propName] + 2 : 1;
|
417 |
+
$this->propix[$propName] = --$propix;
|
418 |
+
}
|
419 |
+
switch( $propName ) {
|
420 |
+
case 'ATTENDEE':
|
421 |
+
case 'CATEGORIES':
|
422 |
+
case 'CONTACT':
|
423 |
+
case 'DTSTART':
|
424 |
+
case 'GEOLOCATION':
|
425 |
+
case 'LOCATION':
|
426 |
+
case 'ORGANIZER':
|
427 |
+
case 'PRIORITY':
|
428 |
+
case 'RESOURCES':
|
429 |
+
case 'STATUS':
|
430 |
+
case 'SUMMARY':
|
431 |
+
case 'RECURRENCE-ID-UID':
|
432 |
+
case 'RELATED-TO':
|
433 |
+
case 'R-UID':
|
434 |
+
case 'UID':
|
435 |
+
case 'URL':
|
436 |
+
$output = array();
|
437 |
+
foreach ( $this->components as $cix => $component) {
|
438 |
+
if( !in_array( $component->objName, iCalUtilityFunctions::$vComps ))
|
439 |
+
continue;
|
440 |
+
if( in_array( $propName, iCalUtilityFunctions::$mProps1 )) {
|
441 |
+
$component->_getProperties( $propName, $output );
|
442 |
+
continue;
|
443 |
+
}
|
444 |
+
elseif(( 3 < strlen( $propName )) && ( 'UID' == substr( $propName, -3 ))) {
|
445 |
+
if( FALSE !== ( $content = $component->getProperty( 'RECURRENCE-ID' )))
|
446 |
+
$content = $component->getProperty( 'UID' );
|
447 |
+
}
|
448 |
+
elseif( 'GEOLOCATION' == $propName ) {
|
449 |
+
$content = ( FALSE === ( $loc = $component->getProperty( 'LOCATION' ))) ? '' : $loc.' ';
|
450 |
+
if( FALSE === ( $geo = $component->getProperty( 'GEO' )))
|
451 |
+
continue;
|
452 |
+
$content .= iCalUtilityFunctions::_geo2str2( $geo['latitude'], iCalUtilityFunctions::$geoLatFmt ).
|
453 |
+
iCalUtilityFunctions::_geo2str2( $geo['longitude'], iCalUtilityFunctions::$geoLongFmt ).'/';
|
454 |
+
}
|
455 |
+
elseif( FALSE === ( $content = $component->getProperty( $propName )))
|
456 |
+
continue;
|
457 |
+
if(( FALSE === $content ) || empty( $content ))
|
458 |
+
continue;
|
459 |
+
elseif( is_array( $content )) {
|
460 |
+
if( isset( $content['year'] )) {
|
461 |
+
$key = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $content['year'], (int) $content['month'], (int) $content['day'] );
|
462 |
+
if( !isset( $output[$key] ))
|
463 |
+
$output[$key] = 1;
|
464 |
+
else
|
465 |
+
$output[$key] += 1;
|
466 |
+
}
|
467 |
+
else {
|
468 |
+
foreach( $content as $partValue => $partCount ) {
|
469 |
+
if( !isset( $output[$partValue] ))
|
470 |
+
$output[$partValue] = $partCount;
|
471 |
+
else
|
472 |
+
$output[$partValue] += $partCount;
|
473 |
+
}
|
474 |
+
}
|
475 |
+
} // end elseif( is_array( $content )) {
|
476 |
+
elseif( !isset( $output[$content] ))
|
477 |
+
$output[$content] = 1;
|
478 |
+
else
|
479 |
+
$output[$content] += 1;
|
480 |
+
} // end foreach ( $this->components as $cix => $component)
|
481 |
+
if( !empty( $output ))
|
482 |
+
ksort( $output );
|
483 |
+
return $output;
|
484 |
+
break;
|
485 |
+
case 'CALSCALE':
|
486 |
+
return ( !empty( $this->calscale )) ? $this->calscale : FALSE;
|
487 |
+
break;
|
488 |
+
case 'METHOD':
|
489 |
+
return ( !empty( $this->method )) ? $this->method : FALSE;
|
490 |
+
break;
|
491 |
+
case 'PRODID':
|
492 |
+
if( empty( $this->prodid ))
|
493 |
+
$this->_makeProdid();
|
494 |
+
return $this->prodid;
|
495 |
+
break;
|
496 |
+
case 'VERSION':
|
497 |
+
return ( !empty( $this->version )) ? $this->version : FALSE;
|
498 |
+
break;
|
499 |
+
default:
|
500 |
+
if( $propName != 'X-PROP' ) {
|
501 |
+
if( !isset( $this->xprop[$propName] )) return FALSE;
|
502 |
+
return ( $inclParam ) ? array( $propName, $this->xprop[$propName] )
|
503 |
+
: array( $propName, $this->xprop[$propName]['value'] );
|
504 |
+
}
|
505 |
+
else {
|
506 |
+
if( empty( $this->xprop )) return FALSE;
|
507 |
+
$xpropno = 0;
|
508 |
+
foreach( $this->xprop as $xpropkey => $xpropvalue ) {
|
509 |
+
if( $propix == $xpropno )
|
510 |
+
return ( $inclParam ) ? array( $xpropkey, $this->xprop[$xpropkey] )
|
511 |
+
: array( $xpropkey, $this->xprop[$xpropkey]['value'] );
|
512 |
+
else
|
513 |
+
$xpropno++;
|
514 |
+
}
|
515 |
+
unset( $this->propix[$propName] );
|
516 |
+
return FALSE; // not found ??
|
517 |
+
}
|
518 |
+
}
|
519 |
+
return FALSE;
|
520 |
+
}
|
521 |
+
/**
|
522 |
+
* general vcalendar property setting
|
523 |
+
*
|
524 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
525 |
+
* @since 2.2.13 - 2007-11-04
|
526 |
+
* @param mixed $args variable number of function arguments,
|
527 |
+
* first argument is ALWAYS component name,
|
528 |
+
* second ALWAYS component value!
|
529 |
+
* @uses vcalendar::setCalscale()
|
530 |
+
* @uses vcalendar::setMethod()
|
531 |
+
* @uses vcalendar::setVersion()
|
532 |
+
* @uses vcalendar::setXprop()
|
533 |
+
* @return bool
|
534 |
+
*/
|
535 |
+
function setProperty () {
|
536 |
+
$numargs = func_num_args();
|
537 |
+
if( 1 > $numargs )
|
538 |
+
return FALSE;
|
539 |
+
$arglist = func_get_args();
|
540 |
+
$arglist[0] = strtoupper( $arglist[0] );
|
541 |
+
switch( $arglist[0] ) {
|
542 |
+
case 'CALSCALE':
|
543 |
+
return $this->setCalscale( $arglist[1] );
|
544 |
+
case 'METHOD':
|
545 |
+
return $this->setMethod( $arglist[1] );
|
546 |
+
case 'VERSION':
|
547 |
+
return $this->setVersion( $arglist[1] );
|
548 |
+
default:
|
549 |
+
if( !isset( $arglist[1] )) $arglist[1] = null;
|
550 |
+
if( !isset( $arglist[2] )) $arglist[2] = null;
|
551 |
+
return $this->setXprop( $arglist[0], $arglist[1], $arglist[2] );
|
552 |
+
}
|
553 |
+
return FALSE;
|
554 |
+
}
|
555 |
+
/*********************************************************************************/
|
556 |
+
/**
|
557 |
+
* get vcalendar config values or * calendar components
|
558 |
+
*
|
559 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
560 |
+
* @since 2.11.7 - 2012-01-12
|
561 |
+
* @param mixed $config
|
562 |
+
* @uses vcalendar::getConfig()
|
563 |
+
* @uses vcalendar::$allowEmpty
|
564 |
+
* @uses vcalendar::$components
|
565 |
+
* @uses calendarComponent::_getProperties()
|
566 |
+
* @uses calendarComponent::$objName
|
567 |
+
* @uses calendarComponent::getProperty()
|
568 |
+
* @uses calendarComponent::_getConfig()
|
569 |
+
* @uses vcalendar::$url
|
570 |
+
* @uses vcalendar::$delimiter
|
571 |
+
* @uses vcalendar::$directory
|
572 |
+
* @uses vcalendar::$filename
|
573 |
+
* @uses vcalendar::$format
|
574 |
+
* @uses vcalendar::$language
|
575 |
+
* @uses vcalendar::$nl
|
576 |
+
* @uses vcalendar::$dtzid
|
577 |
+
* @uses vcalendar::$unique_id
|
578 |
+
* @return value
|
579 |
+
*/
|
580 |
+
function getConfig( $config = FALSE ) {
|
581 |
+
if( !$config ) {
|
582 |
+
$return = array();
|
583 |
+
$return['ALLOWEMPTY'] = $this->getConfig( 'ALLOWEMPTY' );
|
584 |
+
$return['DELIMITER'] = $this->getConfig( 'DELIMITER' );
|
585 |
+
$return['DIRECTORY'] = $this->getConfig( 'DIRECTORY' );
|
586 |
+
$return['FILENAME'] = $this->getConfig( 'FILENAME' );
|
587 |
+
$return['DIRFILE'] = $this->getConfig( 'DIRFILE' );
|
588 |
+
$return['FILESIZE'] = $this->getConfig( 'FILESIZE' );
|
589 |
+
$return['FORMAT'] = $this->getConfig( 'FORMAT' );
|
590 |
+
if( FALSE !== ( $lang = $this->getConfig( 'LANGUAGE' )))
|
591 |
+
$return['LANGUAGE'] = $lang;
|
592 |
+
$return['NEWLINECHAR'] = $this->getConfig( 'NEWLINECHAR' );
|
593 |
+
$return['UNIQUE_ID'] = $this->getConfig( 'UNIQUE_ID' );
|
594 |
+
if( FALSE !== ( $url = $this->getConfig( 'URL' )))
|
595 |
+
$return['URL'] = $url;
|
596 |
+
$return['TZID'] = $this->getConfig( 'TZID' );
|
597 |
+
return $return;
|
598 |
+
}
|
599 |
+
switch( strtoupper( $config )) {
|
600 |
+
case 'ALLOWEMPTY':
|
601 |
+
return $this->allowEmpty;
|
602 |
+
break;
|
603 |
+
case 'COMPSINFO':
|
604 |
+
unset( $this->compix );
|
605 |
+
$info = array();
|
606 |
+
foreach( $this->components as $cix => $component ) {
|
607 |
+
if( empty( $component )) continue;
|
608 |
+
$info[$cix]['ordno'] = $cix + 1;
|
609 |
+
$info[$cix]['type'] = $component->objName;
|
610 |
+
$info[$cix]['uid'] = $component->getProperty( 'uid' );
|
611 |
+
$info[$cix]['props'] = $component->getConfig( 'propinfo' );
|
612 |
+
$info[$cix]['sub'] = $component->getConfig( 'compsinfo' );
|
613 |
+
}
|
614 |
+
return $info;
|
615 |
+
break;
|
616 |
+
case 'DELIMITER':
|
617 |
+
return $this->delimiter;
|
618 |
+
break;
|
619 |
+
case 'DIRECTORY':
|
620 |
+
if( empty( $this->directory ) && ( '0' != $this->directory ))
|
621 |
+
$this->directory = '.';
|
622 |
+
return $this->directory;
|
623 |
+
break;
|
624 |
+
case 'DIRFILE':
|
625 |
+
return $this->getConfig( 'directory' ).$this->getConfig( 'delimiter' ).$this->getConfig( 'filename' );
|
626 |
+
break;
|
627 |
+
case 'FILEINFO':
|
628 |
+
return array( $this->getConfig( 'directory' )
|
629 |
+
, $this->getConfig( 'filename' )
|
630 |
+
, $this->getConfig( 'filesize' ));
|
631 |
+
break;
|
632 |
+
case 'FILENAME':
|
633 |
+
if( empty( $this->filename ) && ( '0' != $this->filename )) {
|
634 |
+
if( 'xcal' == $this->format )
|
635 |
+
$this->filename = date( 'YmdHis' ).'.xml'; // recommended xcs.. .
|
636 |
+
else
|
637 |
+
$this->filename = date( 'YmdHis' ).'.ics';
|
638 |
+
}
|
639 |
+
return $this->filename;
|
640 |
+
break;
|
641 |
+
case 'FILESIZE':
|
642 |
+
$size = 0;
|
643 |
+
if( empty( $this->url )) {
|
644 |
+
$dirfile = $this->getConfig( 'dirfile' );
|
645 |
+
if( !is_file( $dirfile ) || ( FALSE === ( $size = filesize( $dirfile ))))
|
646 |
+
$size = 0;
|
647 |
+
clearstatcache();
|
648 |
+
}
|
649 |
+
return $size;
|
650 |
+
break;
|
651 |
+
case 'FORMAT':
|
652 |
+
return ( $this->format == 'xcal' ) ? 'xCal' : 'iCal';
|
653 |
+
break;
|
654 |
+
case 'LANGUAGE':
|
655 |
+
/* get language for calendar component as defined in [RFC 1766] */
|
656 |
+
return $this->language;
|
657 |
+
break;
|
658 |
+
case 'NL':
|
659 |
+
case 'NEWLINECHAR':
|
660 |
+
return $this->nl;
|
661 |
+
break;
|
662 |
+
case 'TZID':
|
663 |
+
return $this->dtzid;
|
664 |
+
break;
|
665 |
+
case 'UNIQUE_ID':
|
666 |
+
return $this->unique_id;
|
667 |
+
break;
|
668 |
+
case 'URL':
|
669 |
+
if( !empty( $this->url ))
|
670 |
+
return $this->url;
|
671 |
+
else
|
672 |
+
return FALSE;
|
673 |
+
break;
|
674 |
+
}
|
675 |
+
}
|
676 |
+
/**
|
677 |
+
* general vcalendar config setting
|
678 |
+
*
|
679 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
680 |
+
* @since 2.20.2 - 2014-05-09
|
681 |
+
* @param mixed $config
|
682 |
+
* @param string $value
|
683 |
+
* @uses vcalendar::setConfig()
|
684 |
+
* @uses vcalendar::$allowEmpty
|
685 |
+
* @uses vcalendar::$components
|
686 |
+
* @uses vcalendar::$url
|
687 |
+
* @uses vcalendar::$delimiter
|
688 |
+
* @uses vcalendar::$directory
|
689 |
+
* @uses vcalendar::$filename
|
690 |
+
* @uses vcalendar::$format
|
691 |
+
* @uses vcalendar::$language
|
692 |
+
* @uses vcalendar::$nl
|
693 |
+
* @uses vcalendar::$dtzid
|
694 |
+
* @uses vcalendar::$unique_id
|
695 |
+
* @uses vcalendar::_makeProdid()
|
696 |
+
* @uses vcalendar::$components
|
697 |
+
* @uses calendarComponent::setConfig()
|
698 |
+
* @uses calendarComponent::copy()
|
699 |
+
* @return void
|
700 |
+
*/
|
701 |
+
function setConfig( $config, $value = FALSE) {
|
702 |
+
if( is_array( $config )) {
|
703 |
+
$config = array_change_key_case( $config, CASE_UPPER );
|
704 |
+
if( isset( $config['DELIMITER'] )) {
|
705 |
+
if( FALSE === $this->setConfig( 'DELIMITER', $config['DELIMITER'] ))
|
706 |
+
return FALSE;
|
707 |
+
unset( $config['DELIMITER'] );
|
708 |
+
}
|
709 |
+
if( isset( $config['DIRECTORY'] )) {
|
710 |
+
if( FALSE === $this->setConfig( 'DIRECTORY', $config['DIRECTORY'] ))
|
711 |
+
return FALSE;
|
712 |
+
unset( $config['DIRECTORY'] );
|
713 |
+
}
|
714 |
+
foreach( $config as $cKey => $cValue ) {
|
715 |
+
if( FALSE === $this->setConfig( $cKey, $cValue ))
|
716 |
+
return FALSE;
|
717 |
+
}
|
718 |
+
return TRUE;
|
719 |
+
}
|
720 |
+
else
|
721 |
+
$res = FALSE;
|
722 |
+
$config = strtoupper( $config );
|
723 |
+
switch( $config ) {
|
724 |
+
case 'ALLOWEMPTY':
|
725 |
+
$this->allowEmpty = $value;
|
726 |
+
$subcfg = array( 'ALLOWEMPTY' => $value );
|
727 |
+
$res = TRUE;
|
728 |
+
break;
|
729 |
+
case 'DELIMITER':
|
730 |
+
$this->delimiter = $value;
|
731 |
+
return TRUE;
|
732 |
+
break;
|
733 |
+
case 'DIRECTORY':
|
734 |
+
if( FALSE === ( $value = realpath( rtrim( trim( $value ), $this->delimiter ))))
|
735 |
+
return FALSE;
|
736 |
+
else {
|
737 |
+
/* local directory */
|
738 |
+
$this->directory = $value;
|
739 |
+
$this->url = null;
|
740 |
+
return TRUE;
|
741 |
+
}
|
742 |
+
break;
|
743 |
+
case 'FILENAME':
|
744 |
+
$value = trim( $value );
|
745 |
+
$dirfile = $this->directory.$this->delimiter.$value;
|
746 |
+
if( file_exists( $dirfile )) {
|
747 |
+
/* local file exists */
|
748 |
+
if( is_readable( $dirfile ) || is_writable( $dirfile )) {
|
749 |
+
clearstatcache();
|
750 |
+
$this->filename = $value;
|
751 |
+
return TRUE;
|
752 |
+
}
|
753 |
+
else
|
754 |
+
return FALSE;
|
755 |
+
}
|
756 |
+
elseif( is_readable( $this->directory ) || is_writable( $this->directory )) {
|
757 |
+
/* read- or writable directory */
|
758 |
+
clearstatcache();
|
759 |
+
$this->filename = $value;
|
760 |
+
return TRUE;
|
761 |
+
}
|
762 |
+
else
|
763 |
+
return FALSE;
|
764 |
+
break;
|
765 |
+
case 'FORMAT':
|
766 |
+
$value = trim( strtolower( $value ));
|
767 |
+
if( 'xcal' == $value ) {
|
768 |
+
$this->format = 'xcal';
|
769 |
+
$this->attributeDelimiter = $this->nl;
|
770 |
+
$this->valueInit = null;
|
771 |
+
}
|
772 |
+
else {
|
773 |
+
$this->format = null;
|
774 |
+
$this->attributeDelimiter = ';';
|
775 |
+
$this->valueInit = ':';
|
776 |
+
}
|
777 |
+
$subcfg = array( 'FORMAT' => $value );
|
778 |
+
$res = TRUE;
|
779 |
+
break;
|
780 |
+
case 'LANGUAGE': // set language for calendar component as defined in [RFC 1766]
|
781 |
+
$value = trim( $value );
|
782 |
+
$this->language = $value;
|
783 |
+
$this->_makeProdid();
|
784 |
+
$subcfg = array( 'LANGUAGE' => $value );
|
785 |
+
$res = TRUE;
|
786 |
+
break;
|
787 |
+
case 'NL':
|
788 |
+
case 'NEWLINECHAR':
|
789 |
+
$this->nl = $value;
|
790 |
+
if( 'xcal' == $value ) {
|
791 |
+
$this->attributeDelimiter = $this->nl;
|
792 |
+
$this->valueInit = null;
|
793 |
+
}
|
794 |
+
else {
|
795 |
+
$this->attributeDelimiter = ';';
|
796 |
+
$this->valueInit = ':';
|
797 |
+
}
|
798 |
+
$subcfg = array( 'NL' => $value );
|
799 |
+
$res = TRUE;
|
800 |
+
break;
|
801 |
+
case 'TZID':
|
802 |
+
$this->dtzid = $value;
|
803 |
+
$subcfg = array( 'TZID' => $value );
|
804 |
+
$res = TRUE;
|
805 |
+
break;
|
806 |
+
case 'UNIQUE_ID':
|
807 |
+
$value = trim( $value );
|
808 |
+
$this->unique_id = $value;
|
809 |
+
$this->_makeProdid();
|
810 |
+
$subcfg = array( 'UNIQUE_ID' => $value );
|
811 |
+
$res = TRUE;
|
812 |
+
break;
|
813 |
+
case 'URL':
|
814 |
+
/* remote file - URL */
|
815 |
+
$value = str_replace( array( 'HTTP://', 'WEBCAL://', 'webcal://' ), 'http://', trim( $value ));
|
816 |
+
$value = str_replace( 'HTTPS://', 'https://', trim( $value ));
|
817 |
+
if(( 'http://' != substr( $value, 0, 7 )) && ( 'https://' != substr( $value, 0, 8 )))
|
818 |
+
return FALSE;
|
819 |
+
$this->directory = '.';
|
820 |
+
$this->url = $value;
|
821 |
+
if( '.ics' != strtolower( substr( $value, -4 )))
|
822 |
+
unset( $this->filename );
|
823 |
+
else
|
824 |
+
$this->filename = basename( $value );
|
825 |
+
return TRUE;
|
826 |
+
break;
|
827 |
+
default: // any unvalid config key.. .
|
828 |
+
return TRUE;
|
829 |
+
}
|
830 |
+
if( !$res ) return FALSE;
|
831 |
+
if( isset( $subcfg ) && !empty( $this->components )) {
|
832 |
+
foreach( $subcfg as $cfgkey => $cfgvalue ) {
|
833 |
+
foreach( $this->components as $cix => $component ) {
|
834 |
+
$res = $component->setConfig( $cfgkey, $cfgvalue, TRUE );
|
835 |
+
if( !$res )
|
836 |
+
break 2;
|
837 |
+
$this->components[$cix] = $component->copy(); // PHP4 compliant
|
838 |
+
}
|
839 |
+
}
|
840 |
+
}
|
841 |
+
return $res;
|
842 |
+
}
|
843 |
+
/*********************************************************************************/
|
844 |
+
/**
|
845 |
+
* add calendar component to container
|
846 |
+
*
|
847 |
+
* alias to setComponent
|
848 |
+
*
|
849 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
850 |
+
* @since 1.x.x - 2007-04-24
|
851 |
+
* @param object $component calendar component
|
852 |
+
* @uses vcalendar::setComponent()
|
853 |
+
* @return void
|
854 |
+
*/
|
855 |
+
function addComponent( $component ) {
|
856 |
+
$this->setComponent( $component );
|
857 |
+
}
|
858 |
+
/**
|
859 |
+
* delete calendar component from container
|
860 |
+
*
|
861 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
862 |
+
* @since 2.8.8 - 2011-03-15
|
863 |
+
* @param mixed $arg1 ordno / component type / component uid
|
864 |
+
* @param mixed $arg2 optional, ordno if arg1 = component type
|
865 |
+
* @uses vcalendar::$components
|
866 |
+
* @uses calendarComponent::$objName
|
867 |
+
* @uses calendarComponent::getProperty()
|
868 |
+
* @return void
|
869 |
+
*/
|
870 |
+
function deleteComponent( $arg1, $arg2=FALSE ) {
|
871 |
+
$argType = $index = null;
|
872 |
+
if ( ctype_digit( (string) $arg1 )) {
|
873 |
+
$argType = 'INDEX';
|
874 |
+
$index = (int) $arg1 - 1;
|
875 |
+
}
|
876 |
+
elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
|
877 |
+
$argType = strtolower( $arg1 );
|
878 |
+
$index = ( !empty( $arg2 ) && ctype_digit( (string) $arg2 )) ? (( int ) $arg2 - 1 ) : 0;
|
879 |
+
}
|
880 |
+
$cix1dC = 0;
|
881 |
+
foreach ( $this->components as $cix => $component) {
|
882 |
+
if( empty( $component )) continue;
|
883 |
+
if(( 'INDEX' == $argType ) && ( $index == $cix )) {
|
884 |
+
unset( $this->components[$cix] );
|
885 |
+
return TRUE;
|
886 |
+
}
|
887 |
+
elseif( $argType == $component->objName ) {
|
888 |
+
if( $index == $cix1dC ) {
|
889 |
+
unset( $this->components[$cix] );
|
890 |
+
return TRUE;
|
891 |
+
}
|
892 |
+
$cix1dC++;
|
893 |
+
}
|
894 |
+
elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
|
895 |
+
unset( $this->components[$cix] );
|
896 |
+
return TRUE;
|
897 |
+
}
|
898 |
+
}
|
899 |
+
return FALSE;
|
900 |
+
}
|
901 |
+
/**
|
902 |
+
* get calendar component from container
|
903 |
+
*
|
904 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
905 |
+
* @since 2.21.11 - 2015-03-21
|
906 |
+
* @param mixed $arg1 optional, ordno/component type/ component uid
|
907 |
+
* @param mixed $arg2 optional, ordno if arg1 = component type
|
908 |
+
* @uses vcalendar::$compix
|
909 |
+
* @uses vcalendar::$components
|
910 |
+
* @uses iCalUtilityFunctions::$dateProps
|
911 |
+
* @uses iCalUtilityFunctions::$otherProps
|
912 |
+
* @uses iCalUtilityFunctions::$mProps1
|
913 |
+
* @uses calendarComponent::copy()
|
914 |
+
* @uses calendarComponent::$objName
|
915 |
+
* @uses calendarComponent::_getProperties()
|
916 |
+
* @uses calendarComponent::getProperty()
|
917 |
+
* @uses iCalUtilityFunctions::$fmt
|
918 |
+
* @return object
|
919 |
+
*/
|
920 |
+
function getComponent( $arg1=FALSE, $arg2=FALSE ) {
|
921 |
+
$index = $argType = null;
|
922 |
+
if ( !$arg1 ) { // first or next in component chain
|
923 |
+
$argType = 'INDEX';
|
924 |
+
$index = $this->compix['INDEX'] = ( isset( $this->compix['INDEX'] )) ? $this->compix['INDEX'] + 1 : 1;
|
925 |
+
}
|
926 |
+
elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
|
927 |
+
$arg2 = implode( '-', array_keys( $arg1 ));
|
928 |
+
$index = $this->compix[$arg2] = ( isset( $this->compix[$arg2] )) ? $this->compix[$arg2] + 1 : 1;
|
929 |
+
}
|
930 |
+
elseif ( ctype_digit( (string) $arg1 )) { // specific component in chain
|
931 |
+
$argType = 'INDEX';
|
932 |
+
$index = (int) $arg1;
|
933 |
+
unset( $this->compix );
|
934 |
+
}
|
935 |
+
elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) { // object class name
|
936 |
+
unset( $this->compix['INDEX'] );
|
937 |
+
$argType = strtolower( $arg1 );
|
938 |
+
if( !$arg2 )
|
939 |
+
$index = $this->compix[$argType] = ( isset( $this->compix[$argType] )) ? $this->compix[$argType] + 1 : 1;
|
940 |
+
elseif( isset( $arg2 ) && ctype_digit( (string) $arg2 ))
|
941 |
+
$index = (int) $arg2;
|
942 |
+
}
|
943 |
+
elseif(( strlen( $arg1 ) > strlen( 'vfreebusy' )) && ( FALSE !== strpos( $arg1, '@' ))) { // UID as 1st argument
|
944 |
+
if( !$arg2 )
|
945 |
+
$index = $this->compix[$arg1] = ( isset( $this->compix[$arg1] )) ? $this->compix[$arg1] + 1 : 1;
|
946 |
+
elseif( isset( $arg2 ) && ctype_digit( (string) $arg2 ))
|
947 |
+
$index = (int) $arg2;
|
948 |
+
}
|
949 |
+
if( isset( $index ))
|
950 |
+
$index -= 1;
|
951 |
+
$ckeys = array_keys( $this->components );
|
952 |
+
if( !empty( $index) && ( $index > end( $ckeys )))
|
953 |
+
return FALSE;
|
954 |
+
$cix1gC = 0;
|
955 |
+
foreach ( $this->components as $cix => $component) {
|
956 |
+
if( empty( $component )) continue;
|
957 |
+
if(( 'INDEX' == $argType ) && ( $index == $cix ))
|
958 |
+
return $component->copy();
|
959 |
+
elseif( $argType == $component->objName ) {
|
960 |
+
if( $index == $cix1gC )
|
961 |
+
return $component->copy();
|
962 |
+
$cix1gC++;
|
963 |
+
}
|
964 |
+
elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
|
965 |
+
$hit = array();
|
966 |
+
$arg1 = array_change_key_case( $arg1, CASE_UPPER );
|
967 |
+
foreach( $arg1 as $pName => $pValue ) {
|
968 |
+
if( !in_array( $pName, iCalUtilityFunctions::$dateProps ) && !in_array( $pName, iCalUtilityFunctions::$otherProps ))
|
969 |
+
continue;
|
970 |
+
if( in_array( $pName, iCalUtilityFunctions::$mProps1 )) { // multiple occurrence
|
971 |
+
$propValues = array();
|
972 |
+
$component->_getProperties( $pName, $propValues );
|
973 |
+
$propValues = array_keys( $propValues );
|
974 |
+
$hit[] = ( in_array( $pValue, $propValues )) ? TRUE : FALSE;
|
975 |
+
continue;
|
976 |
+
} // end if(.. .// multiple occurrence
|
977 |
+
if( FALSE === ( $value = $component->getProperty( $pName ))) { // single occurrence
|
978 |
+
$hit[] = FALSE; // missing property
|
979 |
+
continue;
|
980 |
+
}
|
981 |
+
if( 'SUMMARY' == $pName ) { // exists within (any case)
|
982 |
+
$hit[] = ( FALSE !== stripos( $value, $pValue )) ? TRUE : FALSE;
|
983 |
+
continue;
|
984 |
+
}
|
985 |
+
if( in_array( $pName, iCalUtilityFunctions::$dateProps )) {
|
986 |
+
$valuedate = sprintf( iCalUtilityFunctions::$fmt['Ymd'], (int) $value['year'], (int) $value['month'], (int) $value['day'] );
|
987 |
+
if( 8 < strlen( $pValue )) {
|
988 |
+
if( isset( $value['hour'] )) {
|
989 |
+
if( 'T' == substr( $pValue, 8, 1 ))
|
990 |
+
$pValue = str_replace( 'T', '', $pValue );
|
991 |
+
$valuedate .= sprintf( iCalUtilityFunctions::$fmt['His'], (int) $value['hour'], (int) $value['min'], (int) $value['sec'] );
|
992 |
+
}
|
993 |
+
else
|
994 |
+
$pValue = substr( $pValue, 0, 8 );
|
995 |
+
}
|
996 |
+
$hit[] = ( $pValue == $valuedate ) ? TRUE : FALSE;
|
997 |
+
continue;
|
998 |
+
}
|
999 |
+
elseif( !is_array( $value ))
|
1000 |
+
$value = array( $value );
|
1001 |
+
foreach( $value as $part ) {
|
1002 |
+
$part = ( FALSE !== strpos( $part, ',' )) ? explode( ',', $part ) : array( $part );
|
1003 |
+
foreach( $part as $subPart ) {
|
1004 |
+
if( $pValue == $subPart ) {
|
1005 |
+
$hit[] = TRUE;
|
1006 |
+
continue 3;
|
1007 |
+
}
|
1008 |
+
}
|
1009 |
+
} // end foreach( $value as $part )
|
1010 |
+
$hit[] = FALSE; // no hit in property
|
1011 |
+
} // end foreach( $arg1 as $pName => $pValue )
|
1012 |
+
if( in_array( TRUE, $hit )) {
|
1013 |
+
if( $index == $cix1gC )
|
1014 |
+
return $component->copy();
|
1015 |
+
$cix1gC++;
|
1016 |
+
}
|
1017 |
+
} // end elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
|
1018 |
+
elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) { // UID
|
1019 |
+
if( $index == $cix1gC )
|
1020 |
+
return $component->copy();
|
1021 |
+
$cix1gC++;
|
1022 |
+
}
|
1023 |
+
} // end foreach ( $this->components.. .
|
1024 |
+
/* not found.. . */
|
1025 |
+
unset( $this->compix );
|
1026 |
+
return FALSE;
|
1027 |
+
}
|
1028 |
+
/**
|
1029 |
+
* create new calendar component, already included within calendar
|
1030 |
+
*
|
1031 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1032 |
+
* @since 2.20.4 - 2014-08-24
|
1033 |
+
* @param string $compType component type
|
1034 |
+
* @uses vcalendar::$components
|
1035 |
+
* @return object
|
1036 |
+
*/
|
1037 |
+
function & newComponent( $compType ) {
|
1038 |
+
$config = $this->getConfig();
|
1039 |
+
$keys = array_keys( $this->components );
|
1040 |
+
$ix = ( empty( $keys )) ? 0 : end( $keys) + 1;
|
1041 |
+
switch( strtoupper( $compType )) {
|
1042 |
+
case 'EVENT':
|
1043 |
+
case 'VEVENT':
|
1044 |
+
$this->components[$ix] = new vevent( $config );
|
1045 |
+
break;
|
1046 |
+
case 'TODO':
|
1047 |
+
case 'VTODO':
|
1048 |
+
$this->components[$ix] = new vtodo( $config );
|
1049 |
+
break;
|
1050 |
+
case 'JOURNAL':
|
1051 |
+
case 'VJOURNAL':
|
1052 |
+
$this->components[$ix] = new vjournal( $config );
|
1053 |
+
break;
|
1054 |
+
case 'FREEBUSY':
|
1055 |
+
case 'VFREEBUSY':
|
1056 |
+
$this->components[$ix] = new vfreebusy( $config );
|
1057 |
+
break;
|
1058 |
+
case 'TIMEZONE':
|
1059 |
+
case 'VTIMEZONE':
|
1060 |
+
array_unshift( $this->components, new vtimezone( $config ));
|
1061 |
+
$ix = 0;
|
1062 |
+
break;
|
1063 |
+
default:
|
1064 |
+
return FALSE;
|
1065 |
+
}
|
1066 |
+
return $this->components[$ix];
|
1067 |
+
}
|
1068 |
+
/**
|
1069 |
+
* select components from calendar on date or selectOption basis
|
1070 |
+
*
|
1071 |
+
* Ensure DTSTART is set for every component.
|
1072 |
+
* No date controls occurs.
|
1073 |
+
*
|
1074 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1075 |
+
* @since 2.21.11 - 2015-03-31
|
1076 |
+
* @param mixed $startY optional, (int) start Year, default current Year
|
1077 |
+
* ALT. (obj) start date (datetime)
|
1078 |
+
* ALT. array selecOptions ( *[ <propName> => <uniqueValue> ] )
|
1079 |
+
* @param mixed $startM optional, (int) start Month, default current Month
|
1080 |
+
* ALT. (obj) end date (datetime)
|
1081 |
+
* @param int $startD optional, start Day, default current Day
|
1082 |
+
* @param int $endY optional, end Year, default $startY
|
1083 |
+
* @param int $endM optional, end Month, default $startM
|
1084 |
+
* @param int $endD optional, end Day, default $startD
|
1085 |
+
* @param mixed $cType optional, calendar component type(-s), default FALSE=all else string/array type(-s)
|
1086 |
+
* @param bool $flat optional, FALSE (default) => output : array[Year][Month][Day][]
|
1087 |
+
* TRUE => output : array[] (ignores split)
|
1088 |
+
* @param bool $any optional, TRUE (default) - select component(-s) that occurs within period
|
1089 |
+
* FALSE - only component(-s) that starts within period
|
1090 |
+
* @param bool $split optional, TRUE (default) - one component copy every DAY it occurs during the
|
1091 |
+
* period (implies flat=FALSE)
|
1092 |
+
* FALSE - one occurance of component only in output array
|
1093 |
+
* @uses vcalendar::$components
|
1094 |
+
* @uses vcalendar::selectComponents2()
|
1095 |
+
* @uses iCalUtilityFunctions::$vComps
|
1096 |
+
* @uses calendarComponent::$objName
|
1097 |
+
* @uses calendarComponent::getProperty()
|
1098 |
+
* @uses iCaldateTime::factory()
|
1099 |
+
* @uses iCaldateTime::getTimezoneName()
|
1100 |
+
* @uses iCaldateTime::getTime()
|
1101 |
+
* @uses iCalUtilityFunctions::$fmt
|
1102 |
+
* @uses iCaldateTime::$SCbools
|
1103 |
+
* @uses iCaldateTime::format()
|
1104 |
+
* @uses iCalUtilityFunctions::_strDate2arr()
|
1105 |
+
* @uses iCalUtilityFunctions::_recur2date()
|
1106 |
+
* @uses iCalUtilityFunctions::_inScope()
|
1107 |
+
* @uses calendarComponent::copy()
|
1108 |
+
* @uses calendarComponent::setProperty()
|
1109 |
+
* @uses iCalUtilityFunctions::$fmt
|
1110 |
+
* @uses calendarComponent::deleteProperty()
|
1111 |
+
* @uses iCalUtilityFunctions::_setSortArgs()
|
1112 |
+
* @uses iCalUtilityFunctions::_cmpfcn()
|
1113 |
+
* @return array or FALSE
|
1114 |
+
*/
|
1115 |
+
function selectComponents( $startY=FALSE, $startM=FALSE, $startD=FALSE, $endY=FALSE, $endM=FALSE, $endD=FALSE, $cType=FALSE, $flat=FALSE, $any=TRUE, $split=TRUE ) {
|
1116 |
+
/* check if empty calendar */
|
1117 |
+
if( 0 >= count( $this->components )) return FALSE;
|
1118 |
+
if( is_array( $startY ))
|
1119 |
+
return $this->selectComponents2( $startY );
|
1120 |
+
/* check default dates */
|
1121 |
+
if( is_a( $startY, 'DateTime' ) && is_a( $startM, 'DateTime' )) {
|
1122 |
+
$endY = $startM->format( 'Y' );
|
1123 |
+
$endM = $startM->format( 'm' );
|
1124 |
+
$endD = $startM->format( 'd' );
|
1125 |
+
$startD = $startY->format( 'd' );
|
1126 |
+
$startM = $startY->format( 'm' );
|
1127 |
+
$startY = $startY->format( 'Y' );
|
1128 |
+
}
|
1129 |
+
else {
|
1130 |
+
if( ! $startY ) $startY = date( 'Y' );
|
1131 |
+
if( ! $startM ) $startM = date( 'm' );
|
1132 |
+
if( ! $startD ) $startD = date( 'd' );
|
1133 |
+
if( ! $endY ) $endY = $startY;
|
1134 |
+
if( ! $endM ) $endM = $startM;
|
1135 |
+
if( ! $endD ) $endD = $startD;
|
1136 |
+
}
|
1137 |
+
// echo "selectComp args={$startY}-{$startM}-{$startD} - {$endY}-{$endM}-{$endD}<br>\n"; $tcnt = 0;// test ###
|
1138 |
+
/* check component types */
|
1139 |
+
if( empty( $cType ))
|
1140 |
+
$cType = iCalUtilityFunctions::$vComps;
|
1141 |
+
else {
|
1142 |
+
if( ! is_array( $cType ))
|
1143 |
+
$cType = array( $cType );
|
1144 |
+
$cType = array_map( 'strtolower', $cType );
|
1145 |
+
foreach( $cType as $cix => $theType ) {
|
1146 |
+
if( !in_array( $theType, iCalUtilityFunctions::$vComps ))
|
1147 |
+
$cType[$cix] = 'vevent';
|
1148 |
+
}
|
1149 |
+
$cType = array_unique( $cType );
|
1150 |
+
}
|
1151 |
+
if(( FALSE === $flat ) && ( FALSE === $any )) // invalid combination
|
1152 |
+
$split = FALSE;
|
1153 |
+
if(( TRUE === $flat ) && ( TRUE === $split )) // invalid combination
|
1154 |
+
$split = FALSE;
|
1155 |
+
/* iterate components */
|
1156 |
+
$result = array();
|
1157 |
+
$this->sort( 'UID' );
|
1158 |
+
$compUIDcmp = null;
|
1159 |
+
$exdatelist = $recurridList = array();
|
1160 |
+
$intervalP1D = new DateInterval( 'P1D' );
|
1161 |
+
foreach ( $this->components as $cix => $component ) {
|
1162 |
+
if( empty( $component )) continue;
|
1163 |
+
/* deselect unvalid type components */
|
1164 |
+
if( !in_array( $component->objName, $cType ))
|
1165 |
+
continue;
|
1166 |
+
unset( $compStart, $compEnd );
|
1167 |
+
/* select start from dtstart or due if dtstart is missing */
|
1168 |
+
$prop = $component->getProperty( 'dtstart', FALSE, TRUE );
|
1169 |
+
if( empty( $prop ) && ( $component->objName == 'vtodo' ) && ( FALSE === ( $prop = $component->getProperty( 'due', FALSE, TRUE ))))
|
1170 |
+
continue;
|
1171 |
+
if( empty( $prop ))
|
1172 |
+
continue;
|
1173 |
+
/* get UID */
|
1174 |
+
$compUID = $component->getProperty( 'UID' );
|
1175 |
+
if( $compUIDcmp != $compUID ) {
|
1176 |
+
$compUIDcmp = $compUID;
|
1177 |
+
$exdatelist = $recurridList = array();
|
1178 |
+
}
|
1179 |
+
$recurrid = FALSE;
|
1180 |
+
// file_put_contents( '/opt/work/iCal/iCalcreator/iCalcreator-2.20.x/log/log.txt', "#$cix".PHP_EOL.var_export( $component, TRUE ).PHP_EOL.PHP_EOL, FILE_APPEND ); // test ###
|
1181 |
+
$compStart = iCaldateTime::factory( $prop['value'], $prop['params'], $prop['value'] );
|
1182 |
+
$dtstartTz = $compStart->getTimezoneName();
|
1183 |
+
if( isset( $prop['params']['VALUE'] ) && ( 'DATE' == $prop['params']['VALUE'] ))
|
1184 |
+
$compStartHis = '';
|
1185 |
+
else {
|
1186 |
+
$his = $compStart->getTime();
|
1187 |
+
$compStartHis = sprintf( iCalUtilityFunctions::$fmt['His'], (int) $his[0], (int) $his[1], (int) $his[2] );
|
1188 |
+
}
|
1189 |
+
/* get end date from dtend/due/duration properties */
|
1190 |
+
if( FALSE !== ( $prop = $component->getProperty( 'dtend', FALSE, TRUE ))) {
|
1191 |
+
$compEnd = iCaldateTime::factory( $prop['value'], $prop['params'], $prop['value'], $dtstartTz );
|
1192 |
+
$compEnd->SCbools[ 'dtendExist'] = TRUE;
|
1193 |
+
}
|
1194 |
+
if( empty( $prop ) && ( $component->objName == 'vtodo' ) && ( FALSE !== ( $prop = $component->getProperty( 'due', FALSE, TRUE )))) {
|
1195 |
+
$compEnd = iCaldateTime::factory( $prop['value'], $prop['params'], $prop['value'], $dtstartTz );
|
1196 |
+
$compEnd->SCbools[ 'dueExist'] = TRUE;
|
1197 |
+
}
|
1198 |
+
if( empty( $prop ) && ( FALSE !== ( $prop = $component->getProperty( 'duration', FALSE, TRUE, TRUE )))) { // in dtend (array) format
|
1199 |
+
$compEnd = iCaldateTime::factory( $prop['value'], $prop['params'], $prop['value'], $dtstartTz );
|
1200 |
+
$compEnd->SCbools[ 'durationExist'] = TRUE;
|
1201 |
+
}
|
1202 |
+
if( ! empty( $prop ) && ! isset( $prop['value']['hour'] )) {
|
1203 |
+
/* a DTEND without time part denotes an end of an event that actually ends the day before,
|
1204 |
+
for an all-day event DTSTART=20071201 DTEND=20071202, taking place 20071201!!! */
|
1205 |
+
$compEnd->SCbools[ 'endAllDayEvent'] = TRUE;
|
1206 |
+
$compEnd->modify( '-1 day' );
|
1207 |
+
$compEnd->setTime( 23, 59, 59 );
|
1208 |
+
}
|
1209 |
+
unset( $prop );
|
1210 |
+
if( empty( $compEnd )) {
|
1211 |
+
$compDuration = FALSE;
|
1212 |
+
$compEnd = clone $compStart;
|
1213 |
+
$compEnd->setTime( 23, 59, 59 ); // 23:59:59 the same day as start
|
1214 |
+
}
|
1215 |
+
else {
|
1216 |
+
if( $compEnd->format( 'Ymd' ) < $compStart->format( 'Ymd' )) { // MUST be after start date!!
|
1217 |
+
$compEnd = clone $compStart;
|
1218 |
+
$compEnd->setTime( 23, 59, 59 ); // 23:59:59 the same day as start or ???
|
1219 |
+
}
|
1220 |
+
$compDuration = $compStart->diff( $compEnd ); // DateInterval
|
1221 |
+
}
|
1222 |
+
/* check recurrence-id (note, a missing sequence is the same as sequence=0 so don't test for sequence), to alter when hit dtstart/recurlist */
|
1223 |
+
if( FALSE !== ( $prop = $component->getProperty( 'recurrence-id', FALSE, TRUE ))) {
|
1224 |
+
$recurrid = iCaldateTime::factory( $prop['value'], $prop['params'], $prop['value'], $dtstartTz );
|
1225 |
+
$rangeSet = ( isset( $prop['params']['RANGE'] ) && ( 'THISANDFUTURE' == $prop['params']['RANGE'] )) ? TRUE : FALSE;
|
1226 |
+
$recurridList[$recurrid->key] = array( clone $compStart, clone $compEnd, $compDuration, $rangeSet ); // change recur this day to new YmdHis/duration/range
|
1227 |
+
// echo "adding comp no:$cix with date=".$compStart->format(iCalUtilityFunctions::$fmt['YmdHis2e'])." to recurridList id={$recurrid->key}, newDate={$compStart->key}<br>\n"; // test ###
|
1228 |
+
unset( $prop );
|
1229 |
+
continue; // ignore any other props in the component
|
1230 |
+
} // end recurrence-id/sequence test
|
1231 |
+
// else echo "comp no:$cix with date=".$compStart->format().", NO recurrence-id<br>\n"; // test ###
|
1232 |
+
ksort( $recurridList, SORT_STRING );
|
1233 |
+
// echo 'recurridList='.implode(', ', array_keys( $recurridList ))."<br>\n"; // test ###
|
1234 |
+
$fcnStart = clone $compStart;
|
1235 |
+
$fcnStart->setDate((int) $startY, (int) $startM, (int) $startD );
|
1236 |
+
$fcnStart->setTime( 0, 0, 0 );
|
1237 |
+
$fcnEnd = clone $compEnd;
|
1238 |
+
$fcnEnd->setDate((int) $endY, (int) $endM, (int) $endD );
|
1239 |
+
$fcnEnd->setTime( 23, 59, 59 );
|
1240 |
+
// echo 'compStart='.$compStart->format().', compEnd'.$compEnd->format(); if($compDuration)echo ', interval='.$compDuration->format( iCalUtilityFunctions::$fmt['durDHis'] ); echo "<br>\n"; $tcnt = 0;// test ###
|
1241 |
+
/* *************************************************************
|
1242 |
+
make a list of optional exclude dates for component occurence from exrule and exdate
|
1243 |
+
*********************************************************** */
|
1244 |
+
$workStart = clone $compStart;
|
1245 |
+
$workStart->sub( $compDuration ? $compDuration : $intervalP1D );
|
1246 |
+
$workEnd = clone $fcnEnd;
|
1247 |
+
$workEnd->add( $compDuration ? $compDuration : $intervalP1D );
|
1248 |
+
while( FALSE !== ( $prop = $component->getProperty( 'EXRULE' ))) {
|
1249 |
+
$exdatelist2 = array();
|
1250 |
+
if( isset( $prop['UNTIL']['hour'] )) { // convert until date to dtstart timezone
|
1251 |
+
$until = iCaldateTime::factory( $prop['UNTIL'], array( 'TZID' => 'UTC' ), null, $dtstartTz );
|
1252 |
+
$until = $until->format();
|
1253 |
+
iCalUtilityFunctions::_strDate2arr( $until );
|
1254 |
+
$prop['UNTIL'] = $until;
|
1255 |
+
}
|
1256 |
+
iCalUtilityFunctions::_recur2date( $exdatelist2, $prop, $compStart, $workStart, $workEnd );
|
1257 |
+
foreach( $exdatelist2 as $k => $v )
|
1258 |
+
$exdatelist[$k.$compStartHis] = $v; // point out exact every excluded ocurrence (incl. opt. His)
|
1259 |
+
unset( $until, $exdatelist2 );
|
1260 |
+
}
|
1261 |
+
while( FALSE !== ( $prop = $component->getProperty( 'EXDATE', FALSE, TRUE ))) { // - start check exdate
|
1262 |
+
foreach( $prop['value'] as $exdate ) {
|
1263 |
+
$exdate = iCaldateTime::factory( $exdate, $prop['params'], $exdate, $dtstartTz );
|
1264 |
+
$exdatelist[$exdate->key] = TRUE;
|
1265 |
+
} // end - foreach( $exdate as $exdate )
|
1266 |
+
} // end - check exdate
|
1267 |
+
unset( $prop, $exdate );
|
1268 |
+
// echo 'exdatelist=' .implode(', ', array_keys( $exdatelist )) ."<br>\n"; // test ###
|
1269 |
+
/* *************************************************************
|
1270 |
+
select only components within.. .
|
1271 |
+
*********************************************************** */
|
1272 |
+
$xRecurrence = 1;
|
1273 |
+
if(( ! $any && iCalUtilityFunctions::_inScope( $compStart, $fcnStart, $compStart, $fcnEnd, $compStart->dateFormat )) ||
|
1274 |
+
( $any && iCalUtilityFunctions::_inScope( $fcnEnd, $compStart, $fcnStart, $compEnd, $compStart->dateFormat ))) {
|
1275 |
+
/* add the selected component (WITHIN valid dates) to output array */
|
1276 |
+
if( $flat ) { // any=true/false, ignores split
|
1277 |
+
if( !$recurrid )
|
1278 |
+
$result[$compUID] = $component->copy(); // copy original to output (but not anyone with recurrence-id)
|
1279 |
+
}
|
1280 |
+
elseif( $split ) { // split the original component
|
1281 |
+
// echo 'split org.:'.$compStart->format().' < '.$fcnStart->format( 'Ymd His e' )."<br>\n"; // test ###
|
1282 |
+
if( $compStart->format( iCalUtilityFunctions::$fmt['YmdHis2'] ) < $fcnStart->format( iCalUtilityFunctions::$fmt['YmdHis2'] ))
|
1283 |
+
$rstart = clone $fcnStart;
|
1284 |
+
else
|
1285 |
+
$rstart = clone $compStart;
|
1286 |
+
if( $compEnd->format( iCalUtilityFunctions::$fmt['YmdHis2'] ) > $fcnEnd->format( iCalUtilityFunctions::$fmt['YmdHis2'] ))
|
1287 |
+
$rend = clone $fcnEnd;
|
1288 |
+
else
|
1289 |
+
$rend = clone $compEnd;
|
1290 |
+
// echo "going to test comp no:$cix, rstart=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )." (key={$rstart->key}), end=".$rend->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )."<br>\n"; // test ###
|
1291 |
+
if( ! isset( $exdatelist[$rstart->key] )) { // not excluded in exrule/exdate
|
1292 |
+
if( isset( $recurridList[$rstart->key] )) { // change start day to new YmdHis/duration
|
1293 |
+
$k = $rstart->key;
|
1294 |
+
// echo "recurridList HIT, key={$k}, recur Date=".$recurridList[$k][0]->key."<br>\n"; // test ###
|
1295 |
+
$rstart = clone $recurridList[$k][0];
|
1296 |
+
$startHis = $rstart->getTime();
|
1297 |
+
$rend = clone $rstart;
|
1298 |
+
if( FALSE !== $recurridList[$k][2] )
|
1299 |
+
$rend->add( $recurridList[$k][2] );
|
1300 |
+
elseif( FALSE !== $compDuration )
|
1301 |
+
$rend->add( $compDuration );
|
1302 |
+
$endHis = $rend->getTime();
|
1303 |
+
unset( $recurridList[$k] );
|
1304 |
+
}
|
1305 |
+
else {
|
1306 |
+
$startHis = $compStart->getTime();
|
1307 |
+
$endHis = $compEnd->getTime();
|
1308 |
+
}
|
1309 |
+
// echo "_____testing comp no:$cix, rstart=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )." (key={$rstart->key}), end=".$rend->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )."<br>\n"; // test ###
|
1310 |
+
$cnt = 0; // exclude any recurrence START date, found in exdatelist or recurridList but accept the reccurence-id comp itself
|
1311 |
+
$occurenceDays = 1 + (int) $rstart->diff( $rend )->format( '%a' ); // count the days (incl start day)
|
1312 |
+
while( $rstart->format( iCalUtilityFunctions::$fmt['Ymd2'] ) <= $rend->format( iCalUtilityFunctions::$fmt['Ymd2'] )) {
|
1313 |
+
$cnt += 1;
|
1314 |
+
if( 1 < $occurenceDays )
|
1315 |
+
$component->setProperty( 'X-OCCURENCE', sprintf( iCalUtilityFunctions::$fmt['dayOfDays'], $cnt, $occurenceDays ));
|
1316 |
+
if( 1 < $cnt )
|
1317 |
+
$rstart->setTime( 0, 0, 0 );
|
1318 |
+
else {
|
1319 |
+
$rstart->setTime( $startHis[0], $startHis[1], $startHis[2] );
|
1320 |
+
$exdatelist[$rstart->key] = $compDuration; // make sure to exclude start day from the recurrence pattern
|
1321 |
+
}
|
1322 |
+
$component->setProperty( 'X-CURRENT-DTSTART', $rstart->format( $compStart->dateFormat ));
|
1323 |
+
if( FALSE !== $compDuration ) {
|
1324 |
+
$propName = ( isset( $compEnd->SCbools[ 'dueExist'] )) ? 'X-CURRENT-DUE' : 'X-CURRENT-DTEND';
|
1325 |
+
if( $cnt < $occurenceDays )
|
1326 |
+
$rstart->setTime( 23, 59, 59 );
|
1327 |
+
else
|
1328 |
+
$rstart->setTime( $endHis[0], $endHis[1], $endHis[2] );
|
1329 |
+
$component->setProperty( $propName, $rstart->format( $compEnd->dateFormat ));
|
1330 |
+
}
|
1331 |
+
$result[(int)$rstart->format( 'Y' )][(int)$rstart->format( 'm' )][(int)$rstart->format( 'd' )][$compUID] = $component->copy(); // copy to output
|
1332 |
+
$rstart->add( $intervalP1D );
|
1333 |
+
} // end while(( $rstart->format( 'Ymd' ) < $rend->format( 'Ymd' ))
|
1334 |
+
unset( $cnt, $occurenceDays );
|
1335 |
+
} // end if( ! isset( $exdatelist[$rstart->key] ))
|
1336 |
+
// else echo "skip no:$cix with date=".$compStart->format()."<br>\n"; // test ###
|
1337 |
+
unset( $rstart, $rend );
|
1338 |
+
} // end elseif( $split ) - else use component date
|
1339 |
+
else { // !$flat && !$split, i.e. no flat array and DTSTART within period
|
1340 |
+
$tstart = ( isset( $recurridList[$compStart->key] )) ? clone $recurridList[$k][0] : clone $compStart;
|
1341 |
+
// echo "going to test comp no:$cix with checkDate={$compStart->key} with recurridList=".implode(',',array_keys($recurridList)); // test ###
|
1342 |
+
if( ! $any || ! isset( $exdatelist[$tstart->key] )) { // exclude any recurrence date, found in exdatelist
|
1343 |
+
// echo " and copied to output<br>\n"; // test ###
|
1344 |
+
$result[(int)$tstart->format( 'Y' )][(int)$tstart->format( 'm' )][(int)$tstart->format( 'd' )][$compUID] = $component->copy(); // copy to output
|
1345 |
+
}
|
1346 |
+
unset( $tstart );
|
1347 |
+
}
|
1348 |
+
} // end (dt)start within the period OR occurs within the period
|
1349 |
+
/* *************************************************************
|
1350 |
+
if 'any' components, check components with reccurrence rules, removing all excluding dates
|
1351 |
+
*********************************************************** */
|
1352 |
+
if( TRUE === $any ) {
|
1353 |
+
$recurlist = array();
|
1354 |
+
/* make a list of optional repeating dates for component occurence, rrule, rdate */
|
1355 |
+
while( FALSE !== ( $prop = $component->getProperty( 'RRULE' ))) { // get all rrule dates (multiple values allowed)
|
1356 |
+
$recurlist2 = array();
|
1357 |
+
if( isset( $prop['UNTIL']['hour'] )) { // convert $rrule['UNTIL'] to the same timezone as DTSTART !!
|
1358 |
+
$until = iCaldateTime::factory( $prop['UNTIL'], array( 'TZID' => 'UTC' ), null, $dtstartTz );
|
1359 |
+
$until = $until->format();
|
1360 |
+
iCalUtilityFunctions::_strDate2arr( $until );
|
1361 |
+
$prop['UNTIL'] = $until;
|
1362 |
+
}
|
1363 |
+
iCalUtilityFunctions::_recur2date( $recurlist2, $prop, $compStart, $workStart, $workEnd );
|
1364 |
+
foreach( $recurlist2 as $recurkey => $recurvalue ) { // recurkey=Ymd
|
1365 |
+
$recurkey .= $compStartHis; // add opt His
|
1366 |
+
if( ! isset( $exdatelist[$recurkey] ))
|
1367 |
+
$recurlist[$recurkey] = $compDuration; // DateInterval or FALSE
|
1368 |
+
}
|
1369 |
+
unset( $prop, $until, $recurlist2 );
|
1370 |
+
}
|
1371 |
+
$workStart = clone $fcnStart;
|
1372 |
+
$workStart->sub( $compDuration ? $compDuration : $intervalP1D );
|
1373 |
+
$format = $compStart->dateFormat;
|
1374 |
+
while( FALSE !== ( $prop = $component->getProperty( 'RDATE', FALSE, TRUE ))) {
|
1375 |
+
$rdateFmt = ( isset( $prop['params']['VALUE'] )) ? $prop['params']['VALUE'] : 'DATETIME';
|
1376 |
+
$params = $prop['params'];
|
1377 |
+
$prop = $prop['value'];
|
1378 |
+
foreach( $prop as $theRdate ) {
|
1379 |
+
if( 'PERIOD' == $rdateFmt ) { // all days within PERIOD
|
1380 |
+
$rdate = iCaldateTime::factory( $theRdate[0], $params, $theRdate[0], $dtstartTz );
|
1381 |
+
if( ! iCalUtilityFunctions::_inScope( $rdate, $workStart, $rdate, $fcnEnd, $format ) || isset( $exdatelist[$rdate->key] ))
|
1382 |
+
continue;
|
1383 |
+
if( isset( $theRdate[1]['year'] )) // date-date period end
|
1384 |
+
$recurlist[$rdate->key] = $rdate->diff( iCaldateTime::factory( $theRdate[1], $params, $theRdate[1], $dtstartTz ));
|
1385 |
+
else // period duration
|
1386 |
+
$recurlist[$rdate->key] = new DateInterval( iCalUtilityFunctions::_duration2str( $theRdate[1] ));
|
1387 |
+
} // end if( 'PERIOD' == $rdateFmt )
|
1388 |
+
elseif( 'DATE' == $rdateFmt ) { // single recurrence, date
|
1389 |
+
$rdate = iCaldateTime::factory( $theRdate, array_merge( $params, array( 'TZID' => $dtstartTz )), null, $dtstartTz );
|
1390 |
+
if( iCalUtilityFunctions::_inScope( $rdate, $workStart, $rdate, $fcnEnd, $format ) && ! isset( $exdatelist[$rdate->key] ))
|
1391 |
+
$recurlist[$rdate->key.$compStartHis] = $compDuration; // set start date for recurrence + DateInterval/FALSE (+opt His)
|
1392 |
+
} // end DATE
|
1393 |
+
else { // start DATETIME
|
1394 |
+
$rdate = iCaldateTime::factory( $theRdate, $params, $theRdate, $dtstartTz );
|
1395 |
+
if( iCalUtilityFunctions::_inScope( $rdate, $workStart, $rdate, $fcnEnd, $format ) && ! isset( $exdatelist[$rdate->key] ))
|
1396 |
+
$recurlist[$rdate->key] = $compDuration; // set start datetime for recurrence DateInterval/FALSE
|
1397 |
+
} // end DATETIME
|
1398 |
+
} // end foreach( $prop as $theRdate )
|
1399 |
+
} // end while( FALSE !== ( $prop = $component->getProperty( 'rdate', FALSE, TRUE )))
|
1400 |
+
unset( $prop, $workStart, $format, $theRdate, $rdate, $rend );
|
1401 |
+
foreach( $recurridList as $rKey => $rVal ) { // check for recurrence-id, i.e. alter recur Ymd[His] and duration
|
1402 |
+
if( isset( $recurlist[$rKey] )) {
|
1403 |
+
unset( $recurlist[$rKey] );
|
1404 |
+
$recurlist[$rVal[0]->key] = ( FALSE !== $rVal[2] ) ? $rVal[2] : $compDuration;
|
1405 |
+
// echo "alter recurfrom {$rKey} to {$rVal[0]->key} ";if(FALSE!==$dur)echo " ({$dur->format( '%a days, %h-%i-%s' )})";echo "<br>\n"; // test ###
|
1406 |
+
}
|
1407 |
+
}
|
1408 |
+
ksort( $recurlist, SORT_STRING );
|
1409 |
+
// echo 'recurlist=' .implode(', ', array_keys( $recurlist )) ."<br>\n"; // test ###
|
1410 |
+
// echo 'recurridList=' .implode(', ', array_keys( $recurridList )) ."<br>\n"; // test ###
|
1411 |
+
/* *************************************************************
|
1412 |
+
output all remaining components in recurlist
|
1413 |
+
*********************************************************** */
|
1414 |
+
if( 0 < count( $recurlist )) {
|
1415 |
+
$component2 = $component->copy();
|
1416 |
+
$compUID = $component2->getProperty( 'UID' );
|
1417 |
+
$workStart = clone $fcnStart;
|
1418 |
+
$workStart->sub( $compDuration ? $compDuration : $intervalP1D );
|
1419 |
+
$YmdOld = null;
|
1420 |
+
foreach( $recurlist as $recurkey => $durvalue ) {
|
1421 |
+
if( $YmdOld == substr( $recurkey, 0, 8 )) // skip overlapping recur the same day, i.e. RDATE before RRULE
|
1422 |
+
continue;
|
1423 |
+
$YmdOld = substr( $recurkey, 0, 8 );
|
1424 |
+
$rstart = clone $compStart;
|
1425 |
+
$rstart->setDate((int) substr( $recurkey, 0, 4 ), (int) substr( $recurkey, 4, 2 ), (int) substr( $recurkey, 6, 2 ));
|
1426 |
+
$rstart->setTime((int) substr( $recurkey, 8, 2 ), (int) substr( $recurkey, 10, 2 ), (int) substr( $recurkey, 12, 2 ));
|
1427 |
+
// echo "recur start=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] )."<br>\n"; // test ###;
|
1428 |
+
/* add recurring components within valid dates to output array, only start date set */
|
1429 |
+
if( $flat ) {
|
1430 |
+
if( !isset( $result[$compUID] )) // only one comp
|
1431 |
+
$result[$compUID] = $component2->copy(); // copy to output
|
1432 |
+
}
|
1433 |
+
/* add recurring components within valid dates to output array, split for each day */
|
1434 |
+
elseif( $split ) {
|
1435 |
+
$rend = clone $rstart;
|
1436 |
+
if( FALSE !== $durvalue )
|
1437 |
+
$rend->add( $durvalue );
|
1438 |
+
if( $rend->format( iCalUtilityFunctions::$fmt['Ymd2'] ) > $fcnEnd->format( iCalUtilityFunctions::$fmt['Ymd2'] ))
|
1439 |
+
$rend = clone $fcnEnd;
|
1440 |
+
// echo "recur 1={$recurkey}, start=".$rstart->format( iCalUtilityFunctions::$fmt['YmdHis2e'] ).", end=".$rend->format( iCalUtilityFunctions::$fmt['YmdHis2e'] );if($durvalue) echo ", duration=".$durvalue->format( iCalUtilityFunctions::$fmt['durDHis'] );echo "<br>\n"; // test ###
|
1441 |
+
$xRecurrence += 1;
|
1442 |
+
$cnt = 0;
|
1443 |
+
$occurenceDays = 1 + (int) $rstart->diff( $rend )->format( '%a' ); // count the days (incl start day)
|
1444 |
+
while( $rstart->format( iCalUtilityFunctions::$fmt['Ymd2'] ) <= $rend->format( iCalUtilityFunctions::$fmt['Ymd2'] )) { // iterate.. .
|
1445 |
+
$cnt += 1;
|
1446 |
+
if( $rstart->format( iCalUtilityFunctions::$fmt['Ymd2'] ) < $fcnStart->format( iCalUtilityFunctions::$fmt['Ymd2'] )) { // date before dtstart
|
1447 |
+
// echo "recur 3, start=".$rstart->format( 'Y-m-d H:i:s' )." >= fcnStart=".$fcnStart->format( 'Y-m-d H:i:s' )."<br>\n"; // test ###
|
1448 |
+
$rstart->add( $intervalP1D );
|
1449 |
+
$rstart->setTime( 0, 0, 0 );
|
1450 |
+
continue;
|
1451 |
+
}
|
1452 |
+
elseif( 2 == $cnt )
|
1453 |
+
$rstart->setTime( 0, 0, 0 );
|
1454 |
+
$component2->setProperty( 'X-RECURRENCE', $xRecurrence );
|
1455 |
+
if( 1 < $occurenceDays )
|
1456 |
+
$component2->setProperty( 'X-OCCURENCE', sprintf( iCalUtilityFunctions::$fmt['dayOfDays'], $cnt, $occurenceDays ));
|
1457 |
+
else
|
1458 |
+
$component2->deleteProperty( 'X-OCCURENCE' );
|
1459 |
+
$component2->setProperty( 'X-CURRENT-DTSTART', $rstart->format( $compStart->dateFormat ));
|
1460 |
+
$propName = ( isset( $compEnd->SCbools[ 'dueExist'] )) ? 'X-CURRENT-DUE' : 'X-CURRENT-DTEND';
|
1461 |
+
if( FALSE !== $durvalue ) {
|
1462 |
+
if( $cnt < $occurenceDays )
|
1463 |
+
$rstart->setTime( 23, 59, 59 );
|
1464 |
+
else {
|
1465 |
+
$His = $rend->getTime(); // set end time
|
1466 |
+
$rstart->setTime( $His[0], $His[1], $His[2] );
|
1467 |
+
}
|
1468 |
+
$component2->setProperty( $propName, $rstart->format( $compEnd->dateFormat ));
|
1469 |
+
// echo "checking date, (day {$cnt} of {$occurenceDays}), _end_=".$rstart->format( 'Y-m-d H:i:s e' )."<br>"; // test ###;
|
1470 |
+
}
|
1471 |
+
else
|
1472 |
+
$component2->deleteProperty( $propName );
|
1473 |
+
$result[(int)$rstart->format( 'Y' )][(int)$rstart->format( 'm' )][(int)$rstart->format( 'd' )][$compUID] = $component2->copy(); // copy to output
|
1474 |
+
$rstart->add( $intervalP1D );
|
1475 |
+
} // end while( $rstart->format( 'Ymd' ) <= $rend->format( 'Ymd' ))
|
1476 |
+
unset( $rstart, $rend );
|
1477 |
+
} // end elseif( $split )
|
1478 |
+
elseif( $rstart->format( iCalUtilityFunctions::$fmt['Ymd2'] ) >= $fcnStart->format( iCalUtilityFunctions::$fmt['Ymd2'] )) {
|
1479 |
+
$xRecurrence += 1; // date within period //* flat=FALSE && split=FALSE => one comp every recur startdate *//
|
1480 |
+
$component2->setProperty( 'X-RECURRENCE', $xRecurrence );
|
1481 |
+
$component2->setProperty( 'X-CURRENT-DTSTART', $rstart->format( $compStart->dateFormat ));
|
1482 |
+
$propName = ( isset( $compEnd->SCbools[ 'dueExist'] )) ? 'X-CURRENT-DUE' : 'X-CURRENT-DTEND';
|
1483 |
+
if( FALSE !== $durvalue ) {
|
1484 |
+
$rstart->add( $durvalue );
|
1485 |
+
$component2->setProperty( $propName, $rstart->format( $compEnd->dateFormat ));
|
1486 |
+
}
|
1487 |
+
else
|
1488 |
+
$component2->deleteProperty( $propName );
|
1489 |
+
$result[(int)$rstart->format( 'Y' )][(int)$rstart->format( 'm' )][(int)$rstart->format( 'd' )][$compUID] = $component2->copy(); // copy to output
|
1490 |
+
} // end elseif( $rstart >= $fcnStart )
|
1491 |
+
unset( $rstart );
|
1492 |
+
} // end foreach( $recurlist as $recurkey => $durvalue )
|
1493 |
+
unset( $component2, $xRecurrence, $compUID, $workStart, $rstart );
|
1494 |
+
} // end if( 0 < count( $recurlist ))
|
1495 |
+
} // end if( TRUE === $any )
|
1496 |
+
unset( $component );
|
1497 |
+
} // end foreach ( $this->components as $cix => $component )
|
1498 |
+
unset( $recurrid, $recurridList, $fcnStart, $fcnEnd, $compStart, $compEnd, $exdatelist, $recurlist ); // clean up
|
1499 |
+
if( 0 >= count( $result ))
|
1500 |
+
return FALSE;
|
1501 |
+
elseif( !$flat ) {
|
1502 |
+
foreach( $result as $y => $yeararr ) {
|
1503 |
+
foreach( $yeararr as $m => $montharr ) {
|
1504 |
+
foreach( $montharr as $d => $dayarr ) {
|
1505 |
+
if( empty( $result[$y][$m][$d] ))
|
1506 |
+
unset( $result[$y][$m][$d] );
|
1507 |
+
else {
|
1508 |
+
$result[$y][$m][$d] = array_values( $dayarr ); // skip tricky UID-index
|
1509 |
+
if( 1 < count( $result[$y][$m][$d] )) {
|
1510 |
+
foreach( $result[$y][$m][$d] as & $c ) // sort
|
1511 |
+
iCalUtilityFunctions::_setSortArgs( $c );
|
1512 |
+
usort( $result[$y][$m][$d], array( 'iCalUtilityFunctions', '_cmpfcn' ));
|
1513 |
+
}
|
1514 |
+
}
|
1515 |
+
} // end foreach( $montharr as $d => $dayarr )
|
1516 |
+
if( empty( $result[$y][$m] ))
|
1517 |
+
unset( $result[$y][$m] );
|
1518 |
+
else
|
1519 |
+
ksort( $result[$y][$m] );
|
1520 |
+
} // end foreach( $yeararr as $m => $montharr )
|
1521 |
+
if( empty( $result[$y] ))
|
1522 |
+
unset( $result[$y] );
|
1523 |
+
else
|
1524 |
+
ksort( $result[$y] );
|
1525 |
+
}// end foreach( $result as $y => $yeararr )
|
1526 |
+
if( empty( $result ))
|
1527 |
+
unset( $result );
|
1528 |
+
else
|
1529 |
+
ksort( $result );
|
1530 |
+
} // end elseif( !$flat )
|
1531 |
+
if( 0 >= count( $result ))
|
1532 |
+
return FALSE;
|
1533 |
+
return $result;
|
1534 |
+
}
|
1535 |
+
/**
|
1536 |
+
* select components from calendar on based on specific property value(-s)
|
1537 |
+
*
|
1538 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1539 |
+
* @since 2.21.11 - 2015-03-21
|
1540 |
+
* @param array $selectOptions (string) key => (mixed) value, (key=propertyName)
|
1541 |
+
* @uses vcalendar::$components
|
1542 |
+
* @uses calendarComponent::$objName
|
1543 |
+
* @uses iCalUtilityFunctions::$vComps
|
1544 |
+
* @uses calendarComponent::getProperty()
|
1545 |
+
* @uses iCalUtilityFunctions::$otherProps
|
1546 |
+
* @uses calendarComponent::copy()
|
1547 |
+
* @uses iCalUtilityFunctions::$mProps1
|
1548 |
+
* @uses calendarComponent::_getProperties()
|
1549 |
+
* @return array
|
1550 |
+
*/
|
1551 |
+
function selectComponents2( $selectOptions ) {
|
1552 |
+
// $output = array();
|
1553 |
+
$selectOptions = array_change_key_case( $selectOptions, CASE_UPPER );
|
1554 |
+
foreach( $this->components as $cix => $component3 ) {
|
1555 |
+
if( !in_array( $component3->objName, iCalUtilityFunctions::$vComps ))
|
1556 |
+
continue;
|
1557 |
+
$uid = $component3->getProperty( 'UID' );
|
1558 |
+
foreach( $selectOptions as $propName => $pvalue ) {
|
1559 |
+
if( !in_array( $propName, iCalUtilityFunctions::$otherProps ))
|
1560 |
+
continue;
|
1561 |
+
if( !is_array( $pvalue ))
|
1562 |
+
$pvalue = array( $pvalue );
|
1563 |
+
if(( 'UID' == $propName ) && in_array( $uid, $pvalue )) {
|
1564 |
+
$output[$uid][] = $component3->copy();
|
1565 |
+
continue;
|
1566 |
+
}
|
1567 |
+
elseif( in_array( $propName, iCalUtilityFunctions::$mProps1 )) {
|
1568 |
+
$propValues = array();
|
1569 |
+
$component3->_getProperties( $propName, $propValues );
|
1570 |
+
$propValues = array_keys( $propValues );
|
1571 |
+
foreach( $pvalue as $theValue ) {
|
1572 |
+
if( in_array( $theValue, $propValues )) { // && !isset( $output[$uid] )) {
|
1573 |
+
$output[$uid][] = $component3->copy();
|
1574 |
+
break;
|
1575 |
+
}
|
1576 |
+
}
|
1577 |
+
continue;
|
1578 |
+
} // end elseif( // multiple occurrence?
|
1579 |
+
elseif( FALSE === ( $d = $component3->getProperty( $propName ))) // single occurrence
|
1580 |
+
continue;
|
1581 |
+
if( is_array( $d )) {
|
1582 |
+
foreach( $d as $part ) {
|
1583 |
+
if( in_array( $part, $pvalue ) && !isset( $output[$uid] ))
|
1584 |
+
$output[$uid][] = $component3->copy();
|
1585 |
+
}
|
1586 |
+
}
|
1587 |
+
elseif(( 'SUMMARY' == $propName ) && !isset( $output[$uid] )) {
|
1588 |
+
foreach( $pvalue as $pval ) {
|
1589 |
+
if( FALSE !== stripos( $d, $pval )) {
|
1590 |
+
$output[$uid][] = $component3->copy();
|
1591 |
+
break;
|
1592 |
+
}
|
1593 |
+
}
|
1594 |
+
}
|
1595 |
+
elseif( in_array( $d, $pvalue ) && !isset( $output[$uid] ))
|
1596 |
+
$output[$uid][] = $component3->copy();
|
1597 |
+
} // end foreach( $selectOptions as $propName => $pvalue ) {
|
1598 |
+
} // end foreach( $this->components as $cix => $component3 ) {
|
1599 |
+
if( !empty( $output )) {
|
1600 |
+
ksort( $output ); // uid order
|
1601 |
+
$output2 = array();
|
1602 |
+
foreach( $output as $uid => $components ) {
|
1603 |
+
foreach( $components as $component )
|
1604 |
+
$output2[] = $component;
|
1605 |
+
}
|
1606 |
+
$output = $output2;
|
1607 |
+
}
|
1608 |
+
return $output;
|
1609 |
+
}
|
1610 |
+
/**
|
1611 |
+
* replace calendar component in vcalendar
|
1612 |
+
*
|
1613 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1614 |
+
* @since 2.21.11 - 2015-03-21
|
1615 |
+
* @param object $component calendar component
|
1616 |
+
* @uses calendarComponent::$objName
|
1617 |
+
* @uses iCalUtilityFunctions::$vComps
|
1618 |
+
* @uses vcalendar::setComponent()
|
1619 |
+
* @uses calendarComponent::getProperty()
|
1620 |
+
* @return bool
|
1621 |
+
*/
|
1622 |
+
function replaceComponent( $component ) {
|
1623 |
+
if( in_array( $component->objName, iCalUtilityFunctions::$vComps ))
|
1624 |
+
return $this->setComponent( $component, $component->getProperty( 'UID' ));
|
1625 |
+
if(( 'vtimezone' != $component->objName ) || ( FALSE === ( $tzid = $component->getProperty( 'TZID' ))))
|
1626 |
+
return FALSE;
|
1627 |
+
foreach( $this->components as $cix => $comp ) {
|
1628 |
+
if( 'vtimezone' != $component->objName )
|
1629 |
+
continue;
|
1630 |
+
if( $tzid == $comp->getComponent( 'TZID' )) {
|
1631 |
+
unset( $component->propix, $component->compix );
|
1632 |
+
$this->components[$cix] = $component;
|
1633 |
+
return TRUE;
|
1634 |
+
}
|
1635 |
+
}
|
1636 |
+
return FALSE;
|
1637 |
+
}
|
1638 |
+
/**
|
1639 |
+
* add calendar component to calendar
|
1640 |
+
*
|
1641 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1642 |
+
* @since 2.21.11 - 2015-03-21
|
1643 |
+
* @param object $component calendar component
|
1644 |
+
* @param mixed $arg1 optional, ordno/component type/ component uid
|
1645 |
+
* @param mixed $arg2 optional, ordno if arg1 = component type
|
1646 |
+
* @uses calendarComponent::setConfig()
|
1647 |
+
* @uses vcalendar::getConfig()
|
1648 |
+
* @uses calendarComponent::$objName
|
1649 |
+
* @uses calendarComponent::getProperty()
|
1650 |
+
* @uses vcalendar::$components
|
1651 |
+
* @uses iCalUtilityFunctions::$mComps
|
1652 |
+
* @uses calendarComponent::copy()
|
1653 |
+
* @return bool
|
1654 |
+
*/
|
1655 |
+
function setComponent( $component, $arg1=FALSE, $arg2=FALSE ) {
|
1656 |
+
$component->setConfig( $this->getConfig(), FALSE, TRUE );
|
1657 |
+
if( !in_array( $component->objName, array( 'valarm', 'vtimezone' ))) {
|
1658 |
+
/* make sure dtstamp and uid is set */
|
1659 |
+
$dummy1 = $component->getProperty( 'dtstamp' );
|
1660 |
+
$dummy2 = $component->getProperty( 'uid' );
|
1661 |
+
}
|
1662 |
+
unset( $component->propix, $component->compix );
|
1663 |
+
if( !$arg1 ) { // plain insert, last in chain
|
1664 |
+
$this->components[] = $component->copy();
|
1665 |
+
return TRUE;
|
1666 |
+
}
|
1667 |
+
$argType = $index = null;
|
1668 |
+
if ( ctype_digit( (string) $arg1 )) { // index insert/replace
|
1669 |
+
$argType = 'INDEX';
|
1670 |
+
$index = (int) $arg1 - 1;
|
1671 |
+
}
|
1672 |
+
elseif( in_array( strtolower( $arg1 ), iCalUtilityFunctions::$mComps )) {
|
1673 |
+
$argType = strtolower( $arg1 );
|
1674 |
+
$index = ( ctype_digit( (string) $arg2 )) ? ((int) $arg2) - 1 : 0;
|
1675 |
+
}
|
1676 |
+
// else if arg1 is set, arg1 must be an UID
|
1677 |
+
$cix1sC = 0;
|
1678 |
+
foreach ( $this->components as $cix => $component2) {
|
1679 |
+
if( empty( $component2 )) continue;
|
1680 |
+
if(( 'INDEX' == $argType ) && ( $index == $cix )) { // index insert/replace
|
1681 |
+
$this->components[$cix] = $component->copy();
|
1682 |
+
return TRUE;
|
1683 |
+
}
|
1684 |
+
elseif( $argType == $component2->objName ) { // component Type index insert/replace
|
1685 |
+
if( $index == $cix1sC ) {
|
1686 |
+
$this->components[$cix] = $component->copy();
|
1687 |
+
return TRUE;
|
1688 |
+
}
|
1689 |
+
$cix1sC++;
|
1690 |
+
}
|
1691 |
+
elseif( !$argType && ( $arg1 == $component2->getProperty( 'uid' ))) { // UID insert/replace
|
1692 |
+
$this->components[$cix] = $component->copy();
|
1693 |
+
return TRUE;
|
1694 |
+
}
|
1695 |
+
}
|
1696 |
+
/* arg1=index and not found.. . insert at index .. .*/
|
1697 |
+
if( 'INDEX' == $argType ) {
|
1698 |
+
$this->components[$index] = $component->copy();
|
1699 |
+
ksort( $this->components, SORT_NUMERIC );
|
1700 |
+
}
|
1701 |
+
else /* not found.. . insert last in chain anyway .. .*/
|
1702 |
+
$this->components[] = $component->copy();
|
1703 |
+
return TRUE;
|
1704 |
+
}
|
1705 |
+
/**
|
1706 |
+
* sort iCal compoments
|
1707 |
+
*
|
1708 |
+
* ascending sort on properties (if exist) x-current-dtstart, dtstart,
|
1709 |
+
* x-current-dtend, dtend, x-current-due, due, duration, created, dtstamp, uid if called without arguments,
|
1710 |
+
* otherwise sorting on specific (argument) property values
|
1711 |
+
*
|
1712 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1713 |
+
* @since 2.21.11 - 2015-03-21
|
1714 |
+
* @param string $sortArg
|
1715 |
+
* @uses vcalendar::$components
|
1716 |
+
* @uses iCalUtilityFunctions::$otherProps
|
1717 |
+
* @uses iCalUtilityFunctions::_setSortArgs()
|
1718 |
+
* @uses iCalUtilityFunctions::_cmpfcn()
|
1719 |
+
* @return void
|
1720 |
+
*/
|
1721 |
+
function sort( $sortArg=FALSE ) {
|
1722 |
+
if( ! is_array( $this->components ) || ( 2 > count( $this->components )))
|
1723 |
+
return;
|
1724 |
+
if( $sortArg ) {
|
1725 |
+
$sortArg = strtoupper( $sortArg );
|
1726 |
+
if( ! in_array( $sortArg, iCalUtilityFunctions::$otherProps ) && ( 'DTSTAMP' != $sortArg ))
|
1727 |
+
$sortArg = FALSE;
|
1728 |
+
}
|
1729 |
+
foreach( $this->components as & $c )
|
1730 |
+
iCalUtilityFunctions::_setSortArgs( $c, $sortArg );
|
1731 |
+
usort( $this->components, array( 'iCalUtilityFunctions', '_cmpfcn' ));
|
1732 |
+
}
|
1733 |
+
/**
|
1734 |
+
* parse iCal text/file into vcalendar, components, properties and parameters
|
1735 |
+
*
|
1736 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1737 |
+
* @since 2.21.12 - 2014-03-10
|
1738 |
+
* @param mixed $unparsedtext strict rfc2445 formatted, single property string or array of property strings
|
1739 |
+
* @param resource $context PHP resource context
|
1740 |
+
* @uses iCalUtilityFunctions::convEolChar()
|
1741 |
+
* @uses vcalendar::getConfig()
|
1742 |
+
* @uses vcalendar::$components
|
1743 |
+
* @uses calendarComponent::copy()
|
1744 |
+
* @uses vevent::construct()
|
1745 |
+
* @uses vfreebusy::construct()
|
1746 |
+
* @uses vjournal::construct()
|
1747 |
+
* @uses vtodo::construct()
|
1748 |
+
* @uses vtimezone::construct()
|
1749 |
+
* @uses vcalendar::$unparsed
|
1750 |
+
* @uses iCalUtilityFunctions::_splitContent()
|
1751 |
+
* @uses iCalUtilityFunctions::_strunrep()
|
1752 |
+
* @uses vcalendar::setProperty()
|
1753 |
+
* @uses calendarComponent::$unparsed
|
1754 |
+
* @uses calendarComponent::parse()
|
1755 |
+
* @return bool FALSE if error occurs during parsing
|
1756 |
+
*/
|
1757 |
+
function parse( $unparsedtext=FALSE, $context=null ) {
|
1758 |
+
$nl = $this->getConfig( 'nl' );
|
1759 |
+
if(( FALSE === $unparsedtext ) || empty( $unparsedtext )) {
|
1760 |
+
/* directory+filename is set previously via setConfig url or directory+filename */
|
1761 |
+
if( FALSE === ( $file = $this->getConfig( 'url' ))) {
|
1762 |
+
if( FALSE === ( $file = $this->getConfig( 'dirfile' )))
|
1763 |
+
return FALSE; /* err 1 */
|
1764 |
+
if( ! is_file( $file ))
|
1765 |
+
return FALSE; /* err 2 */
|
1766 |
+
if( ! is_readable( $file ))
|
1767 |
+
return FALSE; /* err 3 */
|
1768 |
+
}
|
1769 |
+
/* READ FILE */
|
1770 |
+
if( ! empty( $context ) && filter_var( $file, FILTER_VALIDATE_URL ) &&
|
1771 |
+
( FALSE === ( $rows = file_get_contents( $file, FALSE, $context ))))
|
1772 |
+
return FALSE; /* err 6 */
|
1773 |
+
elseif( FALSE === ( $rows = file_get_contents( $file )))
|
1774 |
+
return FALSE; /* err 5 */
|
1775 |
+
} // end if(( FALSE === $unparsedtext ) || empty( $unparsedtext ))
|
1776 |
+
elseif( is_array( $unparsedtext ))
|
1777 |
+
$rows = implode( '\n'.$nl, $unparsedtext );
|
1778 |
+
else
|
1779 |
+
$rows = & $unparsedtext;
|
1780 |
+
/* fix line folding */
|
1781 |
+
$rows = iCalUtilityFunctions::convEolChar( $rows, $nl );
|
1782 |
+
/* skip leading (empty/invalid) lines (and remove leading BOM chars etc) */
|
1783 |
+
foreach( $rows as $lix => $line ) {
|
1784 |
+
if( FALSE !== stripos( $line, 'BEGIN:VCALENDAR' )) {
|
1785 |
+
$rows[$lix] = 'BEGIN:VCALENDAR';
|
1786 |
+
break;
|
1787 |
+
}
|
1788 |
+
unset( $rows[$lix] );
|
1789 |
+
}
|
1790 |
+
$rcnt = count( $rows );
|
1791 |
+
if( 3 > $rcnt ) /* err 10 */
|
1792 |
+
return FALSE;
|
1793 |
+
/* skip trailing empty lines and ensure an end row */
|
1794 |
+
$lix = array_keys( $rows );
|
1795 |
+
$lix = end( $lix );
|
1796 |
+
while( 3 < $lix ) {
|
1797 |
+
$tst = trim( $rows[$lix] );
|
1798 |
+
if(( '\n' == $tst ) || empty( $tst )) {
|
1799 |
+
unset( $rows[$lix] );
|
1800 |
+
$lix--;
|
1801 |
+
continue;
|
1802 |
+
}
|
1803 |
+
if( FALSE === stripos( $rows[$lix], 'END:VCALENDAR' ))
|
1804 |
+
$rows[] = 'END:VCALENDAR';
|
1805 |
+
else
|
1806 |
+
$rows[$lix] = 'END:VCALENDAR';
|
1807 |
+
break;
|
1808 |
+
}
|
1809 |
+
$comp = & $this;
|
1810 |
+
$calsync = $compsync = 0;
|
1811 |
+
/* identify components and update unparsed data within component */
|
1812 |
+
$config = $this->getConfig();
|
1813 |
+
$endtxt = array( 'END:VE', 'END:VF', 'END:VJ', 'END:VT' );
|
1814 |
+
foreach( $rows as $lix => $line ) {
|
1815 |
+
if( 'BEGIN:VCALENDAR' == strtoupper( substr( $line, 0, 15 ))) {
|
1816 |
+
$calsync++;
|
1817 |
+
continue;
|
1818 |
+
}
|
1819 |
+
elseif( 'END:VCALENDAR' == strtoupper( substr( $line, 0, 13 ))) {
|
1820 |
+
if( 0 < $compsync )
|
1821 |
+
$this->components[] = $comp->copy();
|
1822 |
+
$compsync--;
|
1823 |
+
$calsync--;
|
1824 |
+
break;
|
1825 |
+
}
|
1826 |
+
elseif( 1 != $calsync )
|
1827 |
+
return FALSE; /* err 20 */
|
1828 |
+
elseif( in_array( strtoupper( substr( $line, 0, 6 )), $endtxt )) {
|
1829 |
+
$this->components[] = $comp->copy();
|
1830 |
+
$compsync--;
|
1831 |
+
continue;
|
1832 |
+
}
|
1833 |
+
if( 'BEGIN:VEVENT' == strtoupper( substr( $line, 0, 12 ))) {
|
1834 |
+
$comp = new vevent( $config );
|
1835 |
+
$compsync++;
|
1836 |
+
}
|
1837 |
+
elseif( 'BEGIN:VFREEBUSY' == strtoupper( substr( $line, 0, 15 ))) {
|
1838 |
+
$comp = new vfreebusy( $config );
|
1839 |
+
$compsync++;
|
1840 |
+
}
|
1841 |
+
elseif( 'BEGIN:VJOURNAL' == strtoupper( substr( $line, 0, 14 ))) {
|
1842 |
+
$comp = new vjournal( $config );
|
1843 |
+
$compsync++;
|
1844 |
+
}
|
1845 |
+
elseif( 'BEGIN:VTODO' == strtoupper( substr( $line, 0, 11 ))) {
|
1846 |
+
$comp = new vtodo( $config );
|
1847 |
+
$compsync++;
|
1848 |
+
}
|
1849 |
+
elseif( 'BEGIN:VTIMEZONE' == strtoupper( substr( $line, 0, 15 ))) {
|
1850 |
+
$comp = new vtimezone( $config );
|
1851 |
+
$compsync++;
|
1852 |
+
}
|
1853 |
+
else { /* update component with unparsed data */
|
1854 |
+
$comp->unparsed[] = $line;
|
1855 |
+
}
|
1856 |
+
} // end foreach( $rows as $line )
|
1857 |
+
unset( $config, $endtxt );
|
1858 |
+
/* parse data for calendar (this) object */
|
1859 |
+
if( isset( $this->unparsed ) && is_array( $this->unparsed ) && ( 0 < count( $this->unparsed ))) {
|
1860 |
+
/* concatenate property values spread over several lines */
|
1861 |
+
$propnames = array( 'calscale','method','prodid','version','x-' );
|
1862 |
+
$proprows = array();
|
1863 |
+
for( $i = 0; $i < count( $this->unparsed ); $i++ ) { // concatenate lines
|
1864 |
+
$line = rtrim( $this->unparsed[$i], $nl );
|
1865 |
+
while( isset( $this->unparsed[$i+1] ) && !empty( $this->unparsed[$i+1] ) && ( ' ' == $this->unparsed[$i+1]{0} ))
|
1866 |
+
$line .= rtrim( substr( $this->unparsed[++$i], 1 ), $nl );
|
1867 |
+
$proprows[] = $line;
|
1868 |
+
}
|
1869 |
+
foreach( $proprows as $line ) {
|
1870 |
+
if( '\n' == substr( $line, -2 ))
|
1871 |
+
$line = substr( $line, 0, -2 );
|
1872 |
+
/* get property name */
|
1873 |
+
$propname = '';
|
1874 |
+
$cix = 0;
|
1875 |
+
while( FALSE !== ( $char = substr( $line, $cix, 1 ))) {
|
1876 |
+
if( in_array( $char, array( ':', ';' )))
|
1877 |
+
break;
|
1878 |
+
else
|
1879 |
+
$propname .= $char;
|
1880 |
+
$cix++;
|
1881 |
+
}
|
1882 |
+
/* skip non standard property names */
|
1883 |
+
if(( 'x-' != strtolower( substr( $propname, 0, 2 ))) && !in_array( strtolower( $propname ), $propnames ))
|
1884 |
+
continue;
|
1885 |
+
/* ignore version/prodid properties */
|
1886 |
+
if( in_array( strtolower( $propname ), array( 'version', 'prodid' )))
|
1887 |
+
continue;
|
1888 |
+
/* rest of the line is opt.params and value */
|
1889 |
+
$line = substr( $line, $cix);
|
1890 |
+
/* separate attributes from value */
|
1891 |
+
iCalUtilityFunctions::_splitContent( $line, $propAttr );
|
1892 |
+
/* update Property */
|
1893 |
+
if( FALSE !== strpos( $line, ',' )) {
|
1894 |
+
$content = array( 0 => '' );
|
1895 |
+
$cix = $lix = 0;
|
1896 |
+
while( FALSE !== substr( $line, $lix, 1 )) {
|
1897 |
+
if(( 0 < $lix ) && ( ',' == $line[$lix] ) && ( "\\" != $line[( $lix - 1 )])) {
|
1898 |
+
$cix++;
|
1899 |
+
$content[$cix] = '';
|
1900 |
+
}
|
1901 |
+
else
|
1902 |
+
$content[$cix] .= $line[$lix];
|
1903 |
+
$lix++;
|
1904 |
+
}
|
1905 |
+
if( 1 < count( $content )) {
|
1906 |
+
foreach( $content as $cix => $contentPart )
|
1907 |
+
$content[$cix] = iCalUtilityFunctions::_strunrep( $contentPart );
|
1908 |
+
$this->setProperty( $propname, $content, $propAttr );
|
1909 |
+
continue;
|
1910 |
+
}
|
1911 |
+
else
|
1912 |
+
$line = reset( $content );
|
1913 |
+
$line = iCalUtilityFunctions::_strunrep( $line );
|
1914 |
+
}
|
1915 |
+
$this->setProperty( $propname, rtrim( $line, "\x00..\x1F" ), $propAttr );
|
1916 |
+
} // end - foreach( $this->unparsed.. .
|
1917 |
+
} // end - if( is_array( $this->unparsed.. .
|
1918 |
+
unset( $unparsedtext, $rows, $this->unparsed, $proprows );
|
1919 |
+
/* parse Components */
|
1920 |
+
if( is_array( $this->components ) && ( 0 < count( $this->components ))) {
|
1921 |
+
$ckeys = array_keys( $this->components );
|
1922 |
+
foreach( $ckeys as $ckey ) {
|
1923 |
+
if( !empty( $this->components[$ckey] ) && !empty( $this->components[$ckey]->unparsed )) {
|
1924 |
+
$this->components[$ckey]->parse();
|
1925 |
+
}
|
1926 |
+
}
|
1927 |
+
}
|
1928 |
+
else
|
1929 |
+
return FALSE; /* err 91 or something.. . */
|
1930 |
+
return TRUE;
|
1931 |
+
}
|
1932 |
+
/*********************************************************************************/
|
1933 |
+
/**
|
1934 |
+
* creates formatted output for calendar object instance
|
1935 |
+
*
|
1936 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
1937 |
+
* @since 2.21.07 - 2015-03-31
|
1938 |
+
* @uses vcalendar::$format
|
1939 |
+
* @uses vcalendar::$nl
|
1940 |
+
* @uses vcalendar::createVersion()
|
1941 |
+
* @uses vcalendar::createProdid()
|
1942 |
+
* @uses vcalendar::createCalscale()
|
1943 |
+
* @uses vcalendar::createMethod()
|
1944 |
+
* @uses vcalendar::createXprop()
|
1945 |
+
* @uses vcalendar::$components
|
1946 |
+
* @uses calendarComponent::setConfig()
|
1947 |
+
* @uses vcalendar::getConfig()
|
1948 |
+
* @uses calendarComponent::createComponent()
|
1949 |
+
* @uses vcalendar::$xcaldecl
|
1950 |
+
* @return string
|
1951 |
+
*/
|
1952 |
+
function createCalendar() {
|
1953 |
+
parent::_createFormat();
|
1954 |
+
$calendarInit = $calendarxCaldecl = $calendarStart = $calendar = '';
|
1955 |
+
switch( $this->format ) {
|
1956 |
+
case 'xcal':
|
1957 |
+
$calendarInit = '<?xml version="1.0" encoding="UTF-8"?>'.$this->nl.
|
1958 |
+
'<!DOCTYPE vcalendar PUBLIC "-//IETF//DTD XCAL/iCalendar XML//EN"'.$this->nl.
|
1959 |
+
'"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-01.txt"';
|
1960 |
+
$calendarStart = '>'.$this->nl.'<vcalendar';
|
1961 |
+
break;
|
1962 |
+
default:
|
1963 |
+
$calendarStart = 'BEGIN:VCALENDAR'.$this->nl;
|
1964 |
+
break;
|
1965 |
+
}
|
1966 |
+
$calendarStart .= $this->createVersion();
|
1967 |
+
$calendarStart .= $this->createProdid();
|
1968 |
+
$calendarStart .= $this->createCalscale();
|
1969 |
+
$calendarStart .= $this->createMethod();
|
1970 |
+
if( 'xcal' == $this->format )
|
1971 |
+
$calendarStart .= '>'.$this->nl;
|
1972 |
+
$calendar .= $this->createXprop();
|
1973 |
+
foreach( $this->components as $component ) {
|
1974 |
+
if( empty( $component )) continue;
|
1975 |
+
$component->setConfig( $this->getConfig(), FALSE, TRUE );
|
1976 |
+
$calendar .= $component->createComponent( $this->xcaldecl );
|
1977 |
+
}
|
1978 |
+
if(( 'xcal' == $this->format ) && ( 0 < count( $this->xcaldecl ))) { // xCal only
|
1979 |
+
$calendarInit .= ' [';
|
1980 |
+
$old_xcaldecl = array();
|
1981 |
+
foreach( $this->xcaldecl as $declix => $declPart ) {
|
1982 |
+
if(( 0 < count( $old_xcaldecl)) &&
|
1983 |
+
isset( $declPart['uri'] ) && isset( $declPart['external'] ) &&
|
1984 |
+
isset( $old_xcaldecl['uri'] ) && isset( $old_xcaldecl['external'] ) &&
|
1985 |
+
( in_array( $declPart['uri'], $old_xcaldecl['uri'] )) &&
|
1986 |
+
( in_array( $declPart['external'], $old_xcaldecl['external'] )))
|
1987 |
+
continue; // no duplicate uri and ext. references
|
1988 |
+
if(( 0 < count( $old_xcaldecl)) &&
|
1989 |
+
!isset( $declPart['uri'] ) && !isset( $declPart['uri'] ) &&
|
1990 |
+
isset( $declPart['ref'] ) && isset( $old_xcaldecl['ref'] ) &&
|
1991 |
+
( in_array( $declPart['ref'], $old_xcaldecl['ref'] )))
|
1992 |
+
continue; // no duplicate element declarations
|
1993 |
+
$calendarxCaldecl .= $this->nl.'<!';
|
1994 |
+
foreach( $declPart as $declKey => $declValue ) {
|
1995 |
+
switch( $declKey ) { // index
|
1996 |
+
case 'xmldecl': // no 1
|
1997 |
+
$calendarxCaldecl .= $declValue.' ';
|
1998 |
+
break;
|
1999 |
+
case 'uri': // no 2
|
2000 |
+
$calendarxCaldecl .= $declValue.' ';
|
2001 |
+
$old_xcaldecl['uri'][] = $declValue;
|
2002 |
+
break;
|
2003 |
+
case 'ref': // no 3
|
2004 |
+
$calendarxCaldecl .= $declValue.' ';
|
2005 |
+
$old_xcaldecl['ref'][] = $declValue;
|
2006 |
+
break;
|
2007 |
+
case 'external': // no 4
|
2008 |
+
$calendarxCaldecl .= '"'.$declValue.'" ';
|
2009 |
+
$old_xcaldecl['external'][] = $declValue;
|
2010 |
+
break;
|
2011 |
+
case 'type': // no 5
|
2012 |
+
$calendarxCaldecl .= $declValue.' ';
|
2013 |
+
break;
|
2014 |
+
case 'type2': // no 6
|
2015 |
+
$calendarxCaldecl .= $declValue;
|
2016 |
+
break;
|
2017 |
+
}
|
2018 |
+
}
|
2019 |
+
$calendarxCaldecl .= '>';
|
2020 |
+
}
|
2021 |
+
$calendarxCaldecl .= $this->nl.']';
|
2022 |
+
} // end if(( 'xcal'...
|
2023 |
+
switch( $this->format ) {
|
2024 |
+
case 'xcal':
|
2025 |
+
$calendar .= '</vcalendar>'.$this->nl;
|
2026 |
+
break;
|
2027 |
+
default:
|
2028 |
+
$calendar .= 'END:VCALENDAR'.$this->nl;
|
2029 |
+
break;
|
2030 |
+
}
|
2031 |
+
return $calendarInit.$calendarxCaldecl.$calendarStart.$calendar;
|
2032 |
+
}
|
2033 |
+
/**
|
2034 |
+
* a HTTP redirect header is sent with created, updated and/or parsed calendar
|
2035 |
+
*
|
2036 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2037 |
+
* @since 2.21.5 - 2015-03-29
|
2038 |
+
* @param bool $utf8Encode
|
2039 |
+
* @param bool $gzip
|
2040 |
+
* @param bool $cdType TRUE : Content-Disposition: attachment... (default), FALSE : ...inline...
|
2041 |
+
* @uses vcalendar::getConfig()
|
2042 |
+
* @uses vcalendar::createCalendar()
|
2043 |
+
* @uses vcalendar::$headers
|
2044 |
+
* @uses vcalendar::$format
|
2045 |
+
* @return bool TRUE on success, FALSE on error
|
2046 |
+
*/
|
2047 |
+
function returnCalendar( $utf8Encode=FALSE, $gzip=FALSE, $cdType=TRUE ) {
|
2048 |
+
$filename = $this->getConfig( 'filename' );
|
2049 |
+
$output = $this->createCalendar();
|
2050 |
+
if( $utf8Encode )
|
2051 |
+
$output = utf8_encode( $output );
|
2052 |
+
$fsize = null;
|
2053 |
+
if( $gzip ) {
|
2054 |
+
$output = gzencode( $output, 9 );
|
2055 |
+
$fsize = strlen( $output );
|
2056 |
+
header( self::$headers[0] );
|
2057 |
+
header( self::$headers[1] );
|
2058 |
+
}
|
2059 |
+
// else {
|
2060 |
+
// if( FALSE !== ( $temp = tempnam( sys_get_temp_dir(), 'iCr' ))) {
|
2061 |
+
// if( FALSE !== file_put_contents( $temp, $output ))
|
2062 |
+
// $fsize = @filesize( $temp );
|
2063 |
+
// unlink( $temp );
|
2064 |
+
// }
|
2065 |
+
// }
|
2066 |
+
if( ! empty( $fsize ))
|
2067 |
+
header( sprintf( self::$headers[2], $fsize ));
|
2068 |
+
if( 'xcal' == $this->format )
|
2069 |
+
header( self::$headers[3] );
|
2070 |
+
else
|
2071 |
+
header( self::$headers[4] );
|
2072 |
+
$cdType = ( $cdType ) ? 5 : 6;
|
2073 |
+
header( sprintf( self::$headers[$cdType], $filename ));
|
2074 |
+
header( self::$headers[7] );
|
2075 |
+
echo trim($output);
|
2076 |
+
return TRUE;
|
2077 |
+
}
|
2078 |
+
/**
|
2079 |
+
* save content in a file
|
2080 |
+
*
|
2081 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2082 |
+
* @since 2.21.5 - 2015-03-29
|
2083 |
+
* @uses vcalendar::createComponent()
|
2084 |
+
* @uses vcalendar::getConfig()
|
2085 |
+
* @return bool TRUE on success, FALSE on error
|
2086 |
+
*/
|
2087 |
+
function saveCalendar() {
|
2088 |
+
$output = $this->createCalendar();
|
2089 |
+
if( FALSE === ( $dirfile = $this->getConfig( 'url' )))
|
2090 |
+
$dirfile = $this->getConfig( 'dirfile' );
|
2091 |
+
return ( FALSE === file_put_contents( $dirfile, $output, LOCK_EX )) ? FALSE : TRUE;
|
2092 |
+
}
|
2093 |
+
/**
|
2094 |
+
* if recent version of calendar file exists (default one hour), an HTTP redirect header is sent
|
2095 |
+
* else FALSE is returned
|
2096 |
+
*
|
2097 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
2098 |
+
* @since 2.21.5 - 2015-03-29
|
2099 |
+
* @param int $timeout default 3600 sec
|
2100 |
+
* @param bool $cdType TRUE : Content-Disposition: attachment... (default), FALSE : ...inline...
|
2101 |
+
* @uses vcalendar::getConfig()
|
2102 |
+
* @uses vcalendar::$headers
|
2103 |
+
* @uses vcalendar::$format
|
2104 |
+
* @return bool TRUE on success, FALSE on error
|
2105 |
+
*/
|
2106 |
+
function useCachedCalendar( $timeout=3600, $cdType=TRUE ) {
|
2107 |
+
if( FALSE === ( $dirfile = $this->getConfig( 'url' )))
|
2108 |
+
$dirfile = $this->getConfig( 'dirfile' );
|
2109 |
+
if( ! is_file( $dirfile ) || ! is_readable( $dirfile ))
|
2110 |
+
return FALSE;
|
2111 |
+
if( time() - filemtime( $dirfile ) > $timeout )
|
2112 |
+
return FALSE;
|
2113 |
+
clearstatcache();
|
2114 |
+
$dirfile = $this->getConfig( 'dirfile' );
|
2115 |
+
$fsize = @filesize( $dirfile );
|
2116 |
+
$filename = $this->getConfig( 'filename' );
|
2117 |
+
if( 'xcal' == $this->format )
|
2118 |
+
header( self::$headers[3] );
|
2119 |
+
else
|
2120 |
+
header( self::$headers[4] );
|
2121 |
+
if( ! empty( $fsize ))
|
2122 |
+
header( sprintf( self::$headers[2], $fsize ));
|
2123 |
+
$cdType = ( $cdType ) ? 5 : 6;
|
2124 |
+
header( sprintf( self::$headers[$cdType], $filename ));
|
2125 |
+
header( self::$headers[7] );
|
2126 |
+
if( FALSE === ( $fp = @fopen( $dirfile, 'r' )))
|
2127 |
+
return FALSE;
|
2128 |
+
fpassthru( $fp );
|
2129 |
+
fclose( $fp );
|
2130 |
+
return TRUE;
|
2131 |
+
}
|
2132 |
+
}
|
includes/libs/iCal/lib/vevent.class.php
ADDED
@@ -0,0 +1,269 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* class for calendar component VEVENT
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.5.1 - 2008-10-12
|
34 |
+
*/
|
35 |
+
class vevent extends calendarComponent {
|
36 |
+
/**
|
37 |
+
* @var array $attach component property value
|
38 |
+
* @var array $attendee component property value
|
39 |
+
* @var array $categories component property value
|
40 |
+
* @var array $comment component property value
|
41 |
+
* @var array $contact component property value
|
42 |
+
* @var array $class component property value
|
43 |
+
* @var array $created component property value
|
44 |
+
* @var array $description component property value
|
45 |
+
* @var array $dtend component property value
|
46 |
+
* @var array $dtstart component property value
|
47 |
+
* @var array $duration component property value
|
48 |
+
* @var array $exdate component property value
|
49 |
+
* @var array $exrule component property value
|
50 |
+
* @var array $geo component property value
|
51 |
+
* @var array $lastmodified component property value
|
52 |
+
* @var array $location component property value
|
53 |
+
* @var array $organizer component property value
|
54 |
+
* @var array $priority component property value
|
55 |
+
* @var array $rdate component property value
|
56 |
+
* @var array $recurrenceid component property value
|
57 |
+
* @var array $relatedto component property value
|
58 |
+
* @var array $requeststatus component property value
|
59 |
+
* @var array $resources component property value
|
60 |
+
* @var array $rrule component property value
|
61 |
+
* @var array $sequence component property value
|
62 |
+
* @var array $status component property value
|
63 |
+
* @var array $summary component property value
|
64 |
+
* @var array $transp component property value
|
65 |
+
* @var array $url component property value
|
66 |
+
* @access protected
|
67 |
+
*/
|
68 |
+
protected $attach;
|
69 |
+
protected $attendee;
|
70 |
+
protected $categories;
|
71 |
+
protected $comment;
|
72 |
+
protected $contact;
|
73 |
+
protected $class;
|
74 |
+
protected $created;
|
75 |
+
protected $description;
|
76 |
+
protected $dtend;
|
77 |
+
protected $dtstart;
|
78 |
+
protected $duration;
|
79 |
+
protected $exdate;
|
80 |
+
protected $exrule;
|
81 |
+
protected $geo;
|
82 |
+
protected $lastmodified;
|
83 |
+
protected $location;
|
84 |
+
protected $organizer;
|
85 |
+
protected $priority;
|
86 |
+
protected $rdate;
|
87 |
+
protected $recurrenceid;
|
88 |
+
protected $relatedto;
|
89 |
+
protected $requeststatus;
|
90 |
+
protected $resources;
|
91 |
+
protected $rrule;
|
92 |
+
protected $sequence;
|
93 |
+
protected $status;
|
94 |
+
protected $summary;
|
95 |
+
protected $transp;
|
96 |
+
protected $url;
|
97 |
+
/**
|
98 |
+
* constructor for calendar component VEVENT object
|
99 |
+
*
|
100 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
101 |
+
* @since 2.8.2 - 2011-05-01
|
102 |
+
* @param array $config
|
103 |
+
* @uses vevent::calendarComponent()
|
104 |
+
* @uses vevent::$attach
|
105 |
+
* @uses vevent::$attendee
|
106 |
+
* @uses vevent::$categories
|
107 |
+
* @uses vevent::$class
|
108 |
+
* @uses vevent::$comment
|
109 |
+
* @uses vevent::$contact
|
110 |
+
* @uses vevent::$created
|
111 |
+
* @uses vevent::$description
|
112 |
+
* @uses vevent::$dtstart
|
113 |
+
* @uses vevent::$dtend
|
114 |
+
* @uses vevent::$duration
|
115 |
+
* @uses vevent::$exdate
|
116 |
+
* @uses vevent::$exrule
|
117 |
+
* @uses vevent::$geo
|
118 |
+
* @uses vevent::$lastmodified
|
119 |
+
* @uses vevent::$location
|
120 |
+
* @uses vevent::$organizer
|
121 |
+
* @uses vevent::$priority
|
122 |
+
* @uses vevent::$rdate
|
123 |
+
* @uses vevent::$recurrenceid
|
124 |
+
* @uses vevent::$relatedto
|
125 |
+
* @uses vevent::$requeststatus
|
126 |
+
* @uses vevent::$resources
|
127 |
+
* @uses vevent::$rrule
|
128 |
+
* @uses vevent::$sequence
|
129 |
+
* @uses vevent::$status
|
130 |
+
* @uses vevent::$summary
|
131 |
+
* @uses vevent::$transp
|
132 |
+
* @uses vevent::$url
|
133 |
+
* @uses vevent::$xprop
|
134 |
+
* @uses vevent::$components
|
135 |
+
* @uses calendarComponent::setConfig()
|
136 |
+
*/
|
137 |
+
function __construct( $config = array()) {
|
138 |
+
$this->component();
|
139 |
+
$this->attach = '';
|
140 |
+
$this->attendee = '';
|
141 |
+
$this->categories = '';
|
142 |
+
$this->class = '';
|
143 |
+
$this->comment = '';
|
144 |
+
$this->contact = '';
|
145 |
+
$this->created = '';
|
146 |
+
$this->description = '';
|
147 |
+
$this->dtstart = '';
|
148 |
+
$this->dtend = '';
|
149 |
+
$this->duration = '';
|
150 |
+
$this->exdate = '';
|
151 |
+
$this->exrule = '';
|
152 |
+
$this->geo = '';
|
153 |
+
$this->lastmodified = '';
|
154 |
+
$this->location = '';
|
155 |
+
$this->organizer = '';
|
156 |
+
$this->priority = '';
|
157 |
+
$this->rdate = '';
|
158 |
+
$this->recurrenceid = '';
|
159 |
+
$this->relatedto = '';
|
160 |
+
$this->requeststatus = '';
|
161 |
+
$this->resources = '';
|
162 |
+
$this->rrule = '';
|
163 |
+
$this->sequence = '';
|
164 |
+
$this->status = '';
|
165 |
+
$this->summary = '';
|
166 |
+
$this->transp = '';
|
167 |
+
$this->url = '';
|
168 |
+
$this->xprop = '';
|
169 |
+
$this->components = array();
|
170 |
+
if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
|
171 |
+
$config['language'] = ICAL_LANG;
|
172 |
+
if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
|
173 |
+
if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
|
174 |
+
if( !isset( $config['format'] )) $config['format'] = 'iCal';
|
175 |
+
if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
|
176 |
+
$this->setConfig( $config );
|
177 |
+
}
|
178 |
+
/**
|
179 |
+
* create formatted output for calendar component VEVENT object instance
|
180 |
+
*
|
181 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
182 |
+
* @since 2.10.16 - 2011-10-28
|
183 |
+
* @param array $xcaldecl
|
184 |
+
* @uses calendarComponent::_createFormat()
|
185 |
+
* @uses calendarComponent::$componentStart1
|
186 |
+
* @uses calendarComponent::$componentStart2
|
187 |
+
* @uses calendarComponent::$nl;
|
188 |
+
* @uses calendarComponent::createUid()
|
189 |
+
* @uses calendarComponent::createDtstamp()
|
190 |
+
* @uses calendarComponent::createAttach()
|
191 |
+
* @uses calendarComponent::createAttendee()
|
192 |
+
* @uses calendarComponent::createCategories()
|
193 |
+
* @uses calendarComponent::createComment()
|
194 |
+
* @uses calendarComponent::createContact()
|
195 |
+
* @uses calendarComponent::createClass()
|
196 |
+
* @uses calendarComponent::createCreated()
|
197 |
+
* @uses calendarComponent::createDescription()
|
198 |
+
* @uses calendarComponent::createDtstart()
|
199 |
+
* @uses calendarComponent::createDtend()
|
200 |
+
* @uses calendarComponent::createDuration()
|
201 |
+
* @uses calendarComponent::createExdate()
|
202 |
+
* @uses calendarComponent::createExrule()
|
203 |
+
* @uses calendarComponent::createGeo()
|
204 |
+
* @uses calendarComponent::createLastModified()
|
205 |
+
* @uses calendarComponent::createLocation()
|
206 |
+
* @uses calendarComponent::createOrganizer()
|
207 |
+
* @uses calendarComponent::createPriority()
|
208 |
+
* @uses calendarComponent::createRdate()
|
209 |
+
* @uses calendarComponent::createRrule()
|
210 |
+
* @uses calendarComponent::createRelatedTo()
|
211 |
+
* @uses calendarComponent::createRequestStatus()
|
212 |
+
* @uses calendarComponent::createRecurrenceid()
|
213 |
+
* @uses calendarComponent::createResources()
|
214 |
+
* @uses calendarComponent::createSequence()
|
215 |
+
* @uses calendarComponent::createStatus()
|
216 |
+
* @uses calendarComponent::createSummary()
|
217 |
+
* @uses calendarComponent::createTransp()
|
218 |
+
* @uses calendarComponent::createUrl()
|
219 |
+
* @uses calendarComponent::createXprop()
|
220 |
+
* @uses calendarComponent::createSubComponent()
|
221 |
+
* @uses calendarComponent::$componentEnd1
|
222 |
+
* @uses calendarComponent::$componentEnd2
|
223 |
+
* @uses calendarComponent::$xcaldecl
|
224 |
+
* @return string
|
225 |
+
*/
|
226 |
+
function createComponent( & $xcaldecl ) {
|
227 |
+
$objectname = $this->_createFormat();
|
228 |
+
$component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
|
229 |
+
$component .= $this->createUid();
|
230 |
+
$component .= $this->createDtstamp();
|
231 |
+
$component .= $this->createAttach();
|
232 |
+
$component .= $this->createAttendee();
|
233 |
+
$component .= $this->createCategories();
|
234 |
+
$component .= $this->createComment();
|
235 |
+
$component .= $this->createContact();
|
236 |
+
$component .= $this->createClass();
|
237 |
+
$component .= $this->createCreated();
|
238 |
+
$component .= $this->createDescription();
|
239 |
+
$component .= $this->createDtstart();
|
240 |
+
$component .= $this->createDtend();
|
241 |
+
$component .= $this->createDuration();
|
242 |
+
$component .= $this->createExdate();
|
243 |
+
$component .= $this->createExrule();
|
244 |
+
$component .= $this->createGeo();
|
245 |
+
$component .= $this->createLastModified();
|
246 |
+
$component .= $this->createLocation();
|
247 |
+
$component .= $this->createOrganizer();
|
248 |
+
$component .= $this->createPriority();
|
249 |
+
$component .= $this->createRdate();
|
250 |
+
$component .= $this->createRrule();
|
251 |
+
$component .= $this->createRelatedTo();
|
252 |
+
$component .= $this->createRequestStatus();
|
253 |
+
$component .= $this->createRecurrenceid();
|
254 |
+
$component .= $this->createResources();
|
255 |
+
$component .= $this->createSequence();
|
256 |
+
$component .= $this->createStatus();
|
257 |
+
$component .= $this->createSummary();
|
258 |
+
$component .= $this->createTransp();
|
259 |
+
$component .= $this->createUrl();
|
260 |
+
$component .= $this->createXprop();
|
261 |
+
$component .= $this->createSubComponent();
|
262 |
+
$component .= $this->componentEnd1.$objectname.$this->componentEnd2;
|
263 |
+
if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
|
264 |
+
foreach( $this->xcaldecl as $localxcaldecl )
|
265 |
+
$xcaldecl[] = $localxcaldecl;
|
266 |
+
}
|
267 |
+
return $component;
|
268 |
+
}
|
269 |
+
}
|
includes/libs/iCal/lib/vfreebusy.class.php
ADDED
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* class for calendar component VFREEBUSY
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.5.1 - 2008-10-12
|
34 |
+
*/
|
35 |
+
class vfreebusy extends calendarComponent {
|
36 |
+
/**
|
37 |
+
* @var array $attendee component property value
|
38 |
+
* @var array $comment component property value
|
39 |
+
* @var array $contact component property value
|
40 |
+
* @var array $dtend component property value
|
41 |
+
* @var array $dtstart component property value
|
42 |
+
* @var array $duration component property value
|
43 |
+
* @var array $freebusy component property value
|
44 |
+
* @var array $organizer component property value
|
45 |
+
* @var array $requeststatus component property value
|
46 |
+
* @var array $url component property value
|
47 |
+
* @access protected
|
48 |
+
*/
|
49 |
+
protected $attendee;
|
50 |
+
protected $comment;
|
51 |
+
protected $contact;
|
52 |
+
protected $dtend;
|
53 |
+
protected $dtstart;
|
54 |
+
protected $duration;
|
55 |
+
protected $freebusy;
|
56 |
+
protected $organizer;
|
57 |
+
protected $requeststatus;
|
58 |
+
protected $url;
|
59 |
+
/**
|
60 |
+
* constructor for calendar component VFREEBUSY object
|
61 |
+
*
|
62 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
63 |
+
* @since 2.8.2 - 2011-05-01
|
64 |
+
* @param array $config
|
65 |
+
* @uses vjournal::calendarComponent()
|
66 |
+
* @uses vjournal::$attendee
|
67 |
+
* @uses vjournal::$comment
|
68 |
+
* @uses vjournal::$contact
|
69 |
+
* @uses vjournal::$dtend
|
70 |
+
* @uses vjournal::$dtstart
|
71 |
+
* @uses vjournal::$dtduration
|
72 |
+
* @uses vjournal::$organizer
|
73 |
+
* @uses vjournal::$requeststatus
|
74 |
+
* @uses vjournal::$url
|
75 |
+
* @uses vjournal::$xprop
|
76 |
+
* @uses calendarComponent::setConfig()
|
77 |
+
*/
|
78 |
+
function __construct( $config = array()) {
|
79 |
+
$this->calendarComponent();
|
80 |
+
$this->attendee = '';
|
81 |
+
$this->comment = '';
|
82 |
+
$this->contact = '';
|
83 |
+
$this->dtend = '';
|
84 |
+
$this->dtstart = '';
|
85 |
+
$this->duration = '';
|
86 |
+
$this->freebusy = '';
|
87 |
+
$this->organizer = '';
|
88 |
+
$this->requeststatus = '';
|
89 |
+
$this->url = '';
|
90 |
+
$this->xprop = '';
|
91 |
+
if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
|
92 |
+
$config['language'] = ICAL_LANG;
|
93 |
+
if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
|
94 |
+
if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
|
95 |
+
if( !isset( $config['format'] )) $config['format'] = 'iCal';
|
96 |
+
if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
|
97 |
+
$this->setConfig( $config );
|
98 |
+
}
|
99 |
+
/**
|
100 |
+
* create formatted output for calendar component VFREEBUSY object instance
|
101 |
+
*
|
102 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
103 |
+
* @since 2.3.1 - 2007-11-19
|
104 |
+
* @param array $xcaldecl
|
105 |
+
* @uses calendarComponent::_createFormat()
|
106 |
+
* @uses calendarComponent::createUid()
|
107 |
+
* @uses calendarComponent::createDtstamp()
|
108 |
+
* @uses calendarComponent::createAttendee()
|
109 |
+
* @uses calendarComponent::createComment()
|
110 |
+
* @uses calendarComponent::createContact()
|
111 |
+
* @uses calendarComponent::createDtstart()
|
112 |
+
* @uses calendarComponent::createDtend()
|
113 |
+
* @uses calendarComponent::createDuration()
|
114 |
+
* @uses calendarComponent::createFreebusy()
|
115 |
+
* @uses calendarComponent::createOrganizer()
|
116 |
+
* @uses calendarComponent::createRequestStatus()
|
117 |
+
* @uses calendarComponent::createUrl()
|
118 |
+
* @uses calendarComponent::createXprop()
|
119 |
+
* @uses calendarComponent::createUrl()
|
120 |
+
* @uses calendarComponent::createXprop()
|
121 |
+
* @uses calendarComponent::$componentEnd1
|
122 |
+
* @uses calendarComponent::$componentEnd2
|
123 |
+
* @uses calendarComponent::$xcaldecl
|
124 |
+
* @return string
|
125 |
+
*/
|
126 |
+
function createComponent( &$xcaldecl ) {
|
127 |
+
$objectname = $this->_createFormat();
|
128 |
+
$component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
|
129 |
+
$component .= $this->createUid();
|
130 |
+
$component .= $this->createDtstamp();
|
131 |
+
$component .= $this->createAttendee();
|
132 |
+
$component .= $this->createComment();
|
133 |
+
$component .= $this->createContact();
|
134 |
+
$component .= $this->createDtstart();
|
135 |
+
$component .= $this->createDtend();
|
136 |
+
$component .= $this->createDuration();
|
137 |
+
$component .= $this->createFreebusy();
|
138 |
+
$component .= $this->createOrganizer();
|
139 |
+
$component .= $this->createRequestStatus();
|
140 |
+
$component .= $this->createUrl();
|
141 |
+
$component .= $this->createXprop();
|
142 |
+
$component .= $this->componentEnd1.$objectname.$this->componentEnd2;
|
143 |
+
if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
|
144 |
+
foreach( $this->xcaldecl as $localxcaldecl )
|
145 |
+
$xcaldecl[] = $localxcaldecl;
|
146 |
+
}
|
147 |
+
return $component;
|
148 |
+
}
|
149 |
+
}
|
includes/libs/iCal/lib/vjournal.class.php
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* class for calendar component VJOURNAL
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.5.1 - 2008-10-12
|
34 |
+
*/
|
35 |
+
class vjournal extends calendarComponent {
|
36 |
+
/**
|
37 |
+
* @var array $attach component property value
|
38 |
+
* @var array $attendee component property value
|
39 |
+
* @var array $categories component property value
|
40 |
+
* @var array $comment component property value
|
41 |
+
* @var array $contact component property value
|
42 |
+
* @var array $class component property value
|
43 |
+
* @var array $created component property value
|
44 |
+
* @var array $description component property value
|
45 |
+
* @var array $dtstart component property value
|
46 |
+
* @var array $exdate component property value
|
47 |
+
* @var array $exrule component property value
|
48 |
+
* @var array $lastmodified component property value
|
49 |
+
* @var array $organizer component property value
|
50 |
+
* @var array $rdate component property value
|
51 |
+
* @var array $recurrenceid component property value
|
52 |
+
* @var array $relatedto component property value
|
53 |
+
* @var array $requeststatus component property value
|
54 |
+
* @var array $rrule component property value
|
55 |
+
* @var array $sequence component property value
|
56 |
+
* @var array $status component property value
|
57 |
+
* @var array $summary component property value
|
58 |
+
* @var array $url component property value
|
59 |
+
* @access protected
|
60 |
+
*/
|
61 |
+
protected $attach;
|
62 |
+
protected $attendee;
|
63 |
+
protected $categories;
|
64 |
+
protected $comment;
|
65 |
+
protected $contact;
|
66 |
+
protected $class;
|
67 |
+
protected $created;
|
68 |
+
protected $description;
|
69 |
+
protected $dtstart;
|
70 |
+
protected $exdate;
|
71 |
+
protected $exrule;
|
72 |
+
protected $lastmodified;
|
73 |
+
protected $organizer;
|
74 |
+
protected $rdate;
|
75 |
+
protected $recurrenceid;
|
76 |
+
protected $relatedto;
|
77 |
+
protected $requeststatus;
|
78 |
+
protected $rrule;
|
79 |
+
protected $sequence;
|
80 |
+
protected $status;
|
81 |
+
protected $summary;
|
82 |
+
protected $url;
|
83 |
+
/**
|
84 |
+
* constructor for calendar component VJOURNAL object
|
85 |
+
*
|
86 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
87 |
+
* @since 2.8.2 - 2011-05-01
|
88 |
+
* @param array $config
|
89 |
+
* @uses vjournal::calendarComponent()
|
90 |
+
* @uses vjournal::$attach
|
91 |
+
* @uses vjournal::$attendee
|
92 |
+
* @uses vjournal::$categories
|
93 |
+
* @uses vjournal::$class
|
94 |
+
* @uses vjournal::$comment
|
95 |
+
* @uses vjournal::$contact
|
96 |
+
* @uses vjournal::$created
|
97 |
+
* @uses vjournal::$description
|
98 |
+
* @uses vjournal::$dtstart
|
99 |
+
* @uses vjournal::$exdate
|
100 |
+
* @uses vjournal::$exrule
|
101 |
+
* @uses vjournal::$lastmodified
|
102 |
+
* @uses vjournal::$organizer
|
103 |
+
* @uses vjournal::$rdate
|
104 |
+
* @uses vjournal::$recurrenceid
|
105 |
+
* @uses vjournal::$relatedto
|
106 |
+
* @uses vjournal::$requeststatus
|
107 |
+
* @uses vjournal::$rrule
|
108 |
+
* @uses vjournal::$sequence
|
109 |
+
* @uses vjournal::$status
|
110 |
+
* @uses vjournal::$summary
|
111 |
+
* @uses vjournal::$url
|
112 |
+
* @uses vjournal::$xprop
|
113 |
+
* @uses calendarComponent::setConfig()
|
114 |
+
*/
|
115 |
+
function __construct( $config = array()) {
|
116 |
+
$this->calendarComponent();
|
117 |
+
$this->attach = '';
|
118 |
+
$this->attendee = '';
|
119 |
+
$this->categories = '';
|
120 |
+
$this->class = '';
|
121 |
+
$this->comment = '';
|
122 |
+
$this->contact = '';
|
123 |
+
$this->created = '';
|
124 |
+
$this->description = '';
|
125 |
+
$this->dtstart = '';
|
126 |
+
$this->exdate = '';
|
127 |
+
$this->exrule = '';
|
128 |
+
$this->lastmodified = '';
|
129 |
+
$this->organizer = '';
|
130 |
+
$this->rdate = '';
|
131 |
+
$this->recurrenceid = '';
|
132 |
+
$this->relatedto = '';
|
133 |
+
$this->requeststatus = '';
|
134 |
+
$this->rrule = '';
|
135 |
+
$this->sequence = '';
|
136 |
+
$this->status = '';
|
137 |
+
$this->summary = '';
|
138 |
+
$this->url = '';
|
139 |
+
$this->xprop = '';
|
140 |
+
if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
|
141 |
+
$config['language'] = ICAL_LANG;
|
142 |
+
if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
|
143 |
+
if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
|
144 |
+
if( !isset( $config['format'] )) $config['format'] = 'iCal';
|
145 |
+
if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
|
146 |
+
$this->setConfig( $config );
|
147 |
+
}
|
148 |
+
/**
|
149 |
+
* create formatted output for calendar component VJOURNAL object instance
|
150 |
+
*
|
151 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
152 |
+
* @since 2.5.1 - 2008-10-12
|
153 |
+
* @param array $xcaldecl
|
154 |
+
* @uses calendarComponent::_createFormat()
|
155 |
+
* @uses calendarComponent::$componentStart1
|
156 |
+
* @uses calendarComponent::$componentStart2
|
157 |
+
* @uses calendarComponent::$nl
|
158 |
+
* @uses calendarComponent::createUid()
|
159 |
+
* @uses calendarComponent::createDtstamp()
|
160 |
+
* @uses calendarComponent::createAttach()
|
161 |
+
* @uses calendarComponent::createAttendee()
|
162 |
+
* @uses calendarComponent::createCategories()
|
163 |
+
* @uses calendarComponent::createClass()
|
164 |
+
* @uses calendarComponent::createComment()
|
165 |
+
* @uses calendarComponent::createContact()
|
166 |
+
* @uses calendarComponent::createDescription()
|
167 |
+
* @uses calendarComponent::createDtstart()
|
168 |
+
* @uses calendarComponent::createExdate()
|
169 |
+
* @uses calendarComponent::createExrule()
|
170 |
+
* @uses calendarComponent::createLastModified()
|
171 |
+
* @uses calendarComponent::createOrganizer()
|
172 |
+
* @uses calendarComponent::createRdate()
|
173 |
+
* @uses calendarComponent::createRelatedTo()
|
174 |
+
* @uses calendarComponent::createRequestStatus()
|
175 |
+
* @uses calendarComponent::createRecurrenceid()
|
176 |
+
* @uses calendarComponent::createRrule()
|
177 |
+
* @uses calendarComponent::createSequence()
|
178 |
+
* @uses calendarComponent::createStatus()
|
179 |
+
* @uses calendarComponent::createSummary()
|
180 |
+
* @uses calendarComponent::createUrl()
|
181 |
+
* @uses calendarComponent::createXprop()
|
182 |
+
* @uses calendarComponent::$componentEnd1
|
183 |
+
* @uses calendarComponent::$componentEnd2
|
184 |
+
* @uses calendarComponent::$xcaldecl
|
185 |
+
* @return string
|
186 |
+
*/
|
187 |
+
function createComponent( &$xcaldecl ) {
|
188 |
+
$objectname = $this->_createFormat();
|
189 |
+
$component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
|
190 |
+
$component .= $this->createUid();
|
191 |
+
$component .= $this->createDtstamp();
|
192 |
+
$component .= $this->createAttach();
|
193 |
+
$component .= $this->createAttendee();
|
194 |
+
$component .= $this->createCategories();
|
195 |
+
$component .= $this->createClass();
|
196 |
+
$component .= $this->createComment();
|
197 |
+
$component .= $this->createContact();
|
198 |
+
$component .= $this->createCreated();
|
199 |
+
$component .= $this->createDescription();
|
200 |
+
$component .= $this->createDtstart();
|
201 |
+
$component .= $this->createExdate();
|
202 |
+
$component .= $this->createExrule();
|
203 |
+
$component .= $this->createLastModified();
|
204 |
+
$component .= $this->createOrganizer();
|
205 |
+
$component .= $this->createRdate();
|
206 |
+
$component .= $this->createRequestStatus();
|
207 |
+
$component .= $this->createRecurrenceid();
|
208 |
+
$component .= $this->createRelatedTo();
|
209 |
+
$component .= $this->createRrule();
|
210 |
+
$component .= $this->createSequence();
|
211 |
+
$component .= $this->createStatus();
|
212 |
+
$component .= $this->createSummary();
|
213 |
+
$component .= $this->createUrl();
|
214 |
+
$component .= $this->createXprop();
|
215 |
+
$component .= $this->componentEnd1.$objectname.$this->componentEnd2;
|
216 |
+
if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
|
217 |
+
foreach( $this->xcaldecl as $localxcaldecl )
|
218 |
+
$xcaldecl[] = $localxcaldecl;
|
219 |
+
}
|
220 |
+
return $component;
|
221 |
+
}
|
222 |
+
}
|
includes/libs/iCal/lib/vtimezone.class.php
ADDED
@@ -0,0 +1,165 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* iCalcreator, a PHP rfc2445/rfc5545 solution.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* class for calendar component VTIMEZONE
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.5.1 - 2008-10-12
|
34 |
+
*/
|
35 |
+
class vtimezone extends calendarComponent {
|
36 |
+
/** @var array $timezonetype component property value */
|
37 |
+
public $timezonetype;
|
38 |
+
/**
|
39 |
+
* @var array $comment component property value
|
40 |
+
* @var array $dtstart component property value
|
41 |
+
* @var array $lastmodified component property value
|
42 |
+
* @var array $rdate component property value
|
43 |
+
* @var array $rrule component property value
|
44 |
+
* @var array $tzid component property value
|
45 |
+
* @var array $tzname component property value
|
46 |
+
* @var array $tzoffsetfrom component property value
|
47 |
+
* @var array $tzoffsetto component property value
|
48 |
+
* @var array $tzurl component property value
|
49 |
+
* @access protected
|
50 |
+
*/
|
51 |
+
protected $comment;
|
52 |
+
protected $dtstart;
|
53 |
+
protected $lastmodified;
|
54 |
+
protected $rdate;
|
55 |
+
protected $rrule;
|
56 |
+
protected $tzid;
|
57 |
+
protected $tzname;
|
58 |
+
protected $tzoffsetfrom;
|
59 |
+
protected $tzoffsetto;
|
60 |
+
protected $tzurl;
|
61 |
+
/**
|
62 |
+
* constructor for calendar component VTIMEZONE object
|
63 |
+
*
|
64 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
65 |
+
* @since 2.8.2 - 2011-05-01
|
66 |
+
* @param mixed $timezonetype default FALSE ( STANDARD / DAYLIGHT )
|
67 |
+
* @param array $config
|
68 |
+
* @uses vtimezone::$timezonetype
|
69 |
+
* @uses vtimezone::calendarComponent()
|
70 |
+
* @uses vtimezone::$comment
|
71 |
+
* @uses vtimezone::$dtstart
|
72 |
+
* @uses vtimezone::$lastmodified
|
73 |
+
* @uses vtimezone::$rdate
|
74 |
+
* @uses vtimezone::$rrule
|
75 |
+
* @uses vtimezone::$tzid
|
76 |
+
* @uses vtimezone::$tzname
|
77 |
+
* @uses vtimezone::$tzoffsetfrom
|
78 |
+
* @uses vtimezone::$tzoffsetto
|
79 |
+
* @uses vtimezone::$tzurl
|
80 |
+
* @uses vtimezone::$xprop
|
81 |
+
* @uses vtimezone::$components
|
82 |
+
* @uses calendarComponent::setConfig()
|
83 |
+
*/
|
84 |
+
function __construct( $timezonetype=FALSE, $config = array()) {
|
85 |
+
if( is_array( $timezonetype )) {
|
86 |
+
$config = $timezonetype;
|
87 |
+
$timezonetype = FALSE;
|
88 |
+
}
|
89 |
+
if( !$timezonetype )
|
90 |
+
$this->timezonetype = 'VTIMEZONE';
|
91 |
+
else
|
92 |
+
$this->timezonetype = strtoupper( $timezonetype );
|
93 |
+
$this->component();
|
94 |
+
$this->comment = '';
|
95 |
+
$this->dtstart = '';
|
96 |
+
$this->lastmodified = '';
|
97 |
+
$this->rdate = '';
|
98 |
+
$this->rrule = '';
|
99 |
+
$this->tzid = '';
|
100 |
+
$this->tzname = '';
|
101 |
+
$this->tzoffsetfrom = '';
|
102 |
+
$this->tzoffsetto = '';
|
103 |
+
$this->tzurl = '';
|
104 |
+
$this->xprop = '';
|
105 |
+
$this->components = array();
|
106 |
+
if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
|
107 |
+
$config['language'] = ICAL_LANG;
|
108 |
+
if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
|
109 |
+
if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
|
110 |
+
if( !isset( $config['format'] )) $config['format'] = 'iCal';
|
111 |
+
if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
|
112 |
+
$this->setConfig( $config );
|
113 |
+
}
|
114 |
+
/**
|
115 |
+
* create formatted output for calendar component VTIMEZONE object instance
|
116 |
+
*
|
117 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
118 |
+
* @since 2.5.1 - 2008-10-25
|
119 |
+
* @param array $xcaldecl
|
120 |
+
* @uses calendarComponent::_createFormat()
|
121 |
+
* @uses calendarComponent::$componentStart1
|
122 |
+
* @uses calendarComponent::$componentStart2
|
123 |
+
* @uses calendarComponent::$nl
|
124 |
+
* @uses calendarComponent::createTzid()
|
125 |
+
* @uses calendarComponent::createLastModified()
|
126 |
+
* @uses calendarComponent::createTzurl()
|
127 |
+
* @uses calendarComponent::createDtstart()
|
128 |
+
* @uses calendarComponent::createTzoffsetfrom()
|
129 |
+
* @uses calendarComponent::createTzoffsetto()
|
130 |
+
* @uses calendarComponent::createComment()
|
131 |
+
* @uses calendarComponent::createRdate()
|
132 |
+
* @uses calendarComponent::createRrule()
|
133 |
+
* @uses calendarComponent::createTzname()
|
134 |
+
* @uses calendarComponent::createXprop()
|
135 |
+
* @uses calendarComponent::createSubComponent()
|
136 |
+
* @uses calendarComponent::createXprop()
|
137 |
+
* @uses calendarComponent::$componentEnd1
|
138 |
+
* @uses calendarComponent::$componentEnd2
|
139 |
+
* @uses calendarComponent::$xcaldecl
|
140 |
+
* @return string
|
141 |
+
*/
|
142 |
+
function createComponent( &$xcaldecl )
|
143 |
+
{
|
144 |
+
$objectname = $this->_createFormat();
|
145 |
+
$component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
|
146 |
+
$component .= $this->createTzid();
|
147 |
+
$component .= $this->createLastModified();
|
148 |
+
$component .= $this->createTzurl();
|
149 |
+
$component .= $this->createDtstart();
|
150 |
+
$component .= $this->createTzoffsetfrom();
|
151 |
+
$component .= $this->createTzoffsetto();
|
152 |
+
$component .= $this->createComment();
|
153 |
+
$component .= $this->createRdate();
|
154 |
+
$component .= $this->createRrule();
|
155 |
+
$component .= $this->createTzname();
|
156 |
+
$component .= $this->createXprop();
|
157 |
+
$component .= $this->createSubComponent();
|
158 |
+
$component .= $this->componentEnd1.$objectname.$this->componentEnd2;
|
159 |
+
if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
|
160 |
+
foreach( $this->xcaldecl as $localxcaldecl )
|
161 |
+
$xcaldecl[] = $localxcaldecl;
|
162 |
+
}
|
163 |
+
return $component;
|
164 |
+
}
|
165 |
+
}
|
includes/libs/iCal/lib/vtodo.class.php
ADDED
@@ -0,0 +1,273 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*********************************************************************************/
|
3 |
+
/**
|
4 |
+
*
|
5 |
+
* A PHP implementation of rfc2445/rfc5545.
|
6 |
+
*
|
7 |
+
* @copyright Copyright (c) 2007-2015 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
|
8 |
+
* @link http://kigkonsult.se/iCalcreator/index.php
|
9 |
+
* @license http://kigkonsult.se/downloads/dl.php?f=LGPL
|
10 |
+
* @package iCalcreator
|
11 |
+
* @version 2.22
|
12 |
+
*/
|
13 |
+
/**
|
14 |
+
* This library is free software; you can redistribute it and/or
|
15 |
+
* modify it under the terms of the GNU Lesser General Public
|
16 |
+
* License as published by the Free Software Foundation; either
|
17 |
+
* version 2.1 of the License, or (at your option) any later version.
|
18 |
+
*
|
19 |
+
* This library is distributed in the hope that it will be useful,
|
20 |
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
21 |
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22 |
+
* Lesser General Public License for more details.
|
23 |
+
*
|
24 |
+
* You should have received a copy of the GNU Lesser General Public
|
25 |
+
* License along with this library; if not, write to the Free Software
|
26 |
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
27 |
+
*/
|
28 |
+
/*********************************************************************************/
|
29 |
+
/**
|
30 |
+
* class for calendar component VTODO
|
31 |
+
*
|
32 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
33 |
+
* @since 2.5.1 - 2008-10-12
|
34 |
+
*/
|
35 |
+
class vtodo extends calendarComponent {
|
36 |
+
/**
|
37 |
+
* @var array $attach component property value
|
38 |
+
* @var array $attendee component property value
|
39 |
+
* @var array $categories component property value
|
40 |
+
* @var array $comment component property value
|
41 |
+
* @var array $completed component property value
|
42 |
+
* @var array $contact component property value
|
43 |
+
* @var array $class component property value
|
44 |
+
* @var array $created component property value
|
45 |
+
* @var array $description component property value
|
46 |
+
* @var array $dtstart component property value
|
47 |
+
* @var array $due component property value
|
48 |
+
* @var array $duration component property value
|
49 |
+
* @var array $exdate component property value
|
50 |
+
* @var array $exrule component property value
|
51 |
+
* @var array $geo component property value
|
52 |
+
* @var array $lastmodified component property value
|
53 |
+
* @var array $location component property value
|
54 |
+
* @var array $organizer component property value
|
55 |
+
* @var array $percentcomplete component property value
|
56 |
+
* @var array $priority component property value
|
57 |
+
* @var array $rdate component property value
|
58 |
+
* @var array $recurrenceid component property value
|
59 |
+
* @var array $relatedto component property value
|
60 |
+
* @var array $requeststatus component property value
|
61 |
+
* @var array $resources component property value
|
62 |
+
* @var array $rrule component property value
|
63 |
+
* @var array $sequence component property value
|
64 |
+
* @var array $status component property value
|
65 |
+
* @var array $summary component property value
|
66 |
+
* @var arrayr $url;
|
67 |
+
* @access protected
|
68 |
+
*/
|
69 |
+
protected $attach;
|
70 |
+
protected $attendee;
|
71 |
+
protected $categories;
|
72 |
+
protected $comment;
|
73 |
+
protected $completed;
|
74 |
+
protected $contact;
|
75 |
+
protected $class;
|
76 |
+
protected $created;
|
77 |
+
protected $description;
|
78 |
+
protected $dtstart;
|
79 |
+
protected $due;
|
80 |
+
protected $duration;
|
81 |
+
protected $exdate;
|
82 |
+
protected $exrule;
|
83 |
+
protected $geo;
|
84 |
+
protected $lastmodified;
|
85 |
+
protected $location;
|
86 |
+
protected $organizer;
|
87 |
+
protected $percentcomplete;
|
88 |
+
protected $priority;
|
89 |
+
protected $rdate;
|
90 |
+
protected $recurrenceid;
|
91 |
+
protected $relatedto;
|
92 |
+
protected $requeststatus;
|
93 |
+
protected $resources;
|
94 |
+
protected $rrule;
|
95 |
+
protected $sequence;
|
96 |
+
protected $status;
|
97 |
+
protected $summary;
|
98 |
+
protected $url;
|
99 |
+
/**
|
100 |
+
* constructor for calendar component VTODO object
|
101 |
+
*
|
102 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
103 |
+
* @since 2.8.2 - 2011-05-01
|
104 |
+
* @param array $config
|
105 |
+
* @uses vtodo::calendarComponent()
|
106 |
+
* @uses vtodo::$attach
|
107 |
+
* @uses vtodo::$attendee
|
108 |
+
* @uses vtodo::$categories
|
109 |
+
* @uses vtodo::$class
|
110 |
+
* @uses vtodo::$comment
|
111 |
+
* @uses vtodo::$completed
|
112 |
+
* @uses vtodo::$contact
|
113 |
+
* @uses vtodo::$created
|
114 |
+
* @uses vtodo::$description
|
115 |
+
* @uses vtodo::$dtstart
|
116 |
+
* @uses vtodo::$due
|
117 |
+
* @uses vtodo::$duration
|
118 |
+
* @uses vtodo::$exdate
|
119 |
+
* @uses vtodo::$exrule
|
120 |
+
* @uses vtodo::$geo
|
121 |
+
* @uses vtodo::$lastmodified
|
122 |
+
* @uses vtodo::$location
|
123 |
+
* @uses vtodo::$organizer
|
124 |
+
* @uses vtodo::$percentcomplete
|
125 |
+
* @uses vtodo::$priority
|
126 |
+
* @uses vtodo::$rdate
|
127 |
+
* @uses vtodo::$recurrenceid
|
128 |
+
* @uses vtodo::$relatedto
|
129 |
+
* @uses vtodo::$requeststatus
|
130 |
+
* @uses vtodo::$resources
|
131 |
+
* @uses vtodo::$rrule
|
132 |
+
* @uses vtodo::$sequence
|
133 |
+
* @uses vtodo::$status
|
134 |
+
* @uses vtodo::$summary
|
135 |
+
* @uses vtodo::$url
|
136 |
+
* @uses vtodo::$xprop
|
137 |
+
* @uses vtodo::$components
|
138 |
+
* @uses calendarComponent::setConfig()
|
139 |
+
*/
|
140 |
+
function __construct( $config = array()) {
|
141 |
+
$this->calendarComponent();
|
142 |
+
$this->attach = '';
|
143 |
+
$this->attendee = '';
|
144 |
+
$this->categories = '';
|
145 |
+
$this->class = '';
|
146 |
+
$this->comment = '';
|
147 |
+
$this->completed = '';
|
148 |
+
$this->contact = '';
|
149 |
+
$this->created = '';
|
150 |
+
$this->description = '';
|
151 |
+
$this->dtstart = '';
|
152 |
+
$this->due = '';
|
153 |
+
$this->duration = '';
|
154 |
+
$this->exdate = '';
|
155 |
+
$this->exrule = '';
|
156 |
+
$this->geo = '';
|
157 |
+
$this->lastmodified = '';
|
158 |
+
$this->location = '';
|
159 |
+
$this->organizer = '';
|
160 |
+
$this->percentcomplete = '';
|
161 |
+
$this->priority = '';
|
162 |
+
$this->rdate = '';
|
163 |
+
$this->recurrenceid = '';
|
164 |
+
$this->relatedto = '';
|
165 |
+
$this->requeststatus = '';
|
166 |
+
$this->resources = '';
|
167 |
+
$this->rrule = '';
|
168 |
+
$this->sequence = '';
|
169 |
+
$this->status = '';
|
170 |
+
$this->summary = '';
|
171 |
+
$this->url = '';
|
172 |
+
$this->xprop = '';
|
173 |
+
$this->components = array();
|
174 |
+
if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
|
175 |
+
$config['language'] = ICAL_LANG;
|
176 |
+
if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
|
177 |
+
if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
|
178 |
+
if( !isset( $config['format'] )) $config['format'] = 'iCal';
|
179 |
+
if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
|
180 |
+
$this->setConfig( $config );
|
181 |
+
}
|
182 |
+
/**
|
183 |
+
* create formatted output for calendar component VTODO object instance
|
184 |
+
*
|
185 |
+
* @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
|
186 |
+
* @since 2.5.1 - 2008-11-07
|
187 |
+
* @param array $xcaldecl
|
188 |
+
* @uses calendarComponent::_createFormat()
|
189 |
+
* @uses calendarComponent::$componentStart1
|
190 |
+
* @uses calendarComponent::$componentStart2
|
191 |
+
* @uses calendarComponent::$nl;
|
192 |
+
* @uses calendarComponent::createUid()
|
193 |
+
* @uses calendarComponent::createDtstamp()
|
194 |
+
* @uses calendarComponent::createAttach()
|
195 |
+
* @uses calendarComponent::createAttendee()
|
196 |
+
* @uses calendarComponent::createCategories()
|
197 |
+
* @uses calendarComponent::createClass()
|
198 |
+
* @uses calendarComponent::createComment()
|
199 |
+
* @uses calendarComponent::createCompleted()
|
200 |
+
* @uses calendarComponent::createContact()
|
201 |
+
* @uses calendarComponent::createDescription()
|
202 |
+
* @uses calendarComponent::createDtstart()
|
203 |
+
* @uses calendarComponent::createDtend()
|
204 |
+
* @uses calendarComponent::createDuration()
|
205 |
+
* @uses calendarComponent::createExdate()
|
206 |
+
* @uses calendarComponent::createExrule()
|
207 |
+
* @uses calendarComponent::crea
|