diff --git a/.distignore b/.distignore index 01f67b837..882017fa3 100644 --- a/.distignore +++ b/.distignore @@ -22,4 +22,5 @@ project.json README.md tsconfig.* webpack.config.js -phpstan.neon \ No newline at end of file +phpstan.neon +phpstan-baseline.neon diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..f9a2f6712 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,3 @@ +# .git-blame-ignore-revs +# Apply phpcbf to entire codebase +59340f68fb9c6d6e680ac3ad40a3d095e98837a6 diff --git a/.github/actions/build-plugin/action.yml b/.github/actions/build-plugin/action.yml index 4df6d5df0..96f35d6f9 100644 --- a/.github/actions/build-plugin/action.yml +++ b/.github/actions/build-plugin/action.yml @@ -1,6 +1,15 @@ name: 'Build Plugin' description: 'Builds plugin into ./build/commonsbooking' +inputs: + generate_zip: + description: 'Set to true, if a zip file should be generated in the root of the plugin folder' + required: false + default: 'false' + options: + - true + - false + runs: using: "composite" steps: @@ -30,6 +39,12 @@ runs: - run: npm ci --legacy-peer-deps --include=dev shell: bash - - name: Run build script + - name: Run build script (skip zip generation) + if: ${{ inputs.generate_zip == 'false' }} run: bin/build-zip.sh --skip-zip - shell: bash \ No newline at end of file + shell: bash + + - name: Run build script and generate zip file + if: ${{ inputs.generate_zip == 'true' }} + run: bin/build-zip.sh + shell: bash diff --git a/.github/workflows/zip-pr.yml b/.github/workflows/zip-pr.yml new file mode 100644 index 000000000..103ed6df5 --- /dev/null +++ b/.github/workflows/zip-pr.yml @@ -0,0 +1,52 @@ +name: Build zip from PR +on: + pull_request: + branches: + - 'master' + +jobs: + zip-pr: + runs-on: ubuntu-20.04 + steps: + + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Important for getting full commit history + + - name: Update Version Comment + run: | + sed -i "s|define('COMMONSBOOKING_VERSION_COMMENT',.*|define('COMMONSBOOKING_VERSION_COMMENT', '${{ github.head_ref }} at ${{ github.event.pull_request.head.sha}}');|" commonsbooking.php + - uses: ./.github/actions/build-plugin + with: + generate_zip: 'true' + + - name: Upload zip + uses: SamKirkland/FTP-Deploy-Action@v4.3.5 + with: + exclude: | + ** + ! commonsbooking.zip + server: ${{ secrets.CBZIPUPLOAD_SERVER }} + username: ${{ secrets.CBZIPUPLOAD_USER }} + password: ${{ secrets.CBZIPUPLOAD_KEY }} + server-dir: ${{ github.event.number }}/ + dangerous-clean-slate: true + protocol: ftps + + - name: Find Comment + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: Download built plugin zip + + - name: Create or update comment + uses: peter-evans/create-or-update-comment@v4 + with: + comment-id: ${{ steps.fc.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + [Download built plugin zip](https://builds.commonsbooking.org/${{ github.event.number }}/commonsbooking.zip) + [Test Plugin in Wordpress Playground](https://playground.wordpress.net/#{%22steps%22:[{%22step%22:%22installPlugin%22,%22pluginData%22:{%22resource%22:%22url%22,%22url%22:%22https://builds.commonsbooking.org/${{ github.event.number }}/commonsbooking.zip%22}},{%22step%22:%22importWxr%22,%22file%22:{%22resource%22:%22url%22,%22url%22:%22https://raw.githubusercontent.com/wielebenwir/commonsbooking/refs/heads/master/tests/cypress/wordpress-files/content-example.xml%22}}],%22preferredVersions%22:{%22php%22:%227.4%22,%22wp%22:%22latest%22},%22login%22:true}) + edit-mode: replace diff --git a/Readme.md b/Readme.md index ffea08403..bef8c0869 100644 --- a/Readme.md +++ b/Readme.md @@ -51,8 +51,8 @@ CommonsBooking is a plugin for the management and booking of common goods. This 1. Make sure that composer is installed on your system 2. Navigate into your wp-content/plugins directory 3. Open a terminal and run `git clone https://github.com/wielebenwir/commonsbooking` -4. cd into the directory commonsbooking and run `composer install` -> This might fail, if you don't have the PHP extension [uopz](https://www.php.net/manual/en/book.uopz.php) installed. Try running `composer install --no-dev` if you just quickly want to test a specific branch without installing the extension. +4. cd into the directory commonsbooking and run `npm start` +> This might fail, if you don't have the PHP extension [uopz](https://www.php.net/manual/en/book.uopz.php) installed. Try running `composer install --no-dev && npm install && npm run dist` if you just quickly want to test a specific branch without installing the extension. 5. Activate the plugin in the plugins dashboard ## Contribute diff --git a/TECHNICAL.md b/TECHNICAL.md new file mode 100644 index 000000000..aa69869bc --- /dev/null +++ b/TECHNICAL.md @@ -0,0 +1,10 @@ +### Formatter + +We use .git-blame-ignore-revs to track repo-wide cosmetic refactorings by auto format tools like prettier/phpcbf. +See [Github Documentation](https://docs.github.com/de/repositories/working-with-files/using-files/viewing-and-understanding-files#ignore-commits-in-the-blame-view) + +You can also configure your local git so it always ignores the revs in that file: + +```bash +git config blame.ignoreRevsFile .git-blame-ignore-revs +``` diff --git a/assets/admin/js/admin.js b/assets/admin/js/admin.js index f0d608e84..d5dc4a935 100644 --- a/assets/admin/js/admin.js +++ b/assets/admin/js/admin.js @@ -5,6 +5,14 @@ let startTimeInput = $("#repetition-start_time"); let endTimeInput = $("#repetition-end_time"); let preserveManualCode = false; + let itemInput = $("#item-id"); + let locationInput = $("#location-id"); + let startDateInput = $("#repetition-start_date"); + let bookingCodeInput = $("#_cb_bookingcode"); + let allExist = [ fullDayCheckbox, startTimeInput, endTimeInput, itemInput, locationInput, startDateInput, bookingCodeInput ].every(domElement => domElement.length === 1); + if (!allExist) { + return; + } fullDayCheckbox.on("change", function(event) { if (fullDayCheckbox.is(":checked")) { startTimeInput.val("00:00"); @@ -17,10 +25,6 @@ } }); fullDayCheckbox.trigger("change"); - let itemInput = $("#item-id"); - let locationInput = $("#location-id"); - let startDateInput = $("#repetition-start_date"); - let bookingCodeInput = $("#_cb_bookingcode"); itemInput.on("change", function(event) { let data = { itemID: itemInput.val() diff --git a/assets/admin/js/admin.min.js b/assets/admin/js/admin.min.js index ab0488614..bff27d64a 100644 --- a/assets/admin/js/admin.min.js +++ b/assets/admin/js/admin.min.js @@ -1 +1 @@ -!function(d){"use strict";d(function(){let n=d("#full-day"),t=d("#repetition-start_time"),o=d("#repetition-end_time"),i=!1,a=(n.on("change",function(e){n.is(":checked")?(t.val("00:00"),o.val("23:59"),t.hide(),o.hide()):(t.show(),o.show())}),n.trigger("change"),d("#item-id")),r=d("#location-id"),c=d("#repetition-start_date"),s=d("#_cb_bookingcode");a.on("change",function(e){var t={itemID:a.val()};d.post(cb_ajax_get_bookable_location.ajax_url,{_ajax_nonce:cb_ajax_get_bookable_location.nonce,action:"cb_get_bookable_location",data:t},function(e){e.success&&(r.val(e.locationID),n.prop("checked",e.fullDay),n.trigger("change"))}).then(()=>{l()})}),a.trigger("change");const l=()=>{var e;n.is(":checked")&&(e={itemID:a.val(),locationID:r.val(),startDate:c.val()},d.post(cb_ajax_get_booking_code.ajax_url,{_ajax_nonce:cb_ajax_get_booking_code.nonce,action:"cb_get_booking_code",data:e},function(e){e.success?(s.val(e.bookingCode),i=!1):i||s.val("")}))};s.on("keyup",function(e){i=!0}),c.on("change",function(e){l()}),n.on("change",function(e){l()})})}(jQuery),function(k){"use strict";k(function(){function E(){var t=k("#"+T+"_repeat");t.on("cmb2_add_row cmb2_remove_row cmb2_shift_rows_complete",function(){E()});for(let e=0;e{if(t.name==b){if(a.text(t.description),i.width(300),r.show(),c.show(),s.show(),a.show(),t.hasOwnProperty("params")&&0",{value:e,text:n[e]}));_.width(150);var o=cb_applied_booking_rules.filter(e=>e.name==t.name);1===o.length&&_.val(o[0].appliedSelectParam)}else p.hide()}})}}function i(){var t=k("#"+T+"_repeat");t.on("cmb2_add_row cmb2_remove_row cmb2_shift_rows_complete",function(){i()});for(let e=0;e{m.post(cb_ajax_export_timeframes.ajax_url,{_ajax_nonce:cb_ajax_export_timeframes.nonce,action:"cb_export_timeframes",data:e},function(e){var t,n,o;e.success?(d.show(),h.text(e.message),s.hide(),t=new Blob([e.csv]),n=e.filename,(o=document.createElement("a")).href=URL.createObjectURL(t),o.download=n,o.click()):e.error?(u.show(),f.text(e.message),s.hide()):(l.text(e.progress),i(e))})};i(e)})})}(jQuery),function(a){"use strict";a(function(){var e=a("#holiday_load_btn");const o=a("#timeframe_manual_date");var t=a("#cmb2_multiselect_datepicker"),i=e=>{var t=e.getDate(),n=e.getMonth()+1,t=t<=9?"0"+t:t,n=n<=9?"0"+n:n,e=e.getFullYear()+"-"+n+"-"+t;0{e=new Date(e.date);i(e)})})})}(jQuery),function(l){"use strict";l(function(){function e(e){l.each(e,function(){l(this).parents(".cmb-row").hide()})}function t(e){l.each(e,function(){l(this).parents(".cmb-row").show()})}function n(){(c.prop("checked")?t:e)(s)}function o(){r.prop("checked")?(t(c),n()):(e(c),e(s))}function i(){a.prop("checked")?(e(r),e(c),e(s)):(t(r),t(c),n())}const a=l("#_cb_use_global_settings"),r=l("#_cb_allow_lockdays_in_range"),c=l("#_cb_count_lockdays_in_range"),s=l("#_cb_count_lockdays_maximum");n(),c.change(function(){n()}),o(),r.change(function(){o()});i(),a.change(function(){i()})})}(jQuery),function(i){"use strict";i(function(){var e=i("#cmb2-metabox-cb_map-custom-fields");function t(e,t){function n(){i.each(t,function(){i(this).parents(".cmb-row").show()}),""===o.value&&i.each(t,function(){i(this).parents(".cmb-row").hide()})}const o=document.querySelector(e);n();new MutationObserver(function(e){e.forEach(function(e){"value"===e.attributeName&&n()})}).observe(o,{attributes:!0,childList:!1,subtree:!1})}i("#shortcode-field").find(".button").on("click",function(){var n,e;n=i("#shortcode-field"),e=i(n).find("code")[0].innerText,navigator.clipboard.writeText(e).then(function(){let e=i(n).find(".button"),t=e.text();e.text("✓"),e.disabled=!0,setTimeout(function(){e.text(t),e.disabled=!1},2e3)})}),e.length&&(t("#custom_marker_media",[i("#marker_icon_width"),i("#marker_icon_height"),i("#marker_icon_anchor_x"),i("#marker_icon_anchor_y")]),t("#custom_marker_cluster_media",[i("#marker_cluster_icon_width"),i("#marker_cluster_icon_height")]),t("#marker_item_draft_media",[i("#marker_item_draft_icon_width"),i("#marker_item_draft_icon_height"),i("#marker_item_draft_icon_anchor_x"),i("#marker_item_draft_icon_anchor_y")]))})}(jQuery),function(n){"use strict";n(function(){n("#orphans-migration-start").on("click",function(e){e.preventDefault(),n("#orphans-migration-in-progress").show();e=n(".post-checkboxes:checkbox:checked");let t=[];e.each(function(){t.push(n(this).val())});e=t;n.post(cb_ajax_orphaned_booking_migration.ajax_url,{_ajax_nonce:cb_ajax_orphaned_booking_migration.nonce,action:"cb_orphaned_booking_migration",data:e}).done(function(e){e.success?(n("#orphans-migration-in-progress").hide(),n("#orphans-migration-done").show(),n("#orphans-migration-done span").text(e.message),t.forEach(function(e){n("#row-booking-"+e).remove()})):(n("#orphans-migration-in-progress").hide(),n("#orphans-migration-failed").show(),n("#orphans-migration-failed span").text(e.message))})})})}(jQuery),function(o){"use strict";o(function(){0==o("#upgrade-fields").length&&o(".cmb2-id-upgrade-header").hide(),o("#cmb2-metabox-migration #run-upgrade").on("click",function(e){e.preventDefault(),o("#upgrade-in-progress").show(),o("#run-upgrade").hide();const t=e=>{o.post(cb_ajax_run_upgrade.ajax_url,{_ajax_nonce:cb_ajax_run_upgrade.nonce,action:"cb_run_upgrade",data:e},function(e){e.success?(o("#upgrade-in-progress").hide(),o("#upgrade-done").show()):t(e)})};t({progress:{task:0,page:1}})}),o("#cmb2-metabox-migration #migration-start").on("click",function(e){e.preventDefault(),o("#migration-state").show(),o("#migration-in-progress").show();const t=e=>{o.post(cb_ajax_start_migration.ajax_url,{_ajax_nonce:cb_ajax_start_migration.nonce,action:"cb_start_migration",data:e,geodata:o("#get-geo-locations").is(":checked")},function(e){let n=!0;o.each(e,function(e,t){o("#"+e+"-index").text(t.index),o("#"+e+"-count").text(t.count),"0"==t.complete&&(n=!1)}),n?(o("#migration-in-progress").hide(),o("#migration-done").show()):t(e)})};t(!1)}),o("#cmb2-metabox-migration #booking-update-start").on("click",function(e){e.preventDefault(),o("#booking-migration-in-progress").show(),o.post(cb_ajax_start_migration.ajax_url,{_ajax_nonce:cb_ajax_start_migration.nonce,action:"cb_start_booking_migration"}).done(function(){o("#booking-migration-in-progress").hide(),o("#booking-migration-done").show()}).fail(function(){o("#booking-migration-in-progress").hide(),o("#booking-migration-failed").show()})})})}(jQuery),function(t){"use strict";t(function(){const e=t("input[name=post_type][value=cb_restriction]").parent("form").find("#cb_restriction-custom-fields");e.find("input, select, textarea").on("keyup change paste",function(){e.find("input[name=restriction-send]").prop("disabled",!0)})})}(jQuery),function(o){"use strict";o(function(){if(o("#templates").length){const t=o("#emailtemplates_mail-booking_ics_attach");const n=[o("#emailtemplates_mail-booking_ics_event-title"),o("#emailtemplates_mail-booking_ics_event-description")],e=function(){var e;e=n,o.each(e,function(){o(this).parents(".cmb-row").show()}),t.prop("checked")||(e=n,o.each(e,function(){o(this).parents(".cmb-row").hide()}),t.prop("checked",!1))};e(),t.click(function(){e()})}})}(jQuery),function(X){"use strict";X(function(){const M=function(t,e){var n=[];return jQuery.grep(e,function(e){-1==jQuery.inArray(e,t)&&n.push(e)}),n},i=function(e){X.each(e,function(){X(this).parents(".cmb-row").hide()})},a=function(e){X.each(e,function(){X(this).parents(".cmb-row").show()})};var e=X("#cmb2-metabox-cb_timeframe-custom-fields");const n=X("#timeframe-repetition"),o=X("#location-select"),r=X("#item-select");if(e.length){const n=X("#timeframe-repetition"),s=X("#type"),l=X("#grid"),d=X("#weekdays1");var e=X("#start-time"),t=X("#end-time"),c=X("#title-timeframe-rep-config");const u=X("#repetition-start"),f=X("#repetition-end"),h=X("#full-day"),m=X("#title-timeframe-booking-codes"),p=X("#show-booking-codes"),g=X("#create-booking-codes");var F=X("#booking-codes-download"),B=X("#booking-codes-list"),O=X("#email-booking-codes-list"),U=X("#cron-email-booking-code");const _=X("#timeframe-bookingcodes-sendall"),Y=X("#email-booking-codes-list-all"),$=X("#email-booking-codes-list-current"),q=X("#email-booking-codes-list-next"),b=X(".cmb2-id-location-id"),E=X(".cmb2-id-location-id-list"),T=X(".cmb2-id-item-id"),v=X(".cmb2-id-item-id-list"),w=X(".cmb2-id-location-category-ids"),A=X(".cmb2-id-item-category-ids"),k=X(".cmb2-id--cmb2-holiday");X("#timeframe_manual_date");const x=X("#cmb2_multiselect_datepicker"),R=X(".cmb2-id-timeframe-manual-date");var C=X("#timeframe-max-days"),W=X("#timeframe-advance-booking-days"),P=X("#booking-startday-offset"),Q=X("#title-bookings-config"),K=X("#allowed_user_roles");const I=[c,h,e,t,d,u,f,l],S=[h,e,t,l,u,f],J=[l,e,t],G=[g,B,F,p,O,U],N=[p,B,F,O,U];c=X("input[name=post_type][value=cb_timeframe]").parent("form");const y=[C,W,P,K,Q],H=()=>{var e,t;"3"==s.val()&&((t=T.find("option:selected")).prop("value")&&((e=v.find(`input[value=${t.prop("value")}]`))&&e.prop("checked",!0),t.prop("selected",!1)),(e=b.find("option:selected")).prop("value"))&&((t=E.find(`input[value=${e.prop("value")}]`))&&t.prop("checked",!0),e.prop("selected",!1))},V=(H(),function(){var e=X("option:selected",s).val(),t=X("option:selected",n).val();"2"===e?(a(y),a(m),k.hide()):(i(y),i(m),"3"==e&&"manual"==t?k.show():k.hide()),"3"==e?(r.show(),o.show(),H()):(r.hide(),o.hide())}),L=(V(),s.change(function(){V(),j(),L()}),function(){var e;"3"==X("option:selected",s).val()?(b.hide(),0==(e=X("option:selected",o).val())?(E.show(),w.hide()):1==e?(w.show(),E.hide()):2==e&&(E.hide(),w.hide())):(b.show(),E.hide(),w.hide())}),j=(L(),o.change(function(){L()}),function(){var e;"3"==X("option:selected",s).val()?(T.hide(),0==(e=X("option:selected",r).val())?(v.show(),A.hide()):1==e?(A.show(),v.hide()):2==e&&(v.hide(),A.hide())):(T.show(),v.hide(),A.hide())}),D=(j(),r.change(function(){j()}),function(){X("option:selected",n).val();(h.prop("checked")?(l.prop("selected",!1),i):a)(J)}),Z=(D(),h.change(function(){D()}),function(){var e=X("option:selected",n).val(),t=X("option:selected",s).val();e?("norep"==e?(a(S),i(M(S,I))):(a(I),i(M(I,S))),"manual"===e?(R.show(),x.show(),i(u),i(f),"3"==t?k.show():k.hide()):(R.hide(),x.hide(),a(u),a(f)),"w"===e?d.parents(".cmb-row").show():(d.parents(".cmb-row").hide(),t=X("input[name*=weekdays]"),X.each(t,function(){X(this).prop("checked",!1)})),D()):(i(S),i(I))}),z=(Z(),n.change(function(){Z()}),function(){var e=h.prop("checked"),t=s.val(),n=u.val(),o=f.val();i(G),n&&e&&"2"===t&&(a(G),g.prop("checked")?a(N):(i(N),p.prop("checked",!1)),o?_.show():_.hide())});z(),c.find("input, select, textarea").on("keyup change paste",function(){Y.addClass("disabled"),$.addClass("disabled"),q.addClass("disabled")});e=[u,f,h,s,g];X.each(e,function(e,t){t.change(function(){z()})})}})}(jQuery),function(e){"use strict";e(function(){e(document).tooltip()})}(jQuery),function(e,t){var n,o;"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):(e="undefined"!=typeof globalThis?globalThis:e||self,n=e.feiertagejs,o=e.feiertagejs={},t(o),o.noConflict=function(){return e.feiertagejs=n,o})}(this,function(e){"use strict";const a=["NEUJAHRSTAG","HEILIGEDREIKOENIGE","KARFREITAG","OSTERSONNTAG","OSTERMONTAG","TAG_DER_ARBEIT","CHRISTIHIMMELFAHRT","MARIAHIMMELFAHRT","PFINGSTSONNTAG","PFINGSTMONTAG","FRONLEICHNAM","DEUTSCHEEINHEIT","REFORMATIONSTAG","ALLERHEILIGEN","BUBETAG","ERSTERWEIHNACHTSFEIERTAG","ZWEITERWEIHNACHTSFEIERTAG","WELTKINDERTAG","WELTFRAUENTAG","AUGSBURGER_FRIEDENSFEST"],t=["BW","BY","BE","BB","HB","HE","HH","MV","NI","NW","RP","SL","SN","ST","SH","TH","BUND","AUGSBURG","ALL"];let n="de";const r={de:{NEUJAHRSTAG:"Neujahrstag",HEILIGEDREIKOENIGE:"Heilige Drei Könige",KARFREITAG:"Karfreitag",OSTERSONNTAG:"Ostersonntag",OSTERMONTAG:"Ostermontag",TAG_DER_ARBEIT:"Tag der Arbeit",CHRISTIHIMMELFAHRT:"Christi Himmelfahrt",PFINGSTSONNTAG:"Pfingstsonntag",PFINGSTMONTAG:"Pfingstmontag",FRONLEICHNAM:"Fronleichnam",MARIAHIMMELFAHRT:"Mariä Himmelfahrt",DEUTSCHEEINHEIT:"Tag der Deutschen Einheit",REFORMATIONSTAG:"Reformationstag",ALLERHEILIGEN:"Allerheiligen",BUBETAG:"Buß- und Bettag",ERSTERWEIHNACHTSFEIERTAG:"1. Weihnachtstag",ZWEITERWEIHNACHTSFEIERTAG:"2. Weihnachtstag",WELTKINDERTAG:"Weltkindertag",WELTFRAUENTAG:"Weltfrauentag",AUGSBURGER_FRIEDENSFEST:"Augsburger Friedensfest"}};function o(e,t){i(t);var n=e.getFullYear(),e=f(e);return-1!==function(e,t){e=c(e,t);return e.map(e=>f(e.date))}(n,t).indexOf(e)}function i(e){if(null==e)throw new Error("Region must not be undefined or null");if(-1===t.indexOf(e))throw new Error(`Invalid region: ${e}! Must be one of `+t.toString())}function c(e,t){var n=function(e){var t=Math.floor(e/100),n=e-19*Math.floor(e/19),o=Math.floor((t-17)/25);o=t-Math.floor(t/4)-Math.floor((t-o)/3)+19*n+15,o=(o-=30*Math.floor(o/30))-Math.floor(o/28)*(1-Math.floor(o/28)*Math.floor(29/(1+o))*Math.floor((21-n)/11)),n=e+Math.floor(e/4)+o+2-t+Math.floor(t/4);n-=7*Math.floor(n/7);t=o-n,o=3+Math.floor((40+t)/44),n=28+t-31*Math.floor(o/4);return new Date(e,o-1,n)}(e),o=l(new Date(n.getTime()),-2),i=l(new Date(n.getTime()),1),a=l(new Date(n.getTime()),39),r=l(new Date(n.getTime()),49),c=l(new Date(n.getTime()),50),s=[...[u("NEUJAHRSTAG",d(s=e,1,1)),u("TAG_DER_ARBEIT",d(s,5,1)),u("DEUTSCHEEINHEIT",d(s,10,3)),u("ERSTERWEIHNACHTSFEIERTAG",d(s,12,25)),u("ZWEITERWEIHNACHTSFEIERTAG",d(s,12,26))],u("KARFREITAG",o),u("OSTERMONTAG",i),u("CHRISTIHIMMELFAHRT",a),u("PFINGSTMONTAG",c)];return o=e,i=s,"BW"!==(a=t)&&"BY"!==a&&"AUGSBURG"!==a&&"ST"!==a&&"ALL"!==a||i.push(u("HEILIGEDREIKOENIGE",d(o,1,6))),c=n,a=r,i=s,"BB"!==(o=t)&&"ALL"!==o||i.push(u("OSTERSONNTAG",c),u("PFINGSTSONNTAG",a)),r=n,o=s,"BW"!==(i=t)&&"BY"!==i&&"AUGSBURG"!==i&&"HE"!==i&&"NW"!==i&&"RP"!==i&&"SL"!==i&&"ALL"!==i||(i=l(new Date(r.getTime()),60),o.push(u("FRONLEICHNAM",i))),c=e,a=s,"SL"!==(n=t)&&"BY"!==n&&"AUGSBURG"!==n&&"ALL"!==n||a.push(u("MARIAHIMMELFAHRT",d(c,8,15))),r=t,o=s,2017!==(i=e)&&"NI"!==r&&"BB"!==r&&"HB"!==r&&"HH"!==r&&"MV"!==r&&"SN"!==r&&"ST"!==r&&"TH"!==r&&"SH"!==r&&"ALL"!==r||o.push(u("REFORMATIONSTAG",d(i,10,31))),n=e,a=s,"BW"!==(c=t)&&"BY"!==c&&"AUGSBURG"!==c&&"NW"!==c&&"RP"!==c&&"SL"!==c&&"ALL"!==c||a.push(u("ALLERHEILIGEN",d(n,11,1))),r=e,o=s,"SN"!==(i=t)&&"ALL"!==i||(i=function(e){e=new Date(e,11,25,12,0,0);let t=e.getDay()%7;0===t&&(t=7);var n=t+32;e=new Date(e.getTime());return l(e,-n)}(r),o.push(u("BUBETAG",d(i.getUTCFullYear(),i.getUTCMonth()+1,i.getUTCDate())))),c=t,a=s,2019<=(n=e)&&("TH"===c||"ALL"===c)&&a.push(u("WELTKINDERTAG",d(n,9,20))),r=t,o=s,(i=e)<=2018||("BE"!==r&&"ALL"!==r||o.push(u("WELTFRAUENTAG",d(i,3,8))),"MV"===r&&2023<=i&&o.push(u("WELTFRAUENTAG",d(i,3,8)))),c=e,a=s,"AUGSBURG"===t&&a.push(u("AUGSBURGER_FRIEDENSFEST",d(c,8,8))),s.sort((e,t)=>e.date.getTime()-t.date.getTime())}function l(e,t){var n=new Date(e);return n.setDate(e.getDate()+t),n}function d(e,t,n){return new Date(e,t-1,n)}function u(e,t){return{name:e,date:t,dateString:s(t),trans(e=n){return console.warn('FeiertageJs: You are using "Holiday.trans() method. This will be replaced in the next major version with translate()"'),this.translate(e)},translate(e=n){return null==e?void 0:r[e][this.name]},getNormalizedDate(){return f(this.date)},equals(e){e=s(e);return this.dateString===e}}}function s(e){e=new Date(e.getTime()-60*e.getTimezoneOffset()*1e3);return e.setUTCHours(0,0,0,0),e.toISOString().slice(0,10)}function f(e){e=new Date(e);return e.setHours(0,0,0,0),e.getTime()}e.addTranslation=function(e,t){var e=e.toLowerCase(),n=r.de;let o=!1;for(const i of a)t[i]||(o=!0,t[i]=n[i]);o&&console.warn("[feiertagejs] addTranslation: you did not add all holidays in your translation! Took German as fallback"),r[e]=t},e.getHolidayByDate=function(t,e="ALL"){return i(e),c(t.getFullYear(),e).find(e=>e.equals(t))},e.getHolidays=function(e,t){let n;return n="string"==typeof e?parseInt(e,10):e,i(t),c(n,t)},e.getLanguage=function(){return n},e.isHoliday=o,e.isSpecificHoliday=function(t,e,n="ALL"){i(n);var o=e;if(null==o)throw new TypeError("holidayName must not be null or undefined");if(-1===a.indexOf(o))throw new Error(`feiertage.js: invalid holiday type "${o}"! Must be one of `+a.toString());return!!(o=c(t.getFullYear(),n).find(e=>e.equals(t)))&&o.name===e},e.isSunOrHoliday=function(e,t){return i(t),0===e.getDay()||o(e,t)},e.setLanguage=function(e){var t=e.toLowerCase();if(!r[t])throw new TypeError(`[feiertagejs] tried to set language to ${t} but the translation is missing. Please use addTranslation(isoCode,object) first`);n=e}}); \ No newline at end of file +!function(d){"use strict";d(function(){let n=d("#full-day"),t=d("#repetition-start_time"),o=d("#repetition-end_time"),i=!1,a=d("#item-id"),r=d("#location-id"),c=d("#repetition-start_date"),s=d("#_cb_bookingcode");if(![n,t,o,a,r,c,s].every(e=>1===e.length))return;n.on("change",function(e){n.is(":checked")?(t.val("00:00"),o.val("23:59"),t.hide(),o.hide()):(t.show(),o.show())}),n.trigger("change"),a.on("change",function(e){var t={itemID:a.val()};d.post(cb_ajax_get_bookable_location.ajax_url,{_ajax_nonce:cb_ajax_get_bookable_location.nonce,action:"cb_get_bookable_location",data:t},function(e){e.success&&(r.val(e.locationID),n.prop("checked",e.fullDay),n.trigger("change"))}).then(()=>{l()})}),a.trigger("change");const l=()=>{var e;n.is(":checked")&&(e={itemID:a.val(),locationID:r.val(),startDate:c.val()},d.post(cb_ajax_get_booking_code.ajax_url,{_ajax_nonce:cb_ajax_get_booking_code.nonce,action:"cb_get_booking_code",data:e},function(e){e.success?(s.val(e.bookingCode),i=!1):i||s.val("")}))};s.on("keyup",function(e){i=!0}),c.on("change",function(e){l()}),n.on("change",function(e){l()})})}(jQuery),function(k){"use strict";k(function(){function E(){var t=k("#"+T+"_repeat");t.on("cmb2_add_row cmb2_remove_row cmb2_shift_rows_complete",function(){E()});for(let e=0;e{if(t.name==b){if(a.text(t.description),i.width(300),r.show(),c.show(),s.show(),a.show(),t.hasOwnProperty("params")&&0",{value:e,text:n[e]}));_.width(150);var o=cb_applied_booking_rules.filter(e=>e.name==t.name);1===o.length&&_.val(o[0].appliedSelectParam)}else p.hide()}})}}function i(){var t=k("#"+T+"_repeat");t.on("cmb2_add_row cmb2_remove_row cmb2_shift_rows_complete",function(){i()});for(let e=0;e{m.post(cb_ajax_export_timeframes.ajax_url,{_ajax_nonce:cb_ajax_export_timeframes.nonce,action:"cb_export_timeframes",data:e},function(e){var t,n,o;e.success?(d.show(),h.text(e.message),s.hide(),t=new Blob([e.csv]),n=e.filename,(o=document.createElement("a")).href=URL.createObjectURL(t),o.download=n,o.click()):e.error?(u.show(),f.text(e.message),s.hide()):(l.text(e.progress),i(e))})};i(e)})})}(jQuery),function(a){"use strict";a(function(){var e=a("#holiday_load_btn");const o=a("#timeframe_manual_date");var t=a("#cmb2_multiselect_datepicker"),i=e=>{var t=e.getDate(),n=e.getMonth()+1,t=t<=9?"0"+t:t,n=n<=9?"0"+n:n,e=e.getFullYear()+"-"+n+"-"+t;0{e=new Date(e.date);i(e)})})})}(jQuery),function(l){"use strict";l(function(){function e(e){l.each(e,function(){l(this).parents(".cmb-row").hide()})}function t(e){l.each(e,function(){l(this).parents(".cmb-row").show()})}function n(){(c.prop("checked")?t:e)(s)}function o(){r.prop("checked")?(t(c),n()):(e(c),e(s))}function i(){a.prop("checked")?(e(r),e(c),e(s)):(t(r),t(c),n())}const a=l("#_cb_use_global_settings"),r=l("#_cb_allow_lockdays_in_range"),c=l("#_cb_count_lockdays_in_range"),s=l("#_cb_count_lockdays_maximum");n(),c.change(function(){n()}),o(),r.change(function(){o()});i(),a.change(function(){i()})})}(jQuery),function(i){"use strict";i(function(){var e=i("#cmb2-metabox-cb_map-custom-fields");function t(e,t){function n(){i.each(t,function(){i(this).parents(".cmb-row").show()}),""===o.value&&i.each(t,function(){i(this).parents(".cmb-row").hide()})}const o=document.querySelector(e);n();new MutationObserver(function(e){e.forEach(function(e){"value"===e.attributeName&&n()})}).observe(o,{attributes:!0,childList:!1,subtree:!1})}i("#shortcode-field").find(".button").on("click",function(){var n,e;n=i("#shortcode-field"),e=i(n).find("code")[0].innerText,navigator.clipboard.writeText(e).then(function(){let e=i(n).find(".button"),t=e.text();e.text("✓"),e.disabled=!0,setTimeout(function(){e.text(t),e.disabled=!1},2e3)})}),e.length&&(t("#custom_marker_media",[i("#marker_icon_width"),i("#marker_icon_height"),i("#marker_icon_anchor_x"),i("#marker_icon_anchor_y")]),t("#custom_marker_cluster_media",[i("#marker_cluster_icon_width"),i("#marker_cluster_icon_height")]),t("#marker_item_draft_media",[i("#marker_item_draft_icon_width"),i("#marker_item_draft_icon_height"),i("#marker_item_draft_icon_anchor_x"),i("#marker_item_draft_icon_anchor_y")]))})}(jQuery),function(n){"use strict";n(function(){n("#orphans-migration-start").on("click",function(e){e.preventDefault(),n("#orphans-migration-in-progress").show();e=n(".post-checkboxes:checkbox:checked");let t=[];e.each(function(){t.push(n(this).val())});e=t;n.post(cb_ajax_orphaned_booking_migration.ajax_url,{_ajax_nonce:cb_ajax_orphaned_booking_migration.nonce,action:"cb_orphaned_booking_migration",data:e}).done(function(e){e.success?(n("#orphans-migration-in-progress").hide(),n("#orphans-migration-done").show(),n("#orphans-migration-done span").text(e.message),t.forEach(function(e){n("#row-booking-"+e).remove()})):(n("#orphans-migration-in-progress").hide(),n("#orphans-migration-failed").show(),n("#orphans-migration-failed span").text(e.message))})})})}(jQuery),function(o){"use strict";o(function(){0==o("#upgrade-fields").length&&o(".cmb2-id-upgrade-header").hide(),o("#cmb2-metabox-migration #run-upgrade").on("click",function(e){e.preventDefault(),o("#upgrade-in-progress").show(),o("#run-upgrade").hide();const t=e=>{o.post(cb_ajax_run_upgrade.ajax_url,{_ajax_nonce:cb_ajax_run_upgrade.nonce,action:"cb_run_upgrade",data:e},function(e){e.success?(o("#upgrade-in-progress").hide(),o("#upgrade-done").show()):t(e)})};t({progress:{task:0,page:1}})}),o("#cmb2-metabox-migration #migration-start").on("click",function(e){e.preventDefault(),o("#migration-state").show(),o("#migration-in-progress").show();const t=e=>{o.post(cb_ajax_start_migration.ajax_url,{_ajax_nonce:cb_ajax_start_migration.nonce,action:"cb_start_migration",data:e,geodata:o("#get-geo-locations").is(":checked")},function(e){let n=!0;o.each(e,function(e,t){o("#"+e+"-index").text(t.index),o("#"+e+"-count").text(t.count),"0"==t.complete&&(n=!1)}),n?(o("#migration-in-progress").hide(),o("#migration-done").show()):t(e)})};t(!1)}),o("#cmb2-metabox-migration #booking-update-start").on("click",function(e){e.preventDefault(),o("#booking-migration-in-progress").show(),o.post(cb_ajax_start_migration.ajax_url,{_ajax_nonce:cb_ajax_start_migration.nonce,action:"cb_start_booking_migration"}).done(function(){o("#booking-migration-in-progress").hide(),o("#booking-migration-done").show()}).fail(function(){o("#booking-migration-in-progress").hide(),o("#booking-migration-failed").show()})})})}(jQuery),function(t){"use strict";t(function(){const e=t("input[name=post_type][value=cb_restriction]").parent("form").find("#cb_restriction-custom-fields");e.find("input, select, textarea").on("keyup change paste",function(){e.find("input[name=restriction-send]").prop("disabled",!0)})})}(jQuery),function(o){"use strict";o(function(){if(o("#templates").length){const t=o("#emailtemplates_mail-booking_ics_attach");const n=[o("#emailtemplates_mail-booking_ics_event-title"),o("#emailtemplates_mail-booking_ics_event-description")],e=function(){var e;e=n,o.each(e,function(){o(this).parents(".cmb-row").show()}),t.prop("checked")||(e=n,o.each(e,function(){o(this).parents(".cmb-row").hide()}),t.prop("checked",!1))};e(),t.click(function(){e()})}})}(jQuery),function(X){"use strict";X(function(){const M=function(t,e){var n=[];return jQuery.grep(e,function(e){-1==jQuery.inArray(e,t)&&n.push(e)}),n},i=function(e){X.each(e,function(){X(this).parents(".cmb-row").hide()})},a=function(e){X.each(e,function(){X(this).parents(".cmb-row").show()})};var e=X("#cmb2-metabox-cb_timeframe-custom-fields");const n=X("#timeframe-repetition"),o=X("#location-select"),r=X("#item-select");if(e.length){const n=X("#timeframe-repetition"),s=X("#type"),l=X("#grid"),d=X("#weekdays1");var e=X("#start-time"),t=X("#end-time"),c=X("#title-timeframe-rep-config");const u=X("#repetition-start"),f=X("#repetition-end"),h=X("#full-day"),m=X("#title-timeframe-booking-codes"),p=X("#show-booking-codes"),g=X("#create-booking-codes");var F=X("#booking-codes-download"),B=X("#booking-codes-list"),O=X("#email-booking-codes-list"),U=X("#cron-email-booking-code");const _=X("#timeframe-bookingcodes-sendall"),Y=X("#email-booking-codes-list-all"),$=X("#email-booking-codes-list-current"),q=X("#email-booking-codes-list-next"),b=X(".cmb2-id-location-id"),E=X(".cmb2-id-location-id-list"),T=X(".cmb2-id-item-id"),v=X(".cmb2-id-item-id-list"),w=X(".cmb2-id-location-category-ids"),A=X(".cmb2-id-item-category-ids"),k=X(".cmb2-id--cmb2-holiday");X("#timeframe_manual_date");const x=X("#cmb2_multiselect_datepicker"),R=X(".cmb2-id-timeframe-manual-date");var C=X("#timeframe-max-days"),W=X("#timeframe-advance-booking-days"),P=X("#booking-startday-offset"),Q=X("#title-bookings-config"),K=X("#allowed_user_roles");const I=[c,h,e,t,d,u,f,l],S=[h,e,t,l,u,f],J=[l,e,t],y=[g,B,F,p,O,U],G=[p,B,F,O,U];c=X("input[name=post_type][value=cb_timeframe]").parent("form");const N=[C,W,P,K,Q],H=()=>{var e,t;"3"==s.val()&&((t=T.find("option:selected")).prop("value")&&((e=v.find(`input[value=${t.prop("value")}]`))&&e.prop("checked",!0),t.prop("selected",!1)),(e=b.find("option:selected")).prop("value"))&&((t=E.find(`input[value=${e.prop("value")}]`))&&t.prop("checked",!0),e.prop("selected",!1))},V=(H(),function(){var e=X("option:selected",s).val(),t=X("option:selected",n).val();"2"===e?(a(N),a(m),k.hide()):(i(N),i(m),"3"==e&&"manual"==t?k.show():k.hide()),"3"==e?(r.show(),o.show(),H()):(r.hide(),o.hide())}),L=(V(),s.change(function(){V(),j(),L()}),function(){var e;"3"==X("option:selected",s).val()?(b.hide(),0==(e=X("option:selected",o).val())?(E.show(),w.hide()):1==e?(w.show(),E.hide()):2==e&&(E.hide(),w.hide())):(b.show(),E.hide(),w.hide())}),j=(L(),o.change(function(){L()}),function(){var e;"3"==X("option:selected",s).val()?(T.hide(),0==(e=X("option:selected",r).val())?(v.show(),A.hide()):1==e?(A.show(),v.hide()):2==e&&(v.hide(),A.hide())):(T.show(),v.hide(),A.hide())}),D=(j(),r.change(function(){j()}),function(){X("option:selected",n).val();(h.prop("checked")?(l.prop("selected",!1),i):a)(J)}),Z=(D(),h.change(function(){D()}),function(){var e=X("option:selected",n).val(),t=X("option:selected",s).val();e?("norep"==e?(a(S),i(M(S,I))):(a(I),i(M(I,S))),"manual"===e?(R.show(),x.show(),i(u),i(f),"3"==t?k.show():k.hide()):(R.hide(),x.hide(),a(u),a(f)),"w"===e?d.parents(".cmb-row").show():(d.parents(".cmb-row").hide(),t=X("input[name*=weekdays]"),X.each(t,function(){X(this).prop("checked",!1)})),D()):(i(S),i(I))}),z=(Z(),n.change(function(){Z()}),function(){var e=h.prop("checked"),t=s.val(),n=u.val(),o=f.val();i(y),n&&e&&"2"===t&&(a(y),g.prop("checked")?a(G):(i(G),p.prop("checked",!1)),o?_.show():_.hide())});z(),c.find("input, select, textarea").on("keyup change paste",function(){Y.addClass("disabled"),$.addClass("disabled"),q.addClass("disabled")});e=[u,f,h,s,g];X.each(e,function(e,t){t.change(function(){z()})})}})}(jQuery),function(e){"use strict";e(function(){e(document).tooltip()})}(jQuery),function(e,t){var n,o;"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):(e="undefined"!=typeof globalThis?globalThis:e||self,n=e.feiertagejs,o=e.feiertagejs={},t(o),o.noConflict=function(){return e.feiertagejs=n,o})}(this,function(e){"use strict";const a=["NEUJAHRSTAG","HEILIGEDREIKOENIGE","KARFREITAG","OSTERSONNTAG","OSTERMONTAG","TAG_DER_ARBEIT","CHRISTIHIMMELFAHRT","MARIAHIMMELFAHRT","PFINGSTSONNTAG","PFINGSTMONTAG","FRONLEICHNAM","DEUTSCHEEINHEIT","REFORMATIONSTAG","ALLERHEILIGEN","BUBETAG","ERSTERWEIHNACHTSFEIERTAG","ZWEITERWEIHNACHTSFEIERTAG","WELTKINDERTAG","WELTFRAUENTAG","AUGSBURGER_FRIEDENSFEST"],t=["BW","BY","BE","BB","HB","HE","HH","MV","NI","NW","RP","SL","SN","ST","SH","TH","BUND","AUGSBURG","ALL"];let n="de";const r={de:{NEUJAHRSTAG:"Neujahrstag",HEILIGEDREIKOENIGE:"Heilige Drei Könige",KARFREITAG:"Karfreitag",OSTERSONNTAG:"Ostersonntag",OSTERMONTAG:"Ostermontag",TAG_DER_ARBEIT:"Tag der Arbeit",CHRISTIHIMMELFAHRT:"Christi Himmelfahrt",PFINGSTSONNTAG:"Pfingstsonntag",PFINGSTMONTAG:"Pfingstmontag",FRONLEICHNAM:"Fronleichnam",MARIAHIMMELFAHRT:"Mariä Himmelfahrt",DEUTSCHEEINHEIT:"Tag der Deutschen Einheit",REFORMATIONSTAG:"Reformationstag",ALLERHEILIGEN:"Allerheiligen",BUBETAG:"Buß- und Bettag",ERSTERWEIHNACHTSFEIERTAG:"1. Weihnachtstag",ZWEITERWEIHNACHTSFEIERTAG:"2. Weihnachtstag",WELTKINDERTAG:"Weltkindertag",WELTFRAUENTAG:"Weltfrauentag",AUGSBURGER_FRIEDENSFEST:"Augsburger Friedensfest"}};function o(e,t){i(t);var n=e.getFullYear(),e=f(e);return-1!==function(e,t){e=c(e,t);return e.map(e=>f(e.date))}(n,t).indexOf(e)}function i(e){if(null==e)throw new Error("Region must not be undefined or null");if(-1===t.indexOf(e))throw new Error(`Invalid region: ${e}! Must be one of `+t.toString())}function c(e,t){var n=function(e){var t=Math.floor(e/100),n=e-19*Math.floor(e/19),o=Math.floor((t-17)/25);o=t-Math.floor(t/4)-Math.floor((t-o)/3)+19*n+15,o=(o-=30*Math.floor(o/30))-Math.floor(o/28)*(1-Math.floor(o/28)*Math.floor(29/(1+o))*Math.floor((21-n)/11)),n=e+Math.floor(e/4)+o+2-t+Math.floor(t/4);n-=7*Math.floor(n/7);t=o-n,o=3+Math.floor((40+t)/44),n=28+t-31*Math.floor(o/4);return new Date(e,o-1,n)}(e),o=l(new Date(n.getTime()),-2),i=l(new Date(n.getTime()),1),a=l(new Date(n.getTime()),39),r=l(new Date(n.getTime()),49),c=l(new Date(n.getTime()),50),s=[...[u("NEUJAHRSTAG",d(s=e,1,1)),u("TAG_DER_ARBEIT",d(s,5,1)),u("DEUTSCHEEINHEIT",d(s,10,3)),u("ERSTERWEIHNACHTSFEIERTAG",d(s,12,25)),u("ZWEITERWEIHNACHTSFEIERTAG",d(s,12,26))],u("KARFREITAG",o),u("OSTERMONTAG",i),u("CHRISTIHIMMELFAHRT",a),u("PFINGSTMONTAG",c)];return o=e,i=s,"BW"!==(a=t)&&"BY"!==a&&"AUGSBURG"!==a&&"ST"!==a&&"ALL"!==a||i.push(u("HEILIGEDREIKOENIGE",d(o,1,6))),c=n,a=r,i=s,"BB"!==(o=t)&&"ALL"!==o||i.push(u("OSTERSONNTAG",c),u("PFINGSTSONNTAG",a)),r=n,o=s,"BW"!==(i=t)&&"BY"!==i&&"AUGSBURG"!==i&&"HE"!==i&&"NW"!==i&&"RP"!==i&&"SL"!==i&&"ALL"!==i||(i=l(new Date(r.getTime()),60),o.push(u("FRONLEICHNAM",i))),c=e,a=s,"SL"!==(n=t)&&"BY"!==n&&"AUGSBURG"!==n&&"ALL"!==n||a.push(u("MARIAHIMMELFAHRT",d(c,8,15))),r=t,o=s,2017!==(i=e)&&"NI"!==r&&"BB"!==r&&"HB"!==r&&"HH"!==r&&"MV"!==r&&"SN"!==r&&"ST"!==r&&"TH"!==r&&"SH"!==r&&"ALL"!==r||o.push(u("REFORMATIONSTAG",d(i,10,31))),n=e,a=s,"BW"!==(c=t)&&"BY"!==c&&"AUGSBURG"!==c&&"NW"!==c&&"RP"!==c&&"SL"!==c&&"ALL"!==c||a.push(u("ALLERHEILIGEN",d(n,11,1))),r=e,o=s,"SN"!==(i=t)&&"ALL"!==i||(i=function(e){e=new Date(e,11,25,12,0,0);let t=e.getDay()%7;0===t&&(t=7);var n=t+32;e=new Date(e.getTime());return l(e,-n)}(r),o.push(u("BUBETAG",d(i.getUTCFullYear(),i.getUTCMonth()+1,i.getUTCDate())))),c=t,a=s,2019<=(n=e)&&("TH"===c||"ALL"===c)&&a.push(u("WELTKINDERTAG",d(n,9,20))),r=t,o=s,(i=e)<=2018||("BE"!==r&&"ALL"!==r||o.push(u("WELTFRAUENTAG",d(i,3,8))),"MV"===r&&2023<=i&&o.push(u("WELTFRAUENTAG",d(i,3,8)))),c=e,a=s,"AUGSBURG"===t&&a.push(u("AUGSBURGER_FRIEDENSFEST",d(c,8,8))),s.sort((e,t)=>e.date.getTime()-t.date.getTime())}function l(e,t){var n=new Date(e);return n.setDate(e.getDate()+t),n}function d(e,t,n){return new Date(e,t-1,n)}function u(e,t){return{name:e,date:t,dateString:s(t),trans(e=n){return console.warn('FeiertageJs: You are using "Holiday.trans() method. This will be replaced in the next major version with translate()"'),this.translate(e)},translate(e=n){return null==e?void 0:r[e][this.name]},getNormalizedDate(){return f(this.date)},equals(e){e=s(e);return this.dateString===e}}}function s(e){e=new Date(e.getTime()-60*e.getTimezoneOffset()*1e3);return e.setUTCHours(0,0,0,0),e.toISOString().slice(0,10)}function f(e){e=new Date(e);return e.setHours(0,0,0,0),e.getTime()}e.addTranslation=function(e,t){var e=e.toLowerCase(),n=r.de;let o=!1;for(const i of a)t[i]||(o=!0,t[i]=n[i]);o&&console.warn("[feiertagejs] addTranslation: you did not add all holidays in your translation! Took German as fallback"),r[e]=t},e.getHolidayByDate=function(t,e="ALL"){return i(e),c(t.getFullYear(),e).find(e=>e.equals(t))},e.getHolidays=function(e,t){let n;return n="string"==typeof e?parseInt(e,10):e,i(t),c(n,t)},e.getLanguage=function(){return n},e.isHoliday=o,e.isSpecificHoliday=function(t,e,n="ALL"){i(n);var o=e;if(null==o)throw new TypeError("holidayName must not be null or undefined");if(-1===a.indexOf(o))throw new Error(`feiertage.js: invalid holiday type "${o}"! Must be one of `+a.toString());return!!(o=c(t.getFullYear(),n).find(e=>e.equals(t)))&&o.name===e},e.isSunOrHoliday=function(e,t){return i(t),0===e.getDay()||o(e,t)},e.setLanguage=function(e){var t=e.toLowerCase();if(!r[t])throw new TypeError(`[feiertagejs] tried to set language to ${t} but the translation is missing. Please use addTranslation(isoCode,object) first`);n=e}}); \ No newline at end of file diff --git a/assets/admin/js/src/booking.js b/assets/admin/js/src/booking.js index 950287293..3bb49df00 100644 --- a/assets/admin/js/src/booking.js +++ b/assets/admin/js/src/booking.js @@ -5,6 +5,21 @@ let startTimeInput = $('#repetition-start_time'); let endTimeInput = $('#repetition-end_time'); let preserveManualCode = false; + let itemInput = $('#item-id'); + let locationInput = $('#location-id'); + let startDateInput = $('#repetition-start_date'); + let bookingCodeInput = $('#_cb_bookingcode'); + + // check if this is loaded on right kind of backend page + let allExist = [ + fullDayCheckbox, startTimeInput, endTimeInput, itemInput, locationInput, startDateInput, bookingCodeInput + ].every(domElement => domElement.length === 1); + + if (!allExist) { + // return early to prevent ajax calls with incorrect parameters + return; + } + fullDayCheckbox.on('change', function (event) { if (fullDayCheckbox.is(':checked')) { startTimeInput.val('00:00'); @@ -18,12 +33,6 @@ }); fullDayCheckbox.trigger('change'); - - let itemInput = $('#item-id'); - let locationInput = $('#location-id'); - let startDateInput = $('#repetition-start_date'); - let bookingCodeInput = $('#_cb_bookingcode'); - itemInput.on('change', function (event) { let data = { itemID: itemInput.val(), diff --git a/composer.lock b/composer.lock index 7057f3bd8..722d4df45 100644 --- a/composer.lock +++ b/composer.lock @@ -2893,16 +2893,16 @@ }, { "name": "phpcompatibility/phpcompatibility-wp", - "version": "2.1.5", + "version": "2.1.6", "source": { "type": "git", "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082" + "reference": "80ccb1a7640995edf1b87a4409fa584cd5869469" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082", - "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082", + "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/80ccb1a7640995edf1b87a4409fa584cd5869469", + "reference": "80ccb1a7640995edf1b87a4409fa584cd5869469", "shasum": "" }, "require": { @@ -2959,7 +2959,7 @@ "type": "open_collective" } ], - "time": "2024-04-24T21:37:59+00:00" + "time": "2025-01-16T22:34:19+00:00" }, { "name": "phpcsstandards/phpcsextra", @@ -3177,16 +3177,16 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.1", + "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7" + "reference": "7d08f569e582ade182a375c366cbd896eccadd3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7", - "reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/7d08f569e582ade182a375c366cbd896eccadd3a", + "reference": "7d08f569e582ade182a375c366cbd896eccadd3a", "shasum": "" }, "require": { @@ -3231,7 +3231,7 @@ "type": "github" } ], - "time": "2025-01-05T16:43:48+00:00" + "time": "2025-01-21T14:54:06+00:00" }, { "name": "phpunit/php-code-coverage", @@ -4674,16 +4674,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.10.3", + "version": "3.11.2", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c" + "reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/62d32998e820bddc40f99f8251958aed187a5c9c", - "reference": "62d32998e820bddc40f99f8251958aed187a5c9c", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1368f4a58c3c52114b86b1abe8f4098869cb0079", + "reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079", "shasum": "" }, "require": { @@ -4750,7 +4750,7 @@ "type": "open_collective" } ], - "time": "2024-09-18T10:38:58+00:00" + "time": "2024-12-11T16:04:26+00:00" }, { "name": "szepeviktor/phpstan-wordpress", @@ -4996,13 +4996,13 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { "php": ">=7.4", "ext-json": "*" }, - "platform-dev": {}, - "plugin-api-version": "2.6.0" + "platform-dev": [], + "plugin-api-version": "2.3.0" } diff --git a/includes/Admin.php b/includes/Admin.php index 2780aa553..34922bdf2 100644 --- a/includes/Admin.php +++ b/includes/Admin.php @@ -72,12 +72,11 @@ function commonsbooking_admin() { // Additional info for CMB2 to handle booking rules wp_add_inline_script( 'cb-scripts-admin', -'cb_booking_rules=' . \CommonsBooking\Service\BookingRule::getRulesJSON() . ';' + 'cb_booking_rules=' . \CommonsBooking\Service\BookingRule::getRulesJSON() . ';' . 'cb_applied_booking_rules=' . \CommonsBooking\Service\BookingRuleApplied::getRulesJSON() . ';', ); - - //orphaned bookings migration - re-assign booking when timeframe has changed + // orphaned bookings migration - re-assign booking when timeframe has changed wp_localize_script( 'cb-scripts-admin', 'cb_ajax_orphaned_booking_migration', @@ -98,7 +97,6 @@ function commonsbooking_admin() { ) ); - /** * Ajax - get location for item */ @@ -137,7 +135,7 @@ function commonsbooking_admin() { function commonsbooking_sanitizeHTML( $string ): string { global $allowedposttags; - if ( empty ( $string ) ) { + if ( empty( $string ) ) { return ''; } $allowed_atts = array( @@ -237,7 +235,7 @@ function commonsbooking_filter_from_cmb2( $field_args ) { /** * Only return default value if we don't have a post ID (in the 'post' query variable) * - * @param bool $default On/Off (true/false) + * @param bool $default On/Off (true/false) * @return mixed Returns true or '', the blank default */ function cmb2_set_checkbox_default_for_new_post() { @@ -252,24 +250,22 @@ function cmb2_set_checkbox_default_for_new_post() { * Recursive sanitation for text or array * * @param mixed array_or_string (array|string) - * @param string $sanitize_function name of the sanitziation function, default = sanitize_text_field. You can use any method that accepts a string as parameter + * @param string $sanitize_function name of the sanitziation function, default = sanitize_text_field. You can use any method that accepts a string as parameter * - * See more wordpress sanitization functions: https://developer.wordpress.org/themes/theme-security/data-sanitization-escaping/ + * See more wordpress sanitization functions: https://developer.wordpress.org/themes/theme-security/data-sanitization-escaping/ * * @return array|string */ +function commonsbooking_sanitizeArrayorString( $data, $sanitizeFunction = 'sanitize_text_field' ) { + if ( is_array( $data ) ) { + foreach ( $data as $key => $value ) { + $data[ $key ] = commonsbooking_sanitizeArrayorString( $value, $sanitizeFunction ); + } + } else { + $data = call_user_func( $sanitizeFunction, $data ); + } -function commonsbooking_sanitizeArrayorString( $data, $sanitizeFunction = 'sanitize_text_field' ) { - if ( is_array( $data ) ) { - foreach ( $data as $key => $value ) { - $data[ $key ] = commonsbooking_sanitizeArrayorString( $value, $sanitizeFunction ); - } - } else { - $data = call_user_func( $sanitizeFunction, $data ); - } - - return $data; - + return $data; } @@ -278,28 +274,28 @@ function commonsbooking_sanitizeArrayorString( $data, $sanitizeFunction = 'sanit * only active if DEBUG_LOG is on * * @param mixed $log can be a string, array or object - * @param bool $backtrace if set true the file-path and line of the calling file will be added to the error message + * @param bool $backtrace if set true the file-path and line of the calling file will be added to the error message * * @return void */ function commonsbooking_write_log( $log, $backtrace = true ) { - if ( ! WP_DEBUG_LOG ) { - return; - } + if ( ! WP_DEBUG_LOG ) { + return; + } - if ( is_array( $log ) || is_object( $log ) ) { + if ( is_array( $log ) || is_object( $log ) ) { $logmessage = ( print_r( $log, true ) ); } else { - $logmessage = $log ; + $logmessage = $log; } if ( $backtrace ) { - $bt = debug_backtrace(); - $file = $bt[0]['file']; - $line = $bt[0]['line']; - $logmessage = $file . ':' . $line . ' ' . $logmessage; + $bt = debug_backtrace(); + $file = $bt[0]['file']; + $line = $bt[0]['line']; + $logmessage = $file . ':' . $line . ' ' . $logmessage; } error_log( $logmessage ); -} \ No newline at end of file +} diff --git a/includes/OptionsArray.php b/includes/OptionsArray.php index 53159de0d..50eef0e02 100644 --- a/includes/OptionsArray.php +++ b/includes/OptionsArray.php @@ -14,13 +14,13 @@ use CommonsBooking\Wordpress\CustomPostType\Timeframe; // We need static types, because german month names don't work for datepicker -$dateFormat = "d/m/Y"; +$dateFormat = 'd/m/Y'; if ( strpos( get_locale(), 'de_' ) !== false ) { - $dateFormat = "d.m.Y"; + $dateFormat = 'd.m.Y'; } if ( strpos( get_locale(), 'en_' ) !== false ) { - $dateFormat = "m/d/Y"; + $dateFormat = 'm/d/Y'; } @@ -31,7 +31,6 @@ * * Tabs -> field "groups" -> fields * Notice: options are stored in database wp_options with prefix 'commonsboking_options_' followed by the tab id (e.g. commonsbooking_options_main) - * */ return array( @@ -47,7 +46,10 @@ 'id' => 'welcome', 'desc' => // translators: %s = version number - sprintf( commonsbooking_sanitizeHTML( __( 'You are using CommonsBooking Version %s + sprintf( + commonsbooking_sanitizeHTML( + __( + 'You are using CommonsBooking Version %s

How to start

To get startet visit our tutorials and documentation on https://commonsbooking.org/dokumentation

@@ -56,11 +58,15 @@

Ask your questions or send us your bug reports here https://commonsbooking.org/kontakt/

Contribute

- The future of this plugin depends on your support. You can support us by make a donation on our website: wielebenwir' - , 'commonsbooking' ) ), commonsbooking_sanitizeHTML( COMMONSBOOKING_VERSION ) ), - 'fields' => array() - ) - ) + The future of this plugin depends on your support. You can support us by make a donation on our website: wielebenwir', + 'commonsbooking' + ) + ), + commonsbooking_sanitizeHTML( COMMONSBOOKING_VERSION ) + ), + 'fields' => array(), + ), + ), ), /* Tab: main end*/ @@ -76,18 +82,27 @@ 'id' => 'posttypes', // tranlsators: %s = admin url options page 'desc' => - commonsbooking_sanitizeHTML( __( - 'Customize names & slugs. You can set an individual slug for items and locations to create individual permalinks.
Notice: If the new settings do not work directly (you will get a 404 page error on frontend pages), you must click on the Settings -> Permalinks page after saving these settings to refresh the Wordpress permalink settings.' - , 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( + __( + 'Customize names & slugs. You can set an individual slug for items and locations to create individual permalinks.
Notice: If the new settings do not work directly (you will get a 404 page error on frontend pages), you must click on the Settings -> Permalinks page after saving these settings to refresh the Wordpress permalink settings.', + 'commonsbooking' + ) + ), 'fields' => array( array( 'name' => commonsbooking_sanitizeHTML( __( 'Items slug', 'commonsbooking' ) ), 'id' => 'posttypes_items-slug', // translators: %s = example url (like website.com/cb-items/) 'description' => - sprintf( commonsbooking_sanitizeHTML( __( - 'The slug for article detail page. Type in the slug without slashes. Example: cb_item or article. The url for the items detail will be like %s', - 'commonsbooking' ) ), network_site_url( '/cb_item/' ) ), + sprintf( + commonsbooking_sanitizeHTML( + __( + 'The slug for article detail page. Type in the slug without slashes. Example: cb_item or article. The url for the items detail will be like %s', + 'commonsbooking' + ) + ), + network_site_url( '/cb_item/' ) + ), 'type' => 'text', 'default' => Item::$postType, ), @@ -96,9 +111,15 @@ 'id' => 'posttypes_locations-slug', // translators: %s = example url (like website.com/cb-locations/) 'description' => - sprintf( commonsbooking_sanitizeHTML( __( - 'The slug for location detail page. Type in the slug without slashes. Example: cb_location or location. The url for the items detail will be like %s', - 'commonsbooking' ) ), network_site_url( '/cb_location/' ) ), + sprintf( + commonsbooking_sanitizeHTML( + __( + 'The slug for location detail page. Type in the slug without slashes. Example: cb_location or location. The url for the items detail will be like %s', + 'commonsbooking' + ) + ), + network_site_url( '/cb_location/' ) + ), 'type' => 'text', 'default' => Location::$postType, ), @@ -107,16 +128,22 @@ 'id' => 'bookings_page', // translators: %s = example url (like website.com/cb-locations/) 'description' => - sprintf( commonsbooking_sanitizeHTML( __( - 'The page where you included the [cb_bookings] shortcode. This is used in the Users Widget', - 'commonsbooking' ) ), network_site_url( '/bookings/' ) ), + sprintf( + commonsbooking_sanitizeHTML( + __( + 'The page where you included the [cb_bookings] shortcode. This is used in the Users Widget', + 'commonsbooking' + ) + ), + network_site_url( '/bookings/' ) + ), 'type' => 'select', 'options' => Wordpress::getPageListTitle(), ), ), ), 'bookingCommentSettings' => array( - 'title' => __( "Booking comment", 'commonsbooking' ), + 'title' => __( 'Booking comment', 'commonsbooking' ), 'id' => 'bookingCommentSettings', 'fields' => array( array( @@ -139,15 +166,15 @@ 'type' => 'textarea_small', 'default' => __( 'Here you can leave a comment about your booking. This will be sent to the station.', 'commonsbooking' ), ), - ) + ), ), 'globalLocationSettings' => array( - 'title' => __( "Global location settings", 'commonsbooking' ), + 'title' => __( 'Global location settings', 'commonsbooking' ), 'desc' => commonsbooking_sanitizeHTML( __( 'These settings are used for all locations. You can overwrite these settings for each location in the location settings.', 'commonsbooking' ) ), 'id' => 'globalLocationSettings', - 'fields' => Location::getOverbookingSettingsMetaboxes() - ) - ) + 'fields' => Location::getOverbookingSettingsMetaboxes(), + ), + ), ), /* Tab: general end*/ @@ -160,8 +187,13 @@ 'title' => commonsbooking_sanitizeHTML( __( 'Booking codes', 'commonsbooking' ) ), 'id' => 'bookingcodes', 'desc' => - commonsbooking_sanitizeHTML( __( 'Enter the booking codes to be generated in advance for booking types with all-day booking time frames. Enter booking codes as a comma separated list, e.g.: Code1,Code2,Code3,Code4 -
More information in the documentation: Booking codes', 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( + __( + 'Enter the booking codes to be generated in advance for booking types with all-day booking time frames. Enter booking codes as a comma separated list, e.g.: Code1,Code2,Code3,Code4 +
More information in the documentation: Booking codes', + 'commonsbooking' + ) + ), 'fields' => array( array( 'name' => commonsbooking_sanitizeHTML( __( 'Booking codes', 'commonsbooking' ) ), @@ -179,7 +211,7 @@ ), 'default' => '30', ), - ) + ), ), 'mail_booking_codes' => array( 'title' => commonsbooking_sanitizeHTML( __( 'Booking codes by email', 'commonsbooking' ) ), @@ -197,7 +229,9 @@ 'name' => commonsbooking_sanitizeHTML( __( 'Body for booking codes email', 'commonsbooking' ) ), 'id' => 'mail-booking-codes-body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( ' + 'default' => commonsbooking_sanitizeHTML( + __( + '

Booking codes for {{item:post_title}} : {{codes:formatDateRange}}

Booking codes Table:

@@ -205,7 +239,10 @@ {{codes:codeTable}}

Thanks, the Team.

- ', 'commonsbooking' ) ), + ', + 'commonsbooking' + ) + ), ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Backup E-Mail for booking codes email', 'commonsbooking' ) ), @@ -214,14 +251,14 @@ 'type' => 'text', ), array( - 'name' => commonsbooking_sanitizeHTML( __('Attach iCalendar file to booking codes email', 'commonsbooking') ), + 'name' => commonsbooking_sanitizeHTML( __( 'Attach iCalendar file to booking codes email', 'commonsbooking' ) ), 'id' => 'mail-booking-codes-attach-ical', 'description' => commonsbooking_sanitizeHTML( __( 'Will attach an iCalendar compatible file with booking codes per day to import in their respective calendar application.', 'commonsbooking' ) ), 'type' => 'checkbox', ), - ) - ) - ) + ), + ), + ), ), /* Tab: templates start*/ @@ -253,26 +290,37 @@ 'desc' => commonsbooking_sanitizeHTML( __( 'E-Mail signature that will appear wherever you put {{booking:getEmailSignature}}', 'commonsbooking' ) ), 'id' => 'emailbody_signature', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( ' + 'default' => commonsbooking_sanitizeHTML( + __( + '

Thanks and all the best, the Team. -

', 'commonsbooking' ) ), +

', + 'commonsbooking' + ) + ), ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Booking confirmed email subject', 'commonsbooking' ) ), 'id' => 'emailtemplates_mail-booking-confirmed-subject', 'cb1_legacy_id' => 'commons-booking-settings-mail:commons-booking_mail_confirmation_subject', 'type' => 'text', - 'default' => commonsbooking_sanitizeHTML( __( 'Your booking {{item:post_title}} at {{location:post_title}} {{booking:formattedBookingDate}} ', - 'commonsbooking' ) ), + 'default' => commonsbooking_sanitizeHTML( + __( + 'Your booking {{item:post_title}} at {{location:post_title}} {{booking:formattedBookingDate}} ', + 'commonsbooking' + ) + ), ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Booking confirmed email body', 'commonsbooking' ) ), 'id' => 'emailtemplates_mail-booking-confirmed-body', 'cb1_legacy_id' => 'commons-booking-settings-mail:commons-booking_mail_confirmation_body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( ' + 'default' => commonsbooking_sanitizeHTML( + __( + ' Hi {{user:first_name}},

thank you for booking {{item:post_title}} {{booking:formattedBookingDate}}.
@@ -297,32 +345,43 @@ Name: {{user:first_name}} {{user:last_name}}

{{booking:getEmailSignature}} - ', 'commonsbooking' ) ), + ', + 'commonsbooking' + ) + ), ), array( - 'name' => commonsbooking_sanitizeHTML( __('Attach iCalendar file to booking email', 'commonsbooking') ), - 'id' => 'emailtemplates_mail-booking_ics_attach', - 'type' => 'checkbox', + 'name' => commonsbooking_sanitizeHTML( __( 'Attach iCalendar file to booking email', 'commonsbooking' ) ), + 'id' => 'emailtemplates_mail-booking_ics_attach', + 'type' => 'checkbox', 'desc' => esc_html__( 'Will attach an iCalendar compatible file for users to import in their respective calendar application.', 'commonsbooking' ), ), array( - 'name' => commonsbooking_sanitizeHTML( __('iCalendar event title', 'commonsbooking') ), - 'id' => 'emailtemplates_mail-booking_ics_event-title', - 'type' => 'text', + 'name' => commonsbooking_sanitizeHTML( __( 'iCalendar event title', 'commonsbooking' ) ), + 'id' => 'emailtemplates_mail-booking_ics_event-title', + 'type' => 'text', 'desc' => esc_html__( 'The title of the attached event', 'commonsbooking' ), - 'default' => commonsbooking_sanitizeHTML( __( '{{item:post_title}} at {{location:post_title}}', - 'commonsbooking' ) ), + 'default' => commonsbooking_sanitizeHTML( + __( + '{{item:post_title}} at {{location:post_title}}', + 'commonsbooking' + ) + ), ), array( - 'name' => commonsbooking_sanitizeHTML( __('iCalendar event description', 'commonsbooking') ), - 'id' => 'emailtemplates_mail-booking_ics_event-description', - 'type' => 'textarea', + 'name' => commonsbooking_sanitizeHTML( __( 'iCalendar event description', 'commonsbooking' ) ), + 'id' => 'emailtemplates_mail-booking_ics_event-description', + 'type' => 'textarea', 'desc' => esc_html__( 'The description for the attached event.', 'commonsbooking' ), - 'default' => commonsbooking_sanitizeHTML( __( ' Pick up: {{booking:pickupDatetime}} + 'default' => commonsbooking_sanitizeHTML( + __( + ' Pick up: {{booking:pickupDatetime}} Return date: {{booking:returnDatetime}} {{location:formattedPickupInstructions}} {{booking:formattedBookingCode}} ', - 'commonsbooking' ) ), + 'commonsbooking' + ) + ), ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Booking canceled email subject', 'commonsbooking' ) ), @@ -334,15 +393,20 @@ 'name' => commonsbooking_sanitizeHTML( __( 'Booking canceled email body', 'commonsbooking' ) ), 'id' => 'emailtemplates_mail-booking-canceled-body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( ' + 'default' => commonsbooking_sanitizeHTML( + __( + ' Hi {{user:first_name}},

your booking of {{item:post_title}} at {{location:post_title}} {{booking:formattedBookingDate}} has been canceled.

{{booking:getEmailSignature}} - ', 'commonsbooking' ) ), + ', + 'commonsbooking' + ) + ), ), - ) + ), ), /* field group email templates end */ @@ -400,7 +464,7 @@ 'desc' => esc_html__( 'This text is displayed on the booking button on item/location listing pages.', 'commonsbooking' ), 'default' => esc_html__( 'Book item', 'commonsbooking' ), ), - array( + array( 'name' => esc_html__( 'User details on booking page', 'commonsbooking' ), 'id' => 'user_details_template', 'type' => 'textarea', @@ -465,10 +529,10 @@ 'type' => 'checkbox', 'desc' => commonsbooking_sanitizeHTML( __( 'If checked the image will be cropped to specified dimensions using center crop positions', 'commonsbooking' ) ), ), - ) + ), ), /* image options end */ - + /* field group color setting */ 'colorscheme' => array( @@ -536,7 +600,7 @@ 'desc' => commonsbooking_sanitizeHTML( __( 'The color used for the background of tables and similar elements', 'commonsbooking' ) ), 'default' => '#f6f6f6', ), - + array( 'name' => commonsbooking_sanitizeHTML( __( 'Notice Background Color', 'commonsbooking' ) ), 'id' => 'colorscheme_noticebackgroundcolor', @@ -558,11 +622,11 @@ 'desc' => commonsbooking_sanitizeHTML( __( 'The color used for dark text on light backgrounds', 'commonsbooking' ) ), 'default' => '#000', ), - ) + ), ), /* color settings end*/ - ) + ), ), /* Tab: templates end*/ @@ -603,7 +667,9 @@ 'name' => commonsbooking_sanitizeHTML( __( 'Breakdown email body', 'commonsbooking' ) ), 'id' => 'restrictions-repair-body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( '

Hello {{user:first_name}},

+ 'default' => commonsbooking_sanitizeHTML( + __( + '

Hello {{user:first_name}},

Unfortunately, the article {{item:post_title}} you booked is no longer usable from {{restriction:formattedStartDateTime}} to probably {{restriction:formattedEndDateTime}}.
The reason is:
{{restriction:hint}}

@@ -615,7 +681,10 @@ Please book the item again for a different period or check our website to see if an alternative item is available.
We apologize for any inconvenience.

{{booking:getEmailSignature}} - ', 'commonsbooking' ) ), + ', + 'commonsbooking' + ) + ), ), // E-Mail hint @@ -629,7 +698,9 @@ 'name' => commonsbooking_sanitizeHTML( __( 'Restriction email body', 'commonsbooking' ) ), 'id' => 'restrictions-hint-body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( '

Hello {{user:first_name}},

+ 'default' => commonsbooking_sanitizeHTML( + __( + '

Hello {{user:first_name}},

The article {{item:post_title}} you booked can only be used to a limited extent from {{restriction:formattedStartDateTime}} to probably {{restriction:formattedEndDateTime}}.

@@ -647,7 +718,10 @@ We strive to fix the restriction as soon as possible. You will receive an email when the restriction is resolved.

- {{booking:getEmailSignature}}', 'commonsbooking' ) ), + {{booking:getEmailSignature}}', + 'commonsbooking' + ) + ), ), // E-Mail restriction cancellation @@ -661,16 +735,21 @@ 'name' => commonsbooking_sanitizeHTML( __( 'Restriction cancelled email body', 'commonsbooking' ) ), 'id' => 'restrictions-restriction-cancelled-body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( '

Hello {{user:first_name}},

+ 'default' => commonsbooking_sanitizeHTML( + __( + '

Hello {{user:first_name}},

The article {{item:post_title}} is now fully usable again.

This also affects your booking {{booking:formattedBookingDate}}

Here is the link to your booking: {{booking:BookingLink}}

- {{booking:getEmailSignature}}', 'commonsbooking' ) ), + {{booking:getEmailSignature}}', + 'commonsbooking' + ) + ), ), - ) + ), ), /* field group restriction settings start */ 'restrictionsettings' => array( @@ -683,34 +762,34 @@ 'id' => 'restrictions-no-cancel-on-total-breakdown', 'type' => 'checkbox', 'desc' => commonsbooking_sanitizeHTML( __( 'If checked, bookings will not be cancelled if the item has broken down. The user will be notified and once the item becomes available again, the old bookings are still valid.', 'commonsbooking' ) ), - ) - ) + ), + ), ), /* field group restriction settings end */ 'bookingRules' => array( - 'title' => commonsbooking_sanitizeHTML( __( 'Restrict bookings by booking rules', 'commonsbooking') ), - 'desc' => commonsbooking_sanitizeHTML( __( 'You can apply rules to individual items or categories of items/locations, which will restrict how users are able to book and, if violated, abort the booking process')), + 'title' => commonsbooking_sanitizeHTML( __( 'Restrict bookings by booking rules', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'You can apply rules to individual items or categories of items/locations, which will restrict how users are able to book and, if violated, abort the booking process' ) ), 'id' => 'bookingrules', - 'fields'=> array( + 'fields' => array( array( - 'name' => commonsbooking_sanitizeHTML( __('Count cancelled bookings towards quota', 'commonsbooking') ), - 'desc' => commonsbooking_sanitizeHTML( __('Check if bookings that have been cancelled in the booking period shall be counted towards the amount of booked days for the user. More info in the documentation', 'commonsbooking') ), + 'name' => commonsbooking_sanitizeHTML( __( 'Count cancelled bookings towards quota', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Check if bookings that have been cancelled in the booking period shall be counted towards the amount of booked days for the user. More info in the documentation', 'commonsbooking' ) ), 'id' => 'bookingrules-count-cancelled', - 'type' => 'checkbox' + 'type' => 'checkbox', ), array( 'id' => 'rules_group', 'type' => 'group', - 'repeatable'=> true, + 'repeatable' => true, 'options' => array( - 'group_title' => commonsbooking_sanitizeHTML( __( 'Rule ', 'commonsbooking') ) . '{#}', - 'add_button' => commonsbooking_sanitizeHTML( __( 'Add another rule', 'commonsbooking') ), - 'remove_button' => commonsbooking_sanitizeHTML( __( 'Remove rule', 'commonsbooking') ), + 'group_title' => commonsbooking_sanitizeHTML( __( 'Rule ', 'commonsbooking' ) ) . '{#}', + 'add_button' => commonsbooking_sanitizeHTML( __( 'Add another rule', 'commonsbooking' ) ), + 'remove_button' => commonsbooking_sanitizeHTML( __( 'Remove rule', 'commonsbooking' ) ), ), 'fields' => array( array( - 'name' => commonsbooking_sanitizeHTML( __('Rule type', 'commonsbooking') ), - 'desc' => commonsbooking_sanitizeHTML( __('Select the kind of rule', 'commonsbooking') ), + 'name' => commonsbooking_sanitizeHTML( __( 'Rule type', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Select the kind of rule', 'commonsbooking' ) ), 'id' => 'rule-type', 'type' => 'select', 'show_option_none' => true, @@ -718,7 +797,7 @@ 'options' => BookingRule::getRulesForSelect(), ), - //The following labels are not translated because they are replaced by the rule + // The following labels are not translated because they are replaced by the rule array( 'name' => commonsbooking_sanitizeHTML( __( 'Rule description', 'commonsbooking' ) ), 'desc' => commonsbooking_sanitizeHTML( 'You shall be replaced' ), @@ -729,53 +808,54 @@ 'name' => commonsbooking_sanitizeHTML( 'Parameter 1' ), 'desc' => 'Parameter description', 'id' => 'rule-param1', - 'type' => 'text_small' + 'type' => 'text_small', ), array( 'name' => commonsbooking_sanitizeHTML( 'Parameter 2' ), 'desc' => 'Parameter description', 'id' => 'rule-param2', - 'type' => 'text_small' + 'type' => 'text_small', ), array( - 'name' => commonsbooking_sanitizeHTML( __('Select an option', 'commonsbooking') ), + 'name' => commonsbooking_sanitizeHTML( __( 'Select an option', 'commonsbooking' ) ), 'desc' => 'Select parameter description', 'id' => 'rule-select-param', 'type' => 'select', ), array( - 'name' => commonsbooking_sanitizeHTML( __('Applies to all', 'commonsbooking') ), - 'desc' => commonsbooking_sanitizeHTML( __('Check if this rule applies to all items', 'commonsbooking') ), + 'name' => commonsbooking_sanitizeHTML( __( 'Applies to all', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Check if this rule applies to all items', 'commonsbooking' ) ), 'id' => 'rule-applies-all', - 'type' => 'checkbox' + 'type' => 'checkbox', ), array( - 'name' => commonsbooking_sanitizeHTML( __('Applies to categories', 'commonsbooking') ), - 'desc' => commonsbooking_sanitizeHTML( __('Check the categories that these rules apply to', 'commonsbooking') ), + 'name' => commonsbooking_sanitizeHTML( __( 'Applies to categories', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Check the categories that these rules apply to', 'commonsbooking' ) ), 'id' => 'rule-applies-categories', 'type' => 'multicheck', - 'options' => CustomPostType::sanitizeOptions( + 'options' => CustomPostType::sanitizeOptions( array_merge( \CommonsBooking\Repository\Item::getTerms(), - \CommonsBooking\Repository\Location::getTerms()) + \CommonsBooking\Repository\Location::getTerms() ) + ), ), array( - 'name' => commonsbooking_sanitizeHTML( __('Groups exempt from rule', 'commonsbooking') ), - 'desc' => commonsbooking_sanitizeHTML( __('Here you can define if the rule should not apply to a specific user group. Will apply to all groups if left empty (Administrators and item / location admins are always excluded).', 'commonsbooking') ), + 'name' => commonsbooking_sanitizeHTML( __( 'Groups exempt from rule', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Here you can define if the rule should not apply to a specific user group. Will apply to all groups if left empty (Administrators and item / location admins are always excluded).', 'commonsbooking' ) ), 'id' => 'rule-exempt-roles', 'type' => 'pw_multiselect', - 'options' => CustomPostType::sanitizeOptions( + 'options' => CustomPostType::sanitizeOptions( UserRepository::getUserRoles() - ) - ) - ) - ) + ), + ), + ), + ), - ) - ) + ), + ), /* field group email templates end */ - ) + ), ), /* Tab: restrictions end*/ @@ -789,9 +869,12 @@ 'pre-booking-reminder' => array( 'title' => commonsbooking_sanitizeHTML( __( 'Booking reminder', 'commonsbooking' ) ), 'id' => 'pre-booking-reminder', - 'desc' => commonsbooking_sanitizeHTML( __( - 'You can set here whether users should receive a reminder email before the start of a booking.
More Information in the documentation' - , 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'You can set here whether users should receive a reminder email before the start of a booking.
More Information in the documentation', + 'commonsbooking' + ) + ), 'fields' => array( // settings pre booking reminder -- activate reminder array( @@ -799,7 +882,7 @@ 'id' => 'pre-booking-reminder-activate', 'type' => 'checkbox', ), - // E-Mail pre booking reminder + // E-Mail pre booking reminder array( 'name' => commonsbooking_sanitizeHTML( __( 'E-mail subject', 'commonsbooking' ) ), 'id' => 'pre-booking-reminder-subject', @@ -810,7 +893,9 @@ 'name' => commonsbooking_sanitizeHTML( __( 'email body', 'commonsbooking' ) ), 'id' => 'pre-booking-reminder-body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( '

Hi {{user:first_name}},

+ 'default' => commonsbooking_sanitizeHTML( + __( + '

Hi {{user:first_name}},

Your booking period for the item {{item:post_title}} will start soon.
Your booking period: {{booking:formattedBookingDate}}

@@ -819,16 +904,22 @@ For booking details and cancellation, click on this booking link: {{booking:bookingLink}}
-{{booking:getEmailSignature}}', 'commonsbooking' ) ), +{{booking:getEmailSignature}}', + 'commonsbooking' + ) + ), ), - // settings pre booking reminder -- min days + // settings pre booking reminder -- min days array( 'name' => commonsbooking_sanitizeHTML( __( 'Sent reminder x days before booking start', 'commonsbooking' ) ), 'id' => 'pre-booking-days-before', - 'desc' => '

' . commonsbooking_sanitizeHTML( __( - 'This reminder email will be sent to users x days before the start of the booking. If the booking is made less days before the specified days, no reminder email will be sent' - , 'commonsbooking' ) ) . '

', + 'desc' => '

' . commonsbooking_sanitizeHTML( + __( + 'This reminder email will be sent to users x days before the start of the booking. If the booking is made less days before the specified days, no reminder email will be sent', + 'commonsbooking' + ) + ) . '

', 'type' => 'text_small', 'attributes' => array( 'type' => 'number', @@ -842,9 +933,12 @@ array( 'name' => esc_html__( 'Time', 'commonsbooking' ), 'id' => 'pre-booking-time', - 'desc' => '
' . commonsbooking_sanitizeHTML( __( - 'Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured.' - , 'commonsbooking' ) ), + 'desc' => '
' . commonsbooking_sanitizeHTML( + __( + 'Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured.', + 'commonsbooking' + ) + ), 'type' => 'select', 'show_option_none' => false, 'default' => '1', @@ -885,10 +979,13 @@ 'post-booking-notice' => array( 'title' => commonsbooking_sanitizeHTML( __( 'email after booking has ended', 'commonsbooking' ) ), 'id' => 'post-booking-notice', - 'desc' => commonsbooking_sanitizeHTML( __( - 'Here you can set whether users should receive an additional e-mail after completing a booking. This can be used, for example, to inquire about the users satisfaction or possible problems during the booking. -
The email will be sent around midnight after the booking day has ended.' - , 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'Here you can set whether users should receive an additional e-mail after completing a booking. This can be used, for example, to inquire about the users satisfaction or possible problems during the booking. +
The email will be sent around midnight after the booking day has ended.', + 'commonsbooking' + ) + ), 'fields' => array( // settings post booking reminder -- activate reminder array( @@ -896,7 +993,7 @@ 'id' => 'post-booking-notice-activate', 'type' => 'checkbox', ), - // E-Mail post booking reminder + // E-Mail post booking reminder array( 'name' => commonsbooking_sanitizeHTML( __( 'E-mail subject', 'commonsbooking' ) ), 'id' => 'post-booking-notice-subject', @@ -907,12 +1004,17 @@ 'name' => commonsbooking_sanitizeHTML( __( 'email body', 'commonsbooking' ) ), 'id' => 'post-booking-notice-body', 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( '

Hi {{user:first_name}},

+ 'default' => commonsbooking_sanitizeHTML( + __( + '

Hi {{user:first_name}},

Your booking of {{item:post_title}} at {{location:post_title}} has ended.
We hope that everything worked as expected.
Please let us know if any problems occurred.

-{{booking:getEmailSignature}}', 'commonsbooking' ) ), +{{booking:getEmailSignature}}', + 'commonsbooking' + ) + ), ), ), ), @@ -922,9 +1024,12 @@ 'booking-start-location-reminder' => array( 'title' => commonsbooking_sanitizeHTML( __( 'Reminder for locations before booking starts', 'commonsbooking' ) ), 'id' => 'booking-start-location-reminder', - 'desc' => commonsbooking_sanitizeHTML( __( - 'You can set here whether locations should receive a reminder email before the start of a booking.
More Information in the documentation' - , 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'You can set here whether locations should receive a reminder email before the start of a booking.
More Information in the documentation', + 'commonsbooking' + ) + ), 'fields' => array( // settings booking start reminder -- activate reminder array( @@ -935,46 +1040,57 @@ ), // E-Mail booking start reminder for locations array( - 'name' => commonsbooking_sanitizeHTML( __( 'E-mail subject', 'commonsbooking' ) ), - 'id' => 'booking-start-location-reminder-subject', - 'type' => 'text', - 'default' => commonsbooking_sanitizeHTML( __( 'Upcoming booking of {{item:post_title}} {{booking:formattedBookingDate}}', 'commonsbooking' ) ), - ), - array( - 'name' => commonsbooking_sanitizeHTML( __( 'email body', 'commonsbooking' ) ), - 'id' => 'booking-start-location-reminder-body', - 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( '

Hi,

+ 'name' => commonsbooking_sanitizeHTML( __( 'E-mail subject', 'commonsbooking' ) ), + 'id' => 'booking-start-location-reminder-subject', + 'type' => 'text', + 'default' => commonsbooking_sanitizeHTML( __( 'Upcoming booking of {{item:post_title}} {{booking:formattedBookingDate}}', 'commonsbooking' ) ), + ), + array( + 'name' => commonsbooking_sanitizeHTML( __( 'email body', 'commonsbooking' ) ), + 'id' => 'booking-start-location-reminder-body', + 'type' => 'textarea', + 'default' => commonsbooking_sanitizeHTML( + __( + '

Hi,

The booking period for the item {{item:post_title}} at {{location:post_title}} will start soon.
The booking period: {{booking:formattedBookingDate}}

This item has been booked by {{user:first_name}} {{user:last_name}} ( {{user:user_email}} ).
-{{booking:getEmailSignature}}', 'commonsbooking' ) ), - ), - // settings booking start reminder -- set sending time - array( - 'name' => esc_html__( 'Time', 'commonsbooking' ), - 'id' => 'booking-start-location-reminder-time', - 'desc' => '
' . commonsbooking_sanitizeHTML( __( - 'Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured.' - , 'commonsbooking' ) ), - 'type' => 'text_time', - 'attributes' => array( - 'data-timepicker' => wp_json_encode( - array( - 'stepMinute' => 60, - 'timeFormat' => 'HH:mm', - ) - ), +{{booking:getEmailSignature}}', + 'commonsbooking' + ) + ), + ), + // settings booking start reminder -- set sending time + array( + 'name' => esc_html__( 'Time', 'commonsbooking' ), + 'id' => 'booking-start-location-reminder-time', + 'desc' => '
' . commonsbooking_sanitizeHTML( + __( + 'Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured.', + 'commonsbooking' + ) + ), + 'type' => 'text_time', + 'attributes' => array( + 'data-timepicker' => wp_json_encode( + array( + 'stepMinute' => 60, + 'timeFormat' => 'HH:mm', + ) ), - 'time_format' => esc_html(get_option( 'time_format' )), + ), + 'time_format' => esc_html( get_option( 'time_format' ) ), ), array( 'name' => esc_html__( 'Bookings of', 'commonsbooking' ), 'id' => 'booking-start-location-reminder-day', - 'desc' => '
' . commonsbooking_sanitizeHTML( __( - 'Define for which booking start day the notifications should be sent' - , 'commonsbooking' ) ), + 'desc' => '
' . commonsbooking_sanitizeHTML( + __( + 'Define for which booking start day the notifications should be sent', + 'commonsbooking' + ) + ), 'type' => 'select', 'show_option_none' => false, 'default' => '1', @@ -991,9 +1107,12 @@ 'booking-end-location-reminder' => array( 'title' => commonsbooking_sanitizeHTML( __( 'Reminder for locations before booking ends', 'commonsbooking' ) ), 'id' => 'booking-end-location-reminder', - 'desc' => commonsbooking_sanitizeHTML( __( - 'You can set here whether locations should receive a reminder email before the end of a booking.
More Information in the documentation' - , 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'You can set here whether locations should receive a reminder email before the end of a booking.
More Information in the documentation', + 'commonsbooking' + ) + ), 'fields' => array( // settings booking end reminder -- activate reminder array( @@ -1004,48 +1123,59 @@ ), // E-Mail booking end reminder for locations array( - 'name' => commonsbooking_sanitizeHTML( __( 'E-mail subject', 'commonsbooking' ) ), - 'id' => 'booking-end-location-reminder-subject', - 'type' => 'text', - 'default' => commonsbooking_sanitizeHTML( __( 'Booking of {{item:post_title}} {{booking:formattedBookingDate}}', 'commonsbooking' ) ), - ), - array( - 'name' => commonsbooking_sanitizeHTML( __( 'email body', 'commonsbooking' ) ), - 'id' => 'booking-end-location-reminder-body', - 'type' => 'textarea', - 'default' => commonsbooking_sanitizeHTML( __( '

Hi,

+ 'name' => commonsbooking_sanitizeHTML( __( 'E-mail subject', 'commonsbooking' ) ), + 'id' => 'booking-end-location-reminder-subject', + 'type' => 'text', + 'default' => commonsbooking_sanitizeHTML( __( 'Booking of {{item:post_title}} {{booking:formattedBookingDate}}', 'commonsbooking' ) ), + ), + array( + 'name' => commonsbooking_sanitizeHTML( __( 'email body', 'commonsbooking' ) ), + 'id' => 'booking-end-location-reminder-body', + 'type' => 'textarea', + 'default' => commonsbooking_sanitizeHTML( + __( + '

Hi,

The booking period for the item {{item:post_title}} at {{location:post_title}} will end soon.
The booking period: {{booking:formattedBookingDate}}

This item has been booked by {{user:first_name}} {{user:last_name}} ( {{user:user_email}} ).
-{{booking:getEmailSignature}}', 'commonsbooking' ) ), - ), - // settings booking end reminder -- set sending time - array( - 'name' => esc_html__( 'Time', 'commonsbooking' ), - 'id' => 'booking-end-location-reminder-time', - 'desc' => '
' . commonsbooking_sanitizeHTML( __( - 'Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured.' - , 'commonsbooking' ) ), - 'type' => 'text_time', - 'default' => '1', - 'attributes' => array( - 'data-timepicker' => wp_json_encode( - array( - 'stepMinute' => 60, - 'timeFormat' => 'HH:mm', +{{booking:getEmailSignature}}', + 'commonsbooking' ) ), ), - 'time_format' => esc_html(get_option( 'time_format' )), + // settings booking end reminder -- set sending time + array( + 'name' => esc_html__( 'Time', 'commonsbooking' ), + 'id' => 'booking-end-location-reminder-time', + 'desc' => '
' . commonsbooking_sanitizeHTML( + __( + 'Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured.', + 'commonsbooking' + ) + ), + 'type' => 'text_time', + 'default' => '1', + 'attributes' => array( + 'data-timepicker' => wp_json_encode( + array( + 'stepMinute' => 60, + 'timeFormat' => 'HH:mm', + ) + ), + ), + 'time_format' => esc_html( get_option( 'time_format' ) ), ), array( 'name' => esc_html__( 'Bookings of', 'commonsbooking' ), 'id' => 'booking-end-location-reminder-day', - 'desc' => '
' . commonsbooking_sanitizeHTML( __( - 'Define for which booking end day the notifications should be sent' - , 'commonsbooking' ) ), + 'desc' => '
' . commonsbooking_sanitizeHTML( + __( + 'Define for which booking end day the notifications should be sent', + 'commonsbooking' + ) + ), 'type' => 'select', 'show_option_none' => false, 'default' => '1', @@ -1077,7 +1207,7 @@ 'id' => 'upgrade-custom-field', 'type' => 'text', 'render_row_cb' => array( Migration::class, 'renderUpgradeForm' ), - ) + ), ], ), // migration cb1 -> cb2 @@ -1091,8 +1221,8 @@ 'id' => 'migration-custom-field', 'type' => 'text', 'render_row_cb' => array( Migration::class, 'renderMigrationForm' ), - ) - ] + ), + ], ), @@ -1111,8 +1241,8 @@ 'name' => esc_html__( 'Terms & Services Url', 'commonsbooking' ), 'id' => 'cb1-terms-url', 'type' => 'text', - ) - ] + ), + ], ), // booking migration button @@ -1126,10 +1256,10 @@ 'id' => 'booking-migration-custom-field', 'type' => 'text', 'render_row_cb' => array( Migration::class, 'renderBookingMigrationForm' ), - ) - ] + ), + ], ), - ) + ), ), /* Tab: migration end */ @@ -1145,33 +1275,37 @@ array( 'name' => esc_html__( 'Type', 'commonsbooking' ), 'desc' => esc_html__( 'Select Type of this timeframe (e.g. bookable, repair, holidays, booking). See Documentation for detailed information.', 'commonsbooking' ), - 'id' => "export-type", + 'id' => 'export-type', 'type' => 'select', 'options' => Timeframe::getTypes( true ), ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Location-Fields', 'commonsbooking' ) ), - 'desc' => sprintf ( commonsbooking_sanitizeHTML( __( 'Just add field names, no matter if its a post- or a meta-field. Comma separated list. Beside the standard post fields and standard postmeta-fields, the following custom meta fields are available. Copy only the values in [] in the field without the brackets. %s', 'commonsbooking' ) ), - commonsbooking_sanitizeHTML( Settings::returnFormattedMetaboxFields('cb_location') ) ), + 'desc' => sprintf( + commonsbooking_sanitizeHTML( __( 'Just add field names, no matter if its a post- or a meta-field. Comma separated list. Beside the standard post fields and standard postmeta-fields, the following custom meta fields are available. Copy only the values in [] in the field without the brackets. %s', 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( Settings::returnFormattedMetaboxFields( 'cb_location' ) ) + ), 'id' => TimeframeExport::LOCATION_FIELD, - 'type' => 'text' + 'type' => 'text', ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Item-Fields', 'commonsbooking' ) ), - 'desc' => sprintf ( commonsbooking_sanitizeHTML( __( 'Just add field names, no matter if its a post- or a meta-field. Comma separated list. Beside the standard post fields and standard postmeta-fields, the following custom meta fields are available. Copy only the values in [] in the field without the brackets. %s', 'commonsbooking' ) ), - commonsbooking_sanitizeHTML( Settings::returnFormattedMetaboxFields('cb_item') ) ), + 'desc' => sprintf( + commonsbooking_sanitizeHTML( __( 'Just add field names, no matter if its a post- or a meta-field. Comma separated list. Beside the standard post fields and standard postmeta-fields, the following custom meta fields are available. Copy only the values in [] in the field without the brackets. %s', 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( Settings::returnFormattedMetaboxFields( 'cb_item' ) ) + ), 'id' => TimeframeExport::ITEM_FIELD, - 'type' => 'text' + 'type' => 'text', ), array( 'name' => commonsbooking_sanitizeHTML( __( 'User-Fields', 'commonsbooking' ) ), - 'desc' => commonsbooking_sanitizeHTML( __( 'Just add field names, no matter if its a userfield or a meta-field. Comma separated list.', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Just add field names, no matter if its a userfield or a meta-field. Comma separated list.', 'commonsbooking' ) ), 'id' => TimeframeExport::USER_FIELD, - 'type' => 'text' + 'type' => 'text', ), array( 'name' => esc_html__( 'Export start date', 'commonsbooking' ), - 'id' => "export-timerange-start", + 'id' => 'export-timerange-start', 'type' => 'text_date_timestamp', 'date_format' => $dateFormat, 'default' => date( $dateFormat ), @@ -1181,7 +1315,7 @@ ), array( 'name' => esc_html__( 'Export end date', 'commonsbooking' ), - 'id' => "export-timerange-end", + 'id' => 'export-timerange-end', 'type' => 'text_date_timestamp', 'date_format' => $dateFormat, 'attributes' => array( @@ -1193,8 +1327,8 @@ 'id' => 'export-custom-field', 'type' => 'text', 'render_row_cb' => array( TimeframeExport::class, 'renderExportButton' ), - ) - ] + ), + ], ), 'cron' => array( 'title' => esc_html__( 'Cron settings for timeframes export', 'commonsbooking' ), @@ -1202,23 +1336,23 @@ 'fields' => [ array( 'name' => esc_html__( 'Run as cronjob', 'commonsbooking' ), - 'id' => "export-cron", - 'type' => 'checkbox' + 'id' => 'export-cron', + 'type' => 'checkbox', ), array( 'name' => esc_html__( 'Export interval', 'commonsbooking' ), - 'id' => "export-interval", + 'id' => 'export-interval', 'type' => 'select', 'options' => [ - 'five_minutes' => "5 " . esc_html__( 'minutes', 'commonsbooking' ), - 'thirty_minutes' => "30 " . esc_html__( 'minutes', 'commonsbooking' ), + 'five_minutes' => '5 ' . esc_html__( 'minutes', 'commonsbooking' ), + 'thirty_minutes' => '30 ' . esc_html__( 'minutes', 'commonsbooking' ), 'daily' => esc_html__( 'daily', 'commonsbooking' ), ], ), array( 'name' => esc_html__( 'Export timerange', 'commonsbooking' ), 'desc' => commonsbooking_sanitizeHTML( __( 'Export timerange in days.', 'commonsbooking' ) ), - 'id' => "export-timerange", + 'id' => 'export-timerange', 'type' => 'text', 'attributes' => array( 'type' => 'number', @@ -1229,11 +1363,11 @@ 'name' => commonsbooking_sanitizeHTML( __( 'Filepath', 'commonsbooking' ) ), 'desc' => commonsbooking_sanitizeHTML( __( 'Absolute path on your webserver (including trailing slash) where export file will be saved to.', 'commonsbooking' ) ), 'id' => 'export-filepath', - 'type' => 'text' + 'type' => 'text', ), - ] - ) - ) + ], + ), + ), ), /* Tab: export end */ @@ -1263,13 +1397,13 @@ // Repeatable group -> API Shares 'name' => esc_html__( 'API shares', 'commonsbooking' ), 'desc' => commonsbooking_sanitizeHTML( __( 'You can define on or more API shares. Read the documentation for more information about API shares and configuration API documentation', 'commonsbooking' ) ), - 'id' => "api_share_group", + 'id' => 'api_share_group', 'type' => 'group', 'repeatable' => true, 'options' => array( - 'group_title' => commonsbooking_sanitizeHTML(__('API','commonsbooking') ). '{#}', - 'add_button' => commonsbooking_sanitizeHTML(__( 'Add Another API', 'commonsbooking') ), - 'remove_button' => commonsbooking_sanitizeHTML(__ ( 'Remove API', 'commonsbooking') ), + 'group_title' => commonsbooking_sanitizeHTML( __( 'API', 'commonsbooking' ) ) . '{#}', + 'add_button' => commonsbooking_sanitizeHTML( __( 'Add Another API', 'commonsbooking' ) ), + 'remove_button' => commonsbooking_sanitizeHTML( __( 'Remove API', 'commonsbooking' ) ), 'closed' => false, // Repeater fields closed by default - neat & compact. 'sortable' => false, // Allow changing the order of repeated groups. ), @@ -1311,9 +1445,9 @@ 'default' => get_bloginfo( 'name' ), ), - ) + ), ), - ] + ], ), ), ), @@ -1326,52 +1460,72 @@ 'field_groups' => array( 'custom_metadata' => array( 'title' => esc_html__( 'Set Custom metadata to locations and items', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __( - 'This is an advanced feature and should only be used if you are experienced or instructed how to set it up properly. In future versions we will add more detailed information and documentation.' - , 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'This is an advanced feature and should only be used if you are experienced or instructed how to set it up properly. In future versions we will add more detailed information and documentation.', + 'commonsbooking' + ) + ), 'id' => 'meta_data_group', 'fields' => [ array( 'name' => esc_html__( 'Meta Data', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __( 'Use only this format, separated by semicolon and each entry in a new line:
post_type(item/location);field-name;label(english),type(checkbox,number,text),description(in english)
- Example: item;waterproof;Waterproof material;checkbox;"This item is waterproof and can be used in heavy rain" ', 'commonsbooking' ) ), - 'id' => "metadata", + 'desc' => commonsbooking_sanitizeHTML( + __( + 'Use only this format, separated by semicolon and each entry in a new line:
post_type(item/location);field-name;label(english),type(checkbox,number,text),description(in english)
+ Example: item;waterproof;Waterproof material;checkbox;"This item is waterproof and can be used in heavy rain" ', + 'commonsbooking' + ) + ), + 'id' => 'metadata', 'type' => 'textarea', ), - ] + ], ), 'icalfeed' => array( 'title' => esc_html__( 'iCalendar Feed', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __('Enables users to copy a url for a dynamic iCalendar feed into their own digital calendars. This feature is experimental.', - 'commonsbooking')), - 'id' => 'icalendar_group', - 'fields'=> [ + 'desc' => commonsbooking_sanitizeHTML( + __( + 'Enables users to copy a url for a dynamic iCalendar feed into their own digital calendars. This feature is experimental.', + 'commonsbooking' + ) + ), + 'id' => 'icalendar_group', + 'fields' => [ array( 'name' => esc_html__( 'Enable iCalendar feed', 'commonsbooking' ), 'id' => 'feed_enabled', 'type' => 'checkbox', ), array( - 'name' => esc_html__( 'Event title', 'commonsbooking'), - 'desc' => esc_html__( 'You can use template tags here as well', 'commonsbooking'), - 'default' => commonsbooking_sanitizeHTML( __( '{{item:post_title}} at {{location:post_title}}', - 'commonsbooking' ) ), - 'id' => 'event_title', - 'type' => 'text', + 'name' => esc_html__( 'Event title', 'commonsbooking' ), + 'desc' => esc_html__( 'You can use template tags here as well', 'commonsbooking' ), + 'default' => commonsbooking_sanitizeHTML( + __( + '{{item:post_title}} at {{location:post_title}}', + 'commonsbooking' + ) + ), + 'id' => 'event_title', + 'type' => 'text', ), array( - 'name' => esc_html__( 'Event description', 'commonsbooking'), - 'desc' => esc_html__( 'You can use template tags here as well', 'commonsbooking'), - 'default' => commonsbooking_sanitizeHTML( __( ' + 'name' => esc_html__( 'Event description', 'commonsbooking' ), + 'desc' => esc_html__( 'You can use template tags here as well', 'commonsbooking' ), + 'default' => commonsbooking_sanitizeHTML( + __( + ' Pick up: {{booking:pickupDatetime}} Return date: {{booking:returnDatetime}} {{location:formattedPickupInstructions}} {{booking:formattedBookingCode}} ', - 'commonsbooking' ) ), - 'id' => 'event_desc', - 'type' => 'textarea', - ) - ] + 'commonsbooking' + ) + ), + 'id' => 'event_desc', + 'type' => 'textarea', + ), + ], ), 'experimental' => array( 'title' => commonsbooking_sanitizeHTML( __( 'Advanced caching settings', 'commonsbooking' ) ), @@ -1383,7 +1537,7 @@ 'name' => commonsbooking_sanitizeHTML( __( 'Clear Cache', 'commonsbooking' ) ), 'id' => 'commonsbooking-clear_cache-button', 'type' => 'text', - 'render_row_cb' => array( \CommonsBooking\Plugin::class, 'renderClearCacheButton' ) + 'render_row_cb' => array( \CommonsBooking\Plugin::class, 'renderClearCacheButton' ), ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Filesystem cache path', 'commonsbooking' ) ), @@ -1407,15 +1561,15 @@ 'name' => commonsbooking_sanitizeHTML( __( 'REDIS DSN (REDIS Server URL)', 'commonsbooking' ) ), 'id' => 'redis_dsn', 'type' => 'text', - 'default' => 'redis://localhost:6379' + 'default' => 'redis://localhost:6379', ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Current connection status', 'commonsbooking' ) ), 'id' => 'redis_connection-status', 'type' => 'text', 'render_row_cb' => array( \CommonsBooking\Plugin::class, 'renderREDISConnectionStatus' ), - ) - ) + ), + ), ), ), ), diff --git a/includes/Plugin.php b/includes/Plugin.php index 08f0e2f1c..08752c743 100644 --- a/includes/Plugin.php +++ b/includes/Plugin.php @@ -20,4 +20,4 @@ $cbPlugin->init(); $cbPlugin->initRoutes(); -$cbPlugin->initBookingcodes(); \ No newline at end of file +$cbPlugin->initBookingcodes(); diff --git a/includes/Public.php b/includes/Public.php index 352776cfe..79a0ee513 100644 --- a/includes/Public.php +++ b/includes/Public.php @@ -9,7 +9,6 @@ function commonsbooking_public() { - wp_enqueue_style( 'cb-styles-public', COMMONSBOOKING_PLUGIN_ASSETS_URL . 'public/css/public.css', @@ -18,19 +17,19 @@ function commonsbooking_public() { ); $colorScheme_css = View::getColorCSS(); - if ($colorScheme_css) { //if custom color variables exist, import them after importing the rest of the CSS, overwriting existing defaults - wp_add_inline_style('cb-styles-public',$colorScheme_css); + if ( $colorScheme_css ) { // if custom color variables exist, import them after importing the rest of the CSS, overwriting existing defaults + wp_add_inline_style( 'cb-styles-public', $colorScheme_css ); } // Template specific styles - $template = wp_get_theme()->template; + $template = wp_get_theme()->template; $customizedTemplates = [ 'graphene', 'kasimir', 'twentytwenty', - 'twentynineteen' + 'twentynineteen', ]; - if(in_array($template, $customizedTemplates)) { + if ( in_array( $template, $customizedTemplates ) ) { wp_enqueue_style( 'cb-styles-public-theme', COMMONSBOOKING_PLUGIN_ASSETS_URL . 'public/css/themes/' . $template . '.css', @@ -51,13 +50,17 @@ function commonsbooking_public() { wp_enqueue_style( 'cb-styles-vendor', - COMMONSBOOKING_PLUGIN_ASSETS_URL . 'global/css/vendor.css', array(), COMMONSBOOKING_VERSION + COMMONSBOOKING_PLUGIN_ASSETS_URL . 'global/css/vendor.css', + array(), + COMMONSBOOKING_VERSION ); // Daterangepicker wp_enqueue_style( 'cb-styles-daterangepicker', - COMMONSBOOKING_PLUGIN_ASSETS_URL . 'public/css/themes/daterangepicker/daterangepicker.css', array(), COMMONSBOOKING_VERSION + COMMONSBOOKING_PLUGIN_ASSETS_URL . 'public/css/themes/daterangepicker/daterangepicker.css', + array(), + COMMONSBOOKING_VERSION ); wp_enqueue_script( @@ -70,7 +73,9 @@ function commonsbooking_public() { // Select 2 wp_enqueue_style( 'cb-styles-select2', - COMMONSBOOKING_PLUGIN_ASSETS_URL . 'public/css/themes/select2/select2.min.css', array(), COMMONSBOOKING_VERSION + COMMONSBOOKING_PLUGIN_ASSETS_URL . 'public/css/themes/select2/select2.min.css', + array(), + COMMONSBOOKING_VERSION ); wp_enqueue_script( @@ -160,16 +165,16 @@ function commonsbooking_public() { add_action( 'wp_ajax_nopriv_cb_cache_warmup', array( \CommonsBooking\Plugin::class, 'warmupCache' ) ); if ( is_admin() ) { - //migration AJAX + // migration AJAX add_action( 'wp_ajax_cb_start_migration', array( Migration::class, 'migrateAll' ) ); add_action( 'wp_ajax_cb_start_booking_migration', array( \CommonsBooking\Migration\Booking::class, 'ajaxMigrate' ) ); add_action( 'wp_ajax_cb_run_upgrade', array( \CommonsBooking\Service\Upgrade::class, 'runAJAXUpgradeTasks' ) ); add_action( 'wp_ajax_cb_export_timeframes', array( \CommonsBooking\Service\TimeframeExport::class, 'ajaxExportCsv' ) ); - //getting bookable Location for item AJAX + // getting bookable Location for item AJAX add_action( 'wp_ajax_cb_get_bookable_location', array( \CommonsBooking\View\Booking::class, 'getLocationForItem_AJAX' ) ); - //getting booking code for new backend booking AJAX + // getting booking code for new backend booking AJAX add_action( 'wp_ajax_cb_get_booking_code', array( \CommonsBooking\View\Booking::class, 'getBookingCode_AJAX' ) ); add_action( 'wp_ajax_cb_orphaned_booking_migration', array( \CommonsBooking\Service\MassOperations::class, 'ajaxMigrateOrphaned' ) ); } diff --git a/includes/Shortcodes.php b/includes/Shortcodes.php index 9823ceb44..a4a750439 100644 --- a/includes/Shortcodes.php +++ b/includes/Shortcodes.php @@ -1,13 +1,15 @@ '', - ), $atts, 'cb' ); + $atts = shortcode_atts( + array( + 'tag' => '', + ), + $atts, + 'cb' + ); echo commonsbooking_sanitizeHTML( commonsbooking_parse_shortcode( $atts['tag'] ) ); } add_shortcode( 'cb', 'commonsbooking_tag' ); - - diff --git a/includes/Template.php b/includes/Template.php index d51fa5476..4d096321b 100644 --- a/includes/Template.php +++ b/includes/Template.php @@ -12,7 +12,7 @@ * * @param string $slug * @param string $name - * @param bool $include + * @param bool $include * @param string $before * @param string $after * @@ -37,7 +37,7 @@ function commonsbooking_get_template_part( $slug, $name = '', $include = true, $ if ( file_exists( $path . "{$slug}.php" ) ) { $template = $path . "{$slug}.php"; } - } else if ( file_exists( $path . "{$slug}-{$name}.php" ) ) { + } elseif ( file_exists( $path . "{$slug}-{$name}.php" ) ) { $template = $path . "{$slug}-{$name}.php"; } } @@ -50,13 +50,13 @@ function commonsbooking_get_template_part( $slug, $name = '', $include = true, $ // Allow 3rd party plugin filter template file from their plugin $template = apply_filters( 'commonsbooking_get_template_part', $template, $slug, $name, $plugin_slug ); - $has_post_thumbnail = ( has_post_thumbnail() ) ? 'has-post-thumbnail' : 'no-post-thumbnail'; //@TODO this feils because we have no global post anymore + $has_post_thumbnail = ( has_post_thumbnail() ) ? 'has-post-thumbnail' : 'no-post-thumbnail'; // @TODO this feils because we have no global post anymore $template_classes = array( 'cb-' . $slug . '-' . $name, 'template-' . basename( $template, '.php' ), - 'post-' . get_post_type(), //@TODO: this returns "page", not the type (e.g. "item") that is queried. - $has_post_thumbnail + 'post-' . get_post_type(), // @TODO: this returns "page", not the type (e.g. "item") that is queried. + $has_post_thumbnail, ); $css_classes = implode( ' ', $template_classes ); @@ -67,7 +67,7 @@ function commonsbooking_get_template_part( $slug, $name = '', $include = true, $ // Display debug message if ( WP_DEBUG ) { - if ( empty ( $template ) ) { + if ( empty( $template ) ) { $before_html .= ( '

Template file not found
' ); } else { $before_html .= ( '
Template:' . basename( $template ) . '
' ); @@ -78,7 +78,7 @@ function commonsbooking_get_template_part( $slug, $name = '', $include = true, $ echo( commonsbooking_sanitizeHTML( $before_html ) ); load_template( $template, false ); echo( commonsbooking_sanitizeHTML( $after_html ) ); - } else if ( $template && $include === false ) { + } elseif ( $template && $include === false ) { return $before_html . $template . $after_html; } return ''; diff --git a/includes/TemplateParser.php b/includes/TemplateParser.php index 9e87a7374..9f3df1b3e 100644 --- a/includes/TemplateParser.php +++ b/includes/TemplateParser.php @@ -5,8 +5,8 @@ /** * Parses templates and extracts the template tags used in e-mail templates: {{xxx:yyyy}} * - * @param string $template - * @param array $objects + * @param string $template + * @param array $objects * @param callable $sanitizeFunction The callable used to remove unwanted tags/characters (use default 'commonsbooking_sanitizeHTML' or 'sanitize_text_field') * * @return mixed @@ -20,13 +20,13 @@ function ( $match ) use ( $objects, $sanitizeFunction ) { $template ); - // template is checked recursively to support templates tags within custom fields that are for example added to items or locations - // why? users can add e.g. inidvidual booking-mail texts per location by adding a custom field like 'custom_booking_message' and use all avaiable template tags within this custom field - if ( preg_match_all( '/{{.*?}}/', $template ) === 0 ) { - return apply_filters( 'commonsbooking_template_tag', $template ); - } else { - return commonsbooking_parse_template( $template, $objects, $sanitizeFunction ); - } + // template is checked recursively to support templates tags within custom fields that are for example added to items or locations + // why? users can add e.g. inidvidual booking-mail texts per location by adding a custom field like 'custom_booking_message' and use all avaiable template tags within this custom field + if ( preg_match_all( '/{{.*?}}/', $template ) === 0 ) { + return apply_filters( 'commonsbooking_template_tag', $template ); + } else { + return commonsbooking_parse_template( $template, $objects, $sanitizeFunction ); + } } function commonsbooking_parse_shortcode( $tag ) { @@ -40,61 +40,60 @@ function commonsbooking_parse_shortcode( $tag ) { * Renders html before and after the template tag if it is given by using [html text] before or after the template tag * Example: {{[this comes before: ]item:post_title[this comes after]}} * - * @param mixed $match - * @param array $objects + * @param mixed $match + * @param array $objects * @param callable $sanitizeFunction The callable used to remove unwanted tags/characters * * @return false|mixed */ function commonsbooking_parse_template_callback( $match, array $objects = [], $sanitizeFunction = 'commonsbooking_sanitizeHTML' ) { - if ( isset( $match[0] ) ) { - $match = $match[0]; - - // extract the html before part, looking for {{[*] pattern - if ( preg_match( '/\{\{\[([^\]]*)\]/m', $match, $html_before ) === 1 ) { - $html_before = preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_before[1] ); - $html_before = call_user_func( $sanitizeFunction, $html_before ); - } else { - $html_before = ''; - } - - // extract the html after part looking for [*]}} pattern - if ( preg_match( '/\[([^\]]*)\]\}\}/m', $match, $html_after ) === 1 ) { - $html_after = preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_after[1] ); - $html_after = call_user_func( $sanitizeFunction, $html_after ); - } else { - $html_after = ''; - } - - // remove string between the [ ] control delimiters - $match = preg_replace( '/\[[^\]]*\]/m', '', $match ); - - // remove the {{ }} control delimiters - $match = preg_replace( '/(\{\{)|(\}\})/m', '', $match ); - - // remove whitspace - $match = trim( $match ); - - // we accept : and # as separator cause the : delimiter wasn't working when using the template tag in a href links in the template (like ) - $path = preg_split( '/(\:|\#)/', $match, 2 ); - if ( isset( $path[0] ) && isset( $path[1] ) ) { - - $post = null; - if ( array_key_exists( $path[0], $objects ) ) { - $post = $objects[ $path[0] ]; - } - - $rendered_template_tag = CB::get( commonsbooking_getCBType( $path[0] ), $path[1], $post, null, $sanitizeFunction ); - if ( $rendered_template_tag !== null && strlen( $rendered_template_tag ) > 0 ) { - return $html_before . $rendered_template_tag . $html_after; - } else { - return $rendered_template_tag; - } - } - - return false; - } + if ( isset( $match[0] ) ) { + $match = $match[0]; + + // extract the html before part, looking for {{[*] pattern + if ( preg_match( '/\{\{\[([^\]]*)\]/m', $match, $html_before ) === 1 ) { + $html_before = preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_before[1] ); + $html_before = call_user_func( $sanitizeFunction, $html_before ); + } else { + $html_before = ''; + } + + // extract the html after part looking for [*]}} pattern + if ( preg_match( '/\[([^\]]*)\]\}\}/m', $match, $html_after ) === 1 ) { + $html_after = preg_replace( '/(\{\{)|(\}\})|(\[)|(\])/m', '', $html_after[1] ); + $html_after = call_user_func( $sanitizeFunction, $html_after ); + } else { + $html_after = ''; + } + + // remove string between the [ ] control delimiters + $match = preg_replace( '/\[[^\]]*\]/m', '', $match ); + + // remove the {{ }} control delimiters + $match = preg_replace( '/(\{\{)|(\}\})/m', '', $match ); + + // remove whitspace + $match = trim( $match ); + + // we accept : and # as separator cause the : delimiter wasn't working when using the template tag in a href links in the template (like ) + $path = preg_split( '/(\:|\#)/', $match, 2 ); + if ( isset( $path[0] ) && isset( $path[1] ) ) { + $post = null; + if ( array_key_exists( $path[0], $objects ) ) { + $post = $objects[ $path[0] ]; + } + + $rendered_template_tag = CB::get( commonsbooking_getCBType( $path[0] ), $path[1], $post, null, $sanitizeFunction ); + if ( $rendered_template_tag !== null && strlen( $rendered_template_tag ) > 0 ) { + return $html_before . $rendered_template_tag . $html_after; + } else { + return $rendered_template_tag; + } + } + + return false; + } } /** diff --git a/includes/Users.php b/includes/Users.php index be57f0e27..0a3e3fd2e 100644 --- a/includes/Users.php +++ b/includes/Users.php @@ -11,17 +11,19 @@ /** * Checks if current user is allowed to edit custom post. + * * @param $post * * @return bool * @throws Exception */ function commonsbooking_isCurrentUserAllowedToEdit( $post ): bool { - if (! is_user_logged_in()){ return false; } + if ( ! is_user_logged_in() ) { + return false; } $current_user = wp_get_current_user(); - return commonsbooking_isUserAllowedToEdit($post,$current_user); + return commonsbooking_isUserAllowedToEdit( $post, $current_user ); } /** @@ -33,23 +35,23 @@ function commonsbooking_isCurrentUserAllowedToEdit( $post ): bool { * @return bool * @throws Exception */ -function commonsbooking_isUserAllowedToEdit( $post, WP_User $user): bool { +function commonsbooking_isUserAllowedToEdit( $post, WP_User $user ): bool { - if (! Plugin::isPostCustomPostType($post) ){ + if ( ! Plugin::isPostCustomPostType( $post ) ) { return false; } - $postModel = CustomPostType::getModel($post); + $postModel = CustomPostType::getModel( $post ); - //authors are always allowed to edit their posts, admins are also allowed to edit all posts - if ( $postModel->isAuthor($user) || commonsbooking_isUserAdmin( $user ) ) { + // authors are always allowed to edit their posts, admins are also allowed to edit all posts + if ( $postModel->isAuthor( $user ) || commonsbooking_isUserAdmin( $user ) ) { return true; } $canView = commonsbooking_isUserAllowedToSee( $postModel, $user ); - $canEdit = user_can($user, 'edit_post', $post->ID); + $canEdit = user_can( $user, 'edit_post', $post->ID ); - return $canView && $canEdit; + return $canView && $canEdit; } /** @@ -58,9 +60,9 @@ function commonsbooking_isUserAllowedToEdit( $post, WP_User $user): bool { * @param $current_screen */ function commonsbooking_validate_user_on_edit( $current_screen ) { - if ( $current_screen->base == "post" && in_array( $current_screen->id, Plugin::getCustomPostTypesLabels() ) ) { + if ( $current_screen->base == 'post' && in_array( $current_screen->id, Plugin::getCustomPostTypesLabels() ) ) { if ( array_key_exists( 'action', $_GET ) && $_GET['action'] == 'edit' ) { - $post = get_post( intval($_GET['post']) ); + $post = get_post( intval( $_GET['post'] ) ); if ( ! commonsbooking_isCurrentUserAllowedToEdit( $post ) ) { die( 'Access denied' ); } @@ -79,11 +81,10 @@ function commonsbooking_validate_user_on_edit( $current_screen ) { function commonsbooking_modify_admin_bar() { global $wp_admin_bar; global $post; - //check for CPT before evaluation of permission, use short-circuit to prevent invalid data access - if ( Plugin::isPostCustomPostType($post) && ! commonsbooking_isCurrentUserAllowedToEdit( $post ) ) { + // check for CPT before evaluation of permission, use short-circuit to prevent invalid data access + if ( Plugin::isPostCustomPostType( $post ) && ! commonsbooking_isCurrentUserAllowedToEdit( $post ) ) { $wp_admin_bar->remove_menu( 'edit' ); } - } add_action( 'wp_before_admin_bar_render', 'commonsbooking_modify_admin_bar' ); @@ -97,12 +98,12 @@ function ( $posts, $query ) { if ( is_admin() && array_key_exists( 'post_type', $query->query ) ) { // Post type of current list $postType = $query->query['post_type']; - //return when it is not our CPT + // return when it is not our CPT if ( ! in_array( $postType, Plugin::getCustomPostTypesLabels() ) ) { return $posts; } - $isAdmin = commonsbooking_isCurrentUserAdmin(); + $isAdmin = commonsbooking_isCurrentUserAdmin(); // Check if it is the main query if ( ! $isAdmin && $query->is_main_query() ) { @@ -114,9 +115,9 @@ function ( $posts, $query ) { } // Save posts to global variable for later use -> fix of counts in admin lists - if( - array_key_exists('post_type', $_GET) && - is_array($query->query) && array_key_exists('post_type', $query->query) + if ( + array_key_exists( 'post_type', $_GET ) && + is_array( $query->query ) && array_key_exists( 'post_type', $query->query ) ) { global ${'posts' . $query->query['post_type']}; ${'posts' . $query->query['post_type']} = $posts; @@ -143,7 +144,7 @@ function commonsbooking_custom_view_count( $views ) { // fixes counts for custom posts countings in admin list function commonsbooking_fix_view_counts( $postType, $views ) { // admin is allowed to see all posts - if( commonsbooking_isCurrentUserAdmin() ){ + if ( commonsbooking_isCurrentUserAdmin() ) { return $views; } @@ -151,7 +152,7 @@ function commonsbooking_fix_view_counts( $postType, $views ) { $timeFramePosts = ${'posts' . $postType}; $counts = [ - 'all' => count( $timeFramePosts ) + 'all' => count( $timeFramePosts ), ]; // add counts for differentp states @@ -160,7 +161,7 @@ function commonsbooking_fix_view_counts( $postType, $views ) { $counts[ $post->post_status ] = 0; } - $counts[ $post->post_status ] ++; + ++$counts[ $post->post_status ]; } // replace output @@ -174,7 +175,8 @@ function commonsbooking_fix_view_counts( $postType, $views ) { // Check if current user has admin role function commonsbooking_isCurrentUserAdmin() { - if (! is_user_logged_in() ) { return false; } + if ( ! is_user_logged_in() ) { + return false; } $user = wp_get_current_user(); return apply_filters( 'commonsbooking_isCurrentUserAdmin', commonsbooking_isUserAdmin( $user ) ); @@ -186,13 +188,13 @@ function commonsbooking_isCurrentUserAdmin() { * * An admin is allowed to edit and see all posts. * - * @param \WP_User $user + * @param \WP_User $user * * @return bool */ -function commonsbooking_isUserAdmin(\WP_User $user) { - foreach (\CommonsBooking\Repository\UserRepository::getAdminRoles() as $adminRole) { - if (in_array($adminRole, $user->roles)) { +function commonsbooking_isUserAdmin( \WP_User $user ) { + foreach ( \CommonsBooking\Repository\UserRepository::getAdminRoles() as $adminRole ) { + if ( in_array( $adminRole, $user->roles ) ) { return true; } } @@ -226,7 +228,6 @@ function commonsbooking_isCurrentUserCBManager() { $isManager = ! empty( array_intersect( \CommonsBooking\Repository\UserRepository::getManagerRoles(), $user->roles ) ); return apply_filters( 'commonsbooking_isCurrentUserCBManager', $isManager, $user ); - } /** @@ -236,15 +237,15 @@ function commonsbooking_isCurrentUserCBManager() { * * @return bool */ -function commonsbooking_isCurrentUserAllowedToBook( $timeframeID ):bool { +function commonsbooking_isCurrentUserAllowedToBook( $timeframeID ): bool { $allowedUserRoles = get_post_meta( $timeframeID, \CommonsBooking\Model\Timeframe::META_ALLOWED_USER_ROLES, true ); if ( empty( $allowedUserRoles ) || ( commonsbooking_isCurrentUserAdmin() ) ) { return true; } - $current_user = wp_get_current_user(); - $user_roles = $current_user->roles; + $current_user = wp_get_current_user(); + $user_roles = $current_user->roles; $match = array_intersect( $user_roles, $allowedUserRoles ); @@ -260,21 +261,20 @@ function commonsbooking_isCurrentUserAllowedToBook( $timeframeID ):bool { * * @return void */ -function commonsbooking_isCurrentUserAllowedToSee( $booking ):bool{ - if (! is_user_logged_in()){ return false; } +function commonsbooking_isCurrentUserAllowedToSee( $booking ): bool { + if ( ! is_user_logged_in() ) { + return false; } if ( ! $booking ) { - return false; - } - - $user = wp_get_current_user(); + return false; + } - if ($user){ - return commonsbooking_isUserAllowedToSee( $booking, $user ); - } - else { - return false; - } + $user = wp_get_current_user(); + if ( $user ) { + return commonsbooking_isUserAllowedToSee( $booking, $user ); + } else { + return false; + } } /** @@ -285,40 +285,37 @@ function commonsbooking_isCurrentUserAllowedToSee( $booking ):bool{ * We apply the logic, that only something that is allowed to be seen may be edited. * * @param \CommonsBooking\Model\Booking|WP_Post|int $post - * @param WP_User $user + * @param WP_User $user * * @return bool */ -function commonsbooking_isUserAllowedToSee( $post, WP_User $user): bool -{ +function commonsbooking_isUserAllowedToSee( $post, WP_User $user ): bool { - if (! $post instanceof \CommonsBooking\Model\CustomPost) { - if (! Plugin::isPostCustomPostType($post) ) { + if ( ! $post instanceof \CommonsBooking\Model\CustomPost ) { + if ( ! Plugin::isPostCustomPostType( $post ) ) { return false; } try { - $postModel = CustomPostType::getModel($post); - } catch (Exception $e) { + $postModel = CustomPostType::getModel( $post ); + } catch ( Exception $e ) { return false; } - } - else { + } else { $postModel = $post; } + $isAuthor = $postModel->isAuthor( $user ); + $isAdmin = commonsbooking_isUserAdmin( $user ); + $isAllowed = $isAdmin || $isAuthor; - $isAuthor = $postModel->isAuthor( $user ); - $isAdmin = commonsbooking_isUserAdmin( $user ); - $isAllowed = $isAdmin || $isAuthor; - - if ( ! $isAllowed) { - $admins = $postModel->getAdmins(); - $isAllowed = (is_string( $admins ) && $user->ID == $admins) || - (is_array( $admins ) && in_array( $user->ID , $admins, true )); - } + if ( ! $isAllowed ) { + $admins = $postModel->getAdmins(); + $isAllowed = ( is_string( $admins ) && $user->ID == $admins ) || + ( is_array( $admins ) && in_array( $user->ID, $admins, true ) ); + } - return $isAllowed; + return $isAllowed; } /** @@ -332,11 +329,10 @@ function commonsbooking_isUserAllowedToSee( $post, WP_User $user): bool * * @return bool */ -function commonsbooking_isUIDHashComboCorrect( $user_id, $user_hash): bool { - if (wp_hash($user_id) == $user_hash) { +function commonsbooking_isUIDHashComboCorrect( $user_id, $user_hash ): bool { + if ( wp_hash( $user_id ) == $user_hash ) { return true; - } - else { + } else { return false; } } diff --git a/languages/commonsbooking-de_DE.po b/languages/commonsbooking-de_DE.po index 9789fcdbf..afe5b1b9d 100644 --- a/languages/commonsbooking-de_DE.po +++ b/languages/commonsbooking-de_DE.po @@ -33,21 +33,20 @@ msgstr "wielebenwir e.V." msgid "https://wielebenwir.de/" msgstr "https://wielebenwir.de/" -#: src/Wordpress/CustomPostType/Timeframe.php:124 +#: src/Wordpress/CustomPostType/Timeframe.php:127 msgid "All timeframe types" msgstr "Alle Zeitrahmen-Typen" -#: includes/OptionsArray.php:40 +#: includes/OptionsArray.php:39 msgid "Welcome" msgstr "Willkommen" -#: includes/OptionsArray.php:46 +#: includes/OptionsArray.php:45 #: templates/dashboard-index.php:8 msgid "Welcome to CommonsBooking" msgstr "Willkommen bei CommonsBooking" -#. translators: %s = version number -#: includes/OptionsArray.php:50 +#: includes/OptionsArray.php:51 msgid "" "You are using CommonsBooking Version %s\n" "\n" @@ -71,120 +70,117 @@ msgstr "" "

Mitmachen?

\n" " Die Zukunft dieses Plugins ist abhängig von deiner Unterstützung. Du kannst uns mit einer Spende unterstützen unter: wielebenwir.de" -#: includes/OptionsArray.php:70 +#: includes/OptionsArray.php:76 msgid "General" msgstr "Allgemein" -#: includes/OptionsArray.php:75 +#: includes/OptionsArray.php:81 msgid "Naming and permalinks" msgstr "Namen und Permalinks" -#: includes/OptionsArray.php:79 +#: includes/OptionsArray.php:86 msgid "Customize names & slugs. You can set an individual slug for items and locations to create individual permalinks.
Notice: If the new settings do not work directly (you will get a 404 page error on frontend pages), you must click on the Settings -> Permalinks page after saving these settings to refresh the Wordpress permalink settings." msgstr "Passe Namen & Slugs an. Du kannst individuelle Slugs für Artikel und Standorte festlegen, um individuelle Permalinks zu erstellen.
Hinweis: Sollten die Änderungen nicht sofort funktionieren (404 Seite nicht gefunden wird auf der Webseite angezeigt), müsstest Du nach dem Speichern dieser Einstellungen auf die Seite Einstellungen -> Permalinks klicken, um die WordPress Permalink-Einstellungen zu aktualisieren." -#: includes/OptionsArray.php:84 +#: includes/OptionsArray.php:93 msgid "Items slug" msgstr "Artikel slug" -#. translators: %s = example url (like website.com/cb-items/) -#: includes/OptionsArray.php:88 +#: includes/OptionsArray.php:99 msgid "The slug for article detail page. Type in the slug without slashes. Example: cb_item or article. The url for the items detail will be like %s" msgstr "Die Slug für Artikel Detailseite. Gib den Slug ohne Schrägstriche ein. Beispiel: cb-artikel oder artikel. Die URL für die Artikel-Detailseite lautet dann z.b: %s" -#: includes/OptionsArray.php:95 +#: includes/OptionsArray.php:110 msgid "Locations slug" msgstr "Standorte Slug" -#. translators: %s = example url (like website.com/cb-locations/) -#: includes/OptionsArray.php:99 +#: includes/OptionsArray.php:116 msgid "The slug for location detail page. Type in the slug without slashes. Example: cb_location or location. The url for the items detail will be like %s" msgstr "Die Slug für die Standort Detailseite. Gib den Slug ohne Schrägstriche ein. Beispiel: cb-standort oder Standort. Die URL für die Standort-Detailseite lautet dann z.b: %s" -#: includes/OptionsArray.php:106 +#: includes/OptionsArray.php:127 msgid "Bookings Page" msgstr "Buchungsseite" -#. translators: %s = example url (like website.com/cb-locations/) -#: includes/OptionsArray.php:110 +#: includes/OptionsArray.php:133 msgid "The page where you included the [cb_bookings] shortcode. This is used in the Users Widget" msgstr "Die Seite, auf der Du den [cb_bookings]-Kurzcode eingefügt hast. Dies wird im Benutzer*in Widget verwendet" -#: includes/OptionsArray.php:119 -#: includes/OptionsArray.php:133 +#: includes/OptionsArray.php:146 +#: includes/OptionsArray.php:160 msgid "Booking comment" msgstr "Buchungskommentar" -#: includes/OptionsArray.php:123 +#: includes/OptionsArray.php:150 msgid "Activate booking comments in booking page" msgstr "Aktiviere Buchungskommentare auf der Buchungsseite" -#: includes/OptionsArray.php:125 +#: includes/OptionsArray.php:152 msgid "If enabled, users can enter an internal comment about their booking on the booking confirmation page. This comment can be included in the booking confirmation email." msgstr "Wenn diese Option aktiviert ist, können Nutzende auf der Buchungsbestätigungsseite einen internen Kommentar zu ihrer Buchung eingeben. Dieser Kommentar kann in die Buchungsbestätigungs-E-Mail integriert werden." -#: includes/OptionsArray.php:129 +#: includes/OptionsArray.php:156 msgid "Headline above the comment field in frontend" msgstr "Überschrift über dem Kommentarfeld im Frontend" -#: includes/OptionsArray.php:131 +#: includes/OptionsArray.php:158 msgid "Text that will be shown above the comment field in the booking confirmation page." msgstr "Text, der über dem Kommentarfeld auf der Buchungsbestätigungsseite angezeigt wird." -#: includes/OptionsArray.php:136 +#: includes/OptionsArray.php:163 msgid "Description" msgstr "Beschreibung" -#: includes/OptionsArray.php:138 +#: includes/OptionsArray.php:165 msgid "Short infotext to inform the user how the comment field will be used (e.g. only internal comment etc.) " msgstr "Kurzer Infotext zur Information des Benutzenden, wie das Kommentarfeld verwendet wird (z.B. nur interner Kommentar etc.) " -#: includes/OptionsArray.php:140 +#: includes/OptionsArray.php:167 msgid "Here you can leave a comment about your booking. This will be sent to the station." msgstr "Hier ein Kommentar zur Buchung eingegeben werden. Dieser wird an die Station gesendet." -#: src/Wordpress/CustomPostType/Timeframe.php:734 -#: src/Wordpress/CustomPostType/Timeframe.php:758 -#: src/Wordpress/CustomPostType/Timeframe.php:781 +#: src/Wordpress/CustomPostType/Timeframe.php:751 +#: src/Wordpress/CustomPostType/Timeframe.php:780 +#: src/Wordpress/CustomPostType/Timeframe.php:803 msgid "Booking Codes" msgstr "Buchungs-Codes" -#: includes/OptionsArray.php:229 +#: includes/OptionsArray.php:266 msgid "Templates" msgstr "Vorlagen" -#: includes/OptionsArray.php:234 +#: includes/OptionsArray.php:271 msgid "Email templates" msgstr "E-Mail Vorlagen" -#: includes/OptionsArray.php:238 -#: includes/OptionsArray.php:581 +#: includes/OptionsArray.php:275 +#: includes/OptionsArray.php:645 msgid "Mail-Header from E-Mail" msgstr "Absender E-Mail Mail-Adresse" -#: includes/OptionsArray.php:239 +#: includes/OptionsArray.php:276 msgid "E-Mail that will be shown as sender in generated emails" msgstr "E-Mail, die als Absender in automatisch versendeten E-Mails angezeigt wird" -#: includes/OptionsArray.php:245 -#: includes/OptionsArray.php:588 +#: includes/OptionsArray.php:282 +#: includes/OptionsArray.php:652 msgid "Mail-Header from Name" msgstr "Absender E-Mail Name" -#: includes/OptionsArray.php:246 -#: includes/OptionsArray.php:589 +#: includes/OptionsArray.php:283 +#: includes/OptionsArray.php:653 msgid "Name that will be shown as sender in generated emails" msgstr "Name, der als Absender in automatisch versendeten E-Mails angezeigt wird" -#: includes/OptionsArray.php:252 +#: includes/OptionsArray.php:289 msgid "Mail-Signature" msgstr "E-Mail-Signatur" -#: includes/OptionsArray.php:253 +#: includes/OptionsArray.php:290 msgid "E-Mail signature that will appear wherever you put {{booking:getEmailSignature}}" msgstr "E-Mail-Signatur, die überall dort erscheint, wo Du {{booking:getEmailSignature}} eingibst." -#: includes/OptionsArray.php:256 +#: includes/OptionsArray.php:294 msgid "" "\n" "

\n" @@ -198,19 +194,19 @@ msgstr "" "das Team.\n" "

\t\t\t\t\t" -#: includes/OptionsArray.php:263 +#: includes/OptionsArray.php:305 msgid "Booking confirmed email subject" msgstr "E-Mail-Betreff für bestätigte Buchungen" -#: includes/OptionsArray.php:267 +#: includes/OptionsArray.php:310 msgid "Your booking {{item:post_title}} at {{location:post_title}} {{booking:formattedBookingDate}} " msgstr "Deine Buchung von {{item:post_title}} am Standort {{location:post_title}} {{booking:formattedBookingDate}} " -#: includes/OptionsArray.php:271 +#: includes/OptionsArray.php:317 msgid "Booking confirmed email body" msgstr "E-Mail-Text für bestätige Buchungen" -#: includes/OptionsArray.php:275 +#: includes/OptionsArray.php:322 msgid "" "\n" "Hi {{user:first_name}},
\n" @@ -265,36 +261,36 @@ msgstr "" "{{booking:getEmailSignature}}\n" " " -#: includes/OptionsArray.php:303 +#: includes/OptionsArray.php:354 msgid "Attach iCalendar file to booking email" msgstr "iCalendar Datei an Buchungsmail anhängen" -#: includes/OptionsArray.php:306 +#: includes/OptionsArray.php:357 msgid "Will attach an iCalendar compatible file for users to import in their respective calendar application." msgstr "Hängt eine iCalendar kompatible Datei an die Buchung an, die Nutzende in ihre digitalen Kalender importieren können." -#: includes/OptionsArray.php:309 +#: includes/OptionsArray.php:360 msgid "iCalendar event title" msgstr "iCalendar Termin Titel" -#: includes/OptionsArray.php:312 +#: includes/OptionsArray.php:363 msgid "The title of the attached event" msgstr "Der Titel des angehängten Termins" -#: includes/OptionsArray.php:313 -#: includes/OptionsArray.php:1357 +#: includes/OptionsArray.php:365 +#: includes/OptionsArray.php:1504 msgid "{{item:post_title}} at {{location:post_title}}" msgstr "{{item:post_title}} am Standort {{location:post_title}}." -#: includes/OptionsArray.php:317 +#: includes/OptionsArray.php:372 msgid "iCalendar event description" msgstr "iCalendar Termin Beschreibung" -#: includes/OptionsArray.php:320 +#: includes/OptionsArray.php:375 msgid "The description for the attached event." msgstr "Die Beschreibung des angehängten Termins." -#: includes/OptionsArray.php:321 +#: includes/OptionsArray.php:377 msgid "" " Pick up: {{booking:pickupDatetime}}\n" "Return date: {{booking:returnDatetime}}\n" @@ -306,19 +302,19 @@ msgstr "" "{{location:formattedPickupInstructions}}\n" "{{booking:formattedBookingCode}} " -#: includes/OptionsArray.php:328 +#: includes/OptionsArray.php:387 msgid "Booking canceled email subject" msgstr "E-Mail-Betreff für stornierte Buchungen" -#: includes/OptionsArray.php:331 +#: includes/OptionsArray.php:390 msgid "Booking canceled: {{item:post_title}} at {{location:post_title}} {{booking:formattedBookingDate}}" msgstr "Buchung storniert: {{item:post_title}} am Standort {{location:post_title}} {{booking:formattedBookingDate}}" -#: includes/OptionsArray.php:334 +#: includes/OptionsArray.php:393 msgid "Booking canceled email body" msgstr "E-Mail-Text für stornierte Buchungen" -#: includes/OptionsArray.php:337 +#: includes/OptionsArray.php:397 msgid "" "\n" "Hi {{user:first_name}},
\n" @@ -336,270 +332,270 @@ msgstr "" "{{booking:getEmailSignature}}\n" " " -#: includes/OptionsArray.php:351 +#: includes/OptionsArray.php:415 msgid "Template and booking process messages" msgstr "Template und Buchungsprozess-Meldungen" -#: includes/OptionsArray.php:356 +#: includes/OptionsArray.php:420 msgid "Booking confirmed message" msgstr "Text für bestätigte Buchungen" -#: includes/OptionsArray.php:359 +#: includes/OptionsArray.php:423 msgid "This text is shown as a status message on booking page after a user has confirmed the booking" msgstr "Dieser Text wird als Statusmeldung auf der Buchungsseite angezeigt, nachdem die/der Benutzende die Buchung bestätigt hat" -#: includes/OptionsArray.php:360 +#: includes/OptionsArray.php:424 msgid "Your booking is confirmed. A confirmation mail has been sent to you." msgstr "Deine Buchung wurde bestätigt. Du hast eine Bestätigungs-E-Mail erhalten." -#: includes/OptionsArray.php:363 +#: includes/OptionsArray.php:427 msgid "Item not available" msgstr "Artikel nicht verfügbar" -#: includes/OptionsArray.php:366 +#: includes/OptionsArray.php:430 msgid "This text is shown on item listings (shortcode cb_items) and item detail page if there is no valid bookable timeframe set for this item" msgstr "Dieser Text wird auf Artikellisten (Shortcode cb_items) und der Artikeldetailseite angezeigt, wenn kein gültiger buchbarer Zeitrahmen für diesen Artikel festgelegt" -#: includes/OptionsArray.php:367 +#: includes/OptionsArray.php:431 msgid "This item is currently not bookable." msgstr "Dieser Artikel ist derzeit nicht buchbar." -#: includes/OptionsArray.php:370 +#: includes/OptionsArray.php:434 msgid "Location without available items" msgstr "Standort ohne verfügbare Artikel" -#: includes/OptionsArray.php:373 +#: includes/OptionsArray.php:437 msgid "This text is shown on location listings and location detail page if there are no items available at this location" msgstr "Dieser Text wird auf der Standortliste und auf der Standortdetailseite angezeigt, wenn an diesem Standort keine Artikel verfügbar sind" -#: includes/OptionsArray.php:374 +#: includes/OptionsArray.php:438 msgid "No items available at this location right now." msgstr "Keine Artikel an diesem Standort verfügbar." -#: includes/OptionsArray.php:377 +#: includes/OptionsArray.php:441 msgid "Show contactdetails on booking without confirmation?" msgstr "Kontaktdaten bei Buchung ohne Bestätigung anzeigen?" -#: includes/OptionsArray.php:380 +#: includes/OptionsArray.php:444 msgid "If activated the contactdetails (e.g. phone number, pickupinstructions) will be shown on booking page even if the booking is not confirmed by user. Otherwise these info will be shown only after booking is confirmed" msgstr "Bei Aktivierung werden die Kontaktdaten (z.B. Telefonnummer, Abholanweisungen) auf der Buchungsseite angezeigt, auch wenn die Buchung vom Nutzenden nicht bestätigt ist. Andernfalls werden diese Informationen erst angezeigt, nachdem die Buchung bestätigt wurde" -#: includes/OptionsArray.php:383 +#: includes/OptionsArray.php:447 msgid "Infotext hidden contactdetails" msgstr "Infotext, wenn Kontaktdetails nicht angezeigt werden" -#: includes/OptionsArray.php:386 +#: includes/OptionsArray.php:450 msgid "This text is displayed when contact details of the station are shown only after booking confirmation." msgstr "Dieser Text wird angezeigt, wenn die Kontaktdaten des Standorts erst nach Buchungsbestätigung angezeigt werden." -#: includes/OptionsArray.php:387 +#: includes/OptionsArray.php:451 msgid "Please confirm the booking to see the contact details for pickup and return." msgstr "Bitte bestätige die Buchung, um die Kontaktdaten für die Abholung und Rückgabe zu sehen." -#: includes/OptionsArray.php:390 +#: includes/OptionsArray.php:454 msgid "Text book this item on booking page" msgstr "Text für diesen Artikel buchen auf der Buchungsseite" -#: includes/OptionsArray.php:393 +#: includes/OptionsArray.php:457 msgid "This text is displayed on a booking detail page above the booking calendar ." msgstr "Dieser Text wird auf einer Buchungsdetailseite über dem Buchungskalender angezeigt." -#: includes/OptionsArray.php:394 +#: includes/OptionsArray.php:458 msgid "Book this item at this location" msgstr "Buche den Artikel an dieser Station" -#: includes/OptionsArray.php:397 +#: includes/OptionsArray.php:461 msgid "Label for booking button" msgstr "Text für \"Buchen\"-Button" -#: includes/OptionsArray.php:400 +#: includes/OptionsArray.php:464 msgid "This text is displayed on the booking button on item/location listing pages." msgstr "Dieser Text wird auf dem Buchungs-Button auf den Artikel-/Standortlistenseiten angezeigt." -#: includes/OptionsArray.php:401 +#: includes/OptionsArray.php:465 msgid "Book item" msgstr "Artikel buchen" -#: includes/OptionsArray.php:404 +#: includes/OptionsArray.php:468 msgid "User details on booking page" msgstr "Benutzer*innen-Details auf der Buchungsseite" -#: includes/OptionsArray.php:407 +#: includes/OptionsArray.php:471 msgid "This textblock is displayed on the booking details page. Please use template-tags to fill in user details" msgstr "Dieser Text wird auf einer Buchungsdetailseite angezeigt. Bitte nutze Template-Tags, um Kontaktdaten von Nutzenden einzufügen" -#: includes/OptionsArray.php:408 +#: includes/OptionsArray.php:472 msgid "{{[Phone: ]user:phone}}
{{[Address: ]user:address}}" msgstr "{{[Telefon: ]user:phone}}
{{[Adresse: ]user:address}}" -#: includes/OptionsArray.php:418 +#: includes/OptionsArray.php:482 msgid "Image formatting" msgstr "Bildformatierung" -#: includes/OptionsArray.php:423 +#: includes/OptionsArray.php:487 msgid "Listing image small width (in px)" msgstr "Breite des kleinen Listenbildes (in px)" -#: includes/OptionsArray.php:426 +#: includes/OptionsArray.php:490 msgid "Defines the image width of small images in location and item listings" msgstr "Definiert die Bildbreite von kleinen Bildern in Standort- und Artikellisten" -#: includes/OptionsArray.php:433 +#: includes/OptionsArray.php:497 msgid "Listing image small height (in px)" msgstr "Höhe des kleinen Listenbildes (in px)" -#: includes/OptionsArray.php:436 +#: includes/OptionsArray.php:500 msgid "Defines the image height of small images in location and item listings" msgstr "Definiert die Bildhöhe von kleinen Bildern in Standort- und Artikellisten" -#: includes/OptionsArray.php:443 +#: includes/OptionsArray.php:507 msgid "Listing image medium width (in px)" msgstr "Breite des mittleren Listenbildes (in px)" -#: includes/OptionsArray.php:446 +#: includes/OptionsArray.php:510 msgid "Defines the image width of medium images in location and item listings" msgstr "Definiert die Bildbreite von mittleren Bildern in Standort- und Artikellisten" -#: includes/OptionsArray.php:453 +#: includes/OptionsArray.php:517 msgid "Listing image medium height (in px)" msgstr "Höhe des mittleren Listenbildes (in px)" -#: includes/OptionsArray.php:456 +#: includes/OptionsArray.php:520 msgid "Defines the image height of medium images in location and item listings" msgstr "Definiert die Bildhöhe mittlerer Bilder in Standort- und Artikellisten" -#: includes/OptionsArray.php:463 +#: includes/OptionsArray.php:527 msgid "Crop images" msgstr "Bilder beschneiden" -#: includes/OptionsArray.php:466 +#: includes/OptionsArray.php:530 msgid "If checked the image will be cropped to specified dimensions using center crop positions" msgstr "Wenn diese Option aktiviert ist, wird das Bild mithilfe der mittleren Zuschneidepositionen auf die angegebenen Abmessungen zugeschnitten" -#: includes/OptionsArray.php:475 +#: includes/OptionsArray.php:539 msgid "Color schemes" msgstr "Farbschema" -#: includes/OptionsArray.php:480 +#: includes/OptionsArray.php:544 msgid "Base color" msgstr "Grundfarbe" -#: includes/OptionsArray.php:483 +#: includes/OptionsArray.php:547 msgid "Defines the color that is used in headings and buttons" msgstr "Definiert die Farbe, die in Überschriften und für Knöpfe genutzt wird" -#: includes/OptionsArray.php:487 +#: includes/OptionsArray.php:551 msgid "Secondary color" msgstr "Sekundärfarbe" -#: includes/OptionsArray.php:490 +#: includes/OptionsArray.php:554 msgid "The color shown when hovering a button or a link" msgstr "Definiert die Farbe für ausgewählte Knöpfe und Links" -#: includes/OptionsArray.php:494 +#: includes/OptionsArray.php:558 msgid "Button color" msgstr "Button Farbe" -#: includes/OptionsArray.php:497 +#: includes/OptionsArray.php:561 msgid "The default color for buttons" msgstr "Die Standardfarbe für Knöpfe" -#: includes/OptionsArray.php:501 +#: includes/OptionsArray.php:565 msgid "Confirmation / Available Color" msgstr "Bestätigung / Verfügbar Farbe" -#: includes/OptionsArray.php:504 +#: includes/OptionsArray.php:568 msgid "The color that is used to signify if an item is available or that an action has been completed successfully" msgstr "Die Farbe die benutzt wird um darzustellen, dass ein Artikel verfügbar ist oder, dass eine Aktion erfolgreich beendet wurde" -#: includes/OptionsArray.php:509 +#: includes/OptionsArray.php:573 msgid "Cancel / Not Available Color" msgstr "Abbrechen / Nicht verfügbar Farbe" -#: includes/OptionsArray.php:512 +#: includes/OptionsArray.php:576 msgid "The color that is used to signify if an item is unavailable or for buttons to abort actions" msgstr "Die Farbe, die benutzt wird um darzustellen, dass ein Artikel blockiert ist oder, für Knöpfe mit denen Aktionen abgebrochen werden können" -#: includes/OptionsArray.php:517 +#: includes/OptionsArray.php:581 msgid "Temporarily Unavailable Color" msgstr "Temporär nicht verfügbar Farbe" -#: includes/OptionsArray.php:520 +#: includes/OptionsArray.php:584 msgid "The color that is used to signify if an item is temporarily unbookable (i.e. holiday)" msgstr "Die Farbe, die benutzt wird um einen temporär nicht buchbaren Artikel darzustellen (z.B. Urlaubstage)" -#: includes/OptionsArray.php:525 +#: includes/OptionsArray.php:589 msgid "Greyed out Color" msgstr "Ausgegraut Farbe" -#: includes/OptionsArray.php:528 +#: includes/OptionsArray.php:592 msgid "The color used to signify that no timeframe has been created for an item or a button that is not yet clickable" msgstr "Die Farbe die verwendet wird um anzuzeigen, dass kein Zeitrahmen für einen Artikel erstellt wurde oder, dass ein Knopf noch nicht klickbar ist" -#: includes/OptionsArray.php:533 +#: includes/OptionsArray.php:597 msgid "Background Color" msgstr "Hintergrundfarbe" -#: includes/OptionsArray.php:536 +#: includes/OptionsArray.php:600 msgid "The color used for the background of tables and similar elements" msgstr "Die Hintergrundfarbe, die für den Hintergrund von Tabellen und ähnlichen Elementen verwendet wird" -#: includes/OptionsArray.php:541 +#: includes/OptionsArray.php:605 msgid "Notice Background Color" msgstr "Hinweis Hintergrundfarbe" -#: includes/OptionsArray.php:544 +#: includes/OptionsArray.php:608 msgid "The color used for the background of notices" msgstr "Die Farbe, die im Hintergrund von Hinweistexten verwendet wird" -#: includes/OptionsArray.php:548 +#: includes/OptionsArray.php:612 msgid "Light text color" msgstr "Helle Schriftfarbe" -#: includes/OptionsArray.php:551 +#: includes/OptionsArray.php:615 msgid "The color used for light text on dark backgrounds" msgstr "Die Farbe, die für hellen Text auf dunklem Hintergrund verwendet wird" -#: includes/OptionsArray.php:555 +#: includes/OptionsArray.php:619 msgid "Dark text color" msgstr "Dunkle Schriftfarbe" -#: includes/OptionsArray.php:558 +#: includes/OptionsArray.php:622 msgid "The color used for dark text on light backgrounds" msgstr "Die Farbe, die für dunklen Text auf hellem Hintergrund verwendet wird" -#: includes/OptionsArray.php:571 -#: src/Wordpress/CustomPostType/Restriction.php:308 -#: src/Wordpress/CustomPostType/Restriction.php:329 +#: includes/OptionsArray.php:635 +#: src/Wordpress/CustomPostType/Restriction.php:311 +#: src/Wordpress/CustomPostType/Restriction.php:332 #: templates/dashboard-index.php:47 msgid "Restrictions" msgstr "Einschränkungen" -#: includes/OptionsArray.php:576 +#: includes/OptionsArray.php:640 msgid "Manage Item Restriction Templates" msgstr "Verwaltung der Vorlagen für Einschränkungen" -#: includes/OptionsArray.php:577 +#: includes/OptionsArray.php:641 msgid "Templates for restriction emails.
More Information in the documentation" msgstr "Vorlagen für Einschränkungs-E-Mails.
Weitere Informationen in der Dokumentation" -#: includes/OptionsArray.php:582 +#: includes/OptionsArray.php:646 msgid "Email that will be shown as sender in generated emails" msgstr "E-Mail, die als Absender in automatisch versendeten E-Mails angezeigt wird" -#: includes/OptionsArray.php:597 +#: includes/OptionsArray.php:661 msgid "Breakdown email subject" msgstr "Ausfall E-Mail Betreff" -#: includes/OptionsArray.php:600 +#: includes/OptionsArray.php:664 msgid "Breakdown of {{item:post_title}} for your booking {{booking:formattedBookingDate}}" msgstr "Ausfall von {{item:post_title}} für deine Buchung {{booking:formattedBookingDate}}" -#: includes/OptionsArray.php:603 +#: includes/OptionsArray.php:667 msgid "Breakdown email body" msgstr "E-Mail-Text für Ausfall" -#: includes/OptionsArray.php:606 +#: includes/OptionsArray.php:671 msgid "" "

Hello {{user:first_name}},

\n" "\n" @@ -629,19 +625,19 @@ msgstr "" " {{booking:getEmailSignature}}\n" " " -#: includes/OptionsArray.php:623 +#: includes/OptionsArray.php:692 msgid "Usage restriction email subject" msgstr "E-Mail-Betreff der Verwendungseinschränkung" -#: includes/OptionsArray.php:626 +#: includes/OptionsArray.php:695 msgid "Restriction of use for {{item:post_title}} for your booking {{booking:formattedBookingDate}}" msgstr "Nutzungsbeschränkung für {{item:post_title}} für deine Buchung {{booking:formattedBookingDate}}" -#: includes/OptionsArray.php:629 +#: includes/OptionsArray.php:698 msgid "Restriction email body" msgstr "E-Mail-Text für Einschränkung" -#: includes/OptionsArray.php:632 +#: includes/OptionsArray.php:702 msgid "" "

Hello {{user:first_name}},

\n" "

\n" @@ -683,19 +679,19 @@ msgstr "" "

\n" " {{booking:getEmailSignature}}" -#: includes/OptionsArray.php:655 +#: includes/OptionsArray.php:729 msgid "Restriction cancelled subject" msgstr "E-Mail-Betreff für Aufhebung der Einschränkung" -#: includes/OptionsArray.php:658 +#: includes/OptionsArray.php:732 msgid "Restriction for article {{item:post_title}} no longer exists" msgstr "Einschränkung für Artikel {{item:post_title}}} ist aufgehoben" -#: includes/OptionsArray.php:661 +#: includes/OptionsArray.php:735 msgid "Restriction cancelled email body" msgstr "E-Mail-Text für Aufhebung der Einschränkung" -#: includes/OptionsArray.php:664 +#: includes/OptionsArray.php:739 msgid "" "

Hello {{user:first_name}},

\n" "

The article {{item:post_title}} is now fully usable again.

\n" @@ -715,45 +711,45 @@ msgstr "" "

\n" " {{booking:getEmailSignature}}" -#: includes/OptionsArray.php:784 +#: includes/OptionsArray.php:864 msgid "Reminder" msgstr "Erinnerung" -#: includes/OptionsArray.php:790 +#: includes/OptionsArray.php:870 msgid "Booking reminder" msgstr "Buchungserinnerung" -#: includes/OptionsArray.php:792 +#: includes/OptionsArray.php:873 msgid "You can set here whether users should receive a reminder email before the start of a booking.
More Information in the documentation" msgstr "Hier kannst du einstellen, ob Nutzende vor Beginn einer Buchung eine Erinnerungs-E-Mail erhalten sollen.
Weitere Informationen in der Dokumentation" -#: includes/OptionsArray.php:798 -#: includes/OptionsArray.php:895 -#: includes/OptionsArray.php:931 -#: includes/OptionsArray.php:1000 +#: includes/OptionsArray.php:881 +#: includes/OptionsArray.php:992 +#: includes/OptionsArray.php:1036 +#: includes/OptionsArray.php:1119 msgid "Activate" msgstr "Aktivieren" -#: includes/OptionsArray.php:804 -#: includes/OptionsArray.php:901 -#: includes/OptionsArray.php:938 -#: includes/OptionsArray.php:1007 +#: includes/OptionsArray.php:887 +#: includes/OptionsArray.php:998 +#: includes/OptionsArray.php:1043 +#: includes/OptionsArray.php:1126 msgid "E-mail subject" msgstr "E-Mail Betreff" -#: includes/OptionsArray.php:807 -#: includes/OptionsArray.php:941 +#: includes/OptionsArray.php:890 +#: includes/OptionsArray.php:1046 msgid "Upcoming booking of {{item:post_title}} {{booking:formattedBookingDate}}" msgstr "Bevorstehende Buchung von {{item:post_title}} {{booking:formattedBookingDate}}" -#: includes/OptionsArray.php:810 -#: includes/OptionsArray.php:907 -#: includes/OptionsArray.php:944 -#: includes/OptionsArray.php:1013 +#: includes/OptionsArray.php:893 +#: includes/OptionsArray.php:1004 +#: includes/OptionsArray.php:1049 +#: includes/OptionsArray.php:1132 msgid "email body" msgstr "E-Mail-Text" -#: includes/OptionsArray.php:813 +#: includes/OptionsArray.php:897 msgid "" "

Hi {{user:first_name}},

\n" "

Your booking period for the item {{item:post_title}} will start soon.
\n" @@ -776,31 +772,31 @@ msgstr "" "\n" "{{booking:getEmailSignature}}" -#: includes/OptionsArray.php:827 +#: includes/OptionsArray.php:915 msgid "Sent reminder x days before booking start" msgstr "Sende eine Erinnerung x Tage vor Buchungsbeginn" -#: includes/OptionsArray.php:829 +#: includes/OptionsArray.php:918 msgid "This reminder email will be sent to users x days before the start of the booking. If the booking is made less days before the specified days, no reminder email will be sent" msgstr "Diese Erinnerungs-E-Mail wird x Tage vor Beginn der Buchung an Benutzende gesendet. Wenn die Buchung in weniger als den angegebenen Tagen erfolgt, wird keine Erinnerungs-E-Mail gesendet" -#: includes/OptionsArray.php:843 -#: includes/OptionsArray.php:956 -#: includes/OptionsArray.php:1026 +#: includes/OptionsArray.php:934 +#: includes/OptionsArray.php:1066 +#: includes/OptionsArray.php:1150 msgid "Time" msgstr "Uhrzeit" -#: includes/OptionsArray.php:845 -#: includes/OptionsArray.php:958 -#: includes/OptionsArray.php:1028 +#: includes/OptionsArray.php:937 +#: includes/OptionsArray.php:1069 +#: includes/OptionsArray.php:1153 msgid "Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured." msgstr "Lege fest, wann die Erinnerung gesendet werden soll. Der tatsächliche Versand kann um einige Stunden vom definierten Wert abweichen, je nachdem, wie dein WordPress konfiguriert ist." -#: includes/OptionsArray.php:886 +#: includes/OptionsArray.php:980 msgid "email after booking has ended" msgstr "E-Mail nach Ende der Buchung" -#: includes/OptionsArray.php:888 +#: includes/OptionsArray.php:983 msgid "" "Here you can set whether users should receive an additional e-mail after completing a booking. This can be used, for example, to inquire about the users satisfaction or possible problems during the booking.\n" "\t\t\t\t\t
The email will be sent around midnight after the booking day has ended." @@ -808,11 +804,11 @@ msgstr "" "Hier kannst Du du einstellen, ob Nutzende nach Abschluss einer Buchung eine zusätzliche E-Mail erhalten sollen. Dies kann beispielsweise genutzt werden, um sich nach der Zufriedenheit oder möglichen Problemen bei der Buchung zu erkundigen.\n" "Die E-Mail wird um Mitternacht nach Buchungsende gesendet." -#: includes/OptionsArray.php:904 +#: includes/OptionsArray.php:1001 msgid "Your booking of {{item:post_title}} {{booking:formattedBookingDate}} has ended" msgstr "Deine Buchung von {{item:post_title}} {{booking:formattedBookingDate}} ist beendet" -#: includes/OptionsArray.php:910 +#: includes/OptionsArray.php:1008 msgid "" "

Hi {{user:first_name}},

\n" "

Your booking of {{item:post_title}} at {{location:post_title}} has ended.
\n" @@ -825,270 +821,270 @@ msgstr "" "

Deine Buchung von {{item:post_title}} am Standort {{location:post_title}} ist beendet.
Wir hoffen, dass alles wie erwartet funktioniert hat.
Bitte lass uns uns wissen, wenn Probleme aufgetreten sind.
\n" "{{booking:getEmailSignature}}" -#: includes/OptionsArray.php:1067 +#: includes/OptionsArray.php:1197 msgid "Migration" msgstr "Migration" -#: includes/OptionsArray.php:1085 +#: includes/OptionsArray.php:1215 msgid "Migrate from Commons Booking Version 0.X" msgstr "Migriere von Commons Booking Version 0.X" -#: includes/OptionsArray.php:1087 +#: includes/OptionsArray.php:1217 msgid "Migrate data from CommonsBooking Version 0.X.
The migration includes: locations, items, timeframes and bookings.
If you have clicked \"Migrate\" before, starting the migration again will overwrite any changes you made to locations, items, timeframes and bookings.
Please read the documentation How to migrate from version 0.9.x to 2.x.x before you start migration." msgstr "Migriere Daten aus CommonsBooking Version 0.X.
Die Migration umfasst: Standorte, Artikel, Zeitrahmen und Buchungen.
Wenn du bereits zuvor \"Migrieren\" geklickt hast, startet die Migration erneut und wird alle Änderungen an Standorten, Artikeln, Zeitrahmen oder Buchungen, die du in der Zwischenzeit gemacht hast, überschreiben.
Bitte lies die Dokumentation auf Migration von Version 0.9.x auf 2.x.x., bevor Du mit der Migration beginnst." -#: includes/OptionsArray.php:1090 -#: src/View/Migration.php:73 +#: includes/OptionsArray.php:1220 +#: src/View/Migration.php:77 msgid "Start Migration" msgstr "Migration starten" -#: includes/OptionsArray.php:1101 +#: includes/OptionsArray.php:1231 msgid "CommonsBooking Version 0.X profile fields" msgstr "CommonsBooking Version 0.X Nutzerprofil-Felder" -#: includes/OptionsArray.php:1103 +#: includes/OptionsArray.php:1233 msgid "Enable the following legacy CommonsBooking Version 0.X user profile fields:" msgstr "Aktiviere die folgenden veralteten Nutzer-Profilfelder aus Commons Booking Version 0.X:" -#: includes/OptionsArray.php:1106 +#: includes/OptionsArray.php:1236 msgid "Enable" msgstr "Aktivieren" -#: includes/OptionsArray.php:1111 +#: includes/OptionsArray.php:1241 msgid "Terms & Services Url" msgstr "Nutzungsbedingungen & Services URL" -#: includes/OptionsArray.php:1120 +#: includes/OptionsArray.php:1250 msgid "Migrate bookings to new version" msgstr "Buchungen auf neue Version migrieren" -#: includes/OptionsArray.php:1122 +#: includes/OptionsArray.php:1252 msgid "Migrate bookings to new format so that they are listed at bookings menu item.
This function is only for special cases during migration. Please use it only in case of problems with migration." msgstr "Migriere Buchungen in ein neues Format, sodass diese unter dem Menüpunkt Buchungen aufgelistet werden.
Diese Funktion gilt nur für Sonderfälle während der Migration. Bitte nur bei Problemen währen der Migration verwenden. " -#: includes/OptionsArray.php:1125 +#: includes/OptionsArray.php:1255 #: src/View/MassOperations.php:109 -#: src/View/Migration.php:107 +#: src/View/Migration.php:112 msgid "Migrate bookings" msgstr "Buchungen migrieren" -#: includes/OptionsArray.php:1138 -#: includes/OptionsArray.php:1192 +#: includes/OptionsArray.php:1268 +#: includes/OptionsArray.php:1326 msgid "Export" msgstr "Export" -#: includes/OptionsArray.php:1142 +#: includes/OptionsArray.php:1272 msgid "Download timeframes export" msgstr "Zeitrahmen-Export herunterladen" -#: includes/OptionsArray.php:1146 -#: src/Wordpress/CustomPostType/Map.php:559 +#: includes/OptionsArray.php:1276 +#: src/Wordpress/CustomPostType/Map.php:557 #: src/Wordpress/CustomPostType/Restriction.php:53 -#: src/Wordpress/CustomPostType/Restriction.php:417 -#: src/Wordpress/CustomPostType/Timeframe.php:100 -#: src/Wordpress/CustomPostType/Timeframe.php:486 +#: src/Wordpress/CustomPostType/Restriction.php:421 +#: src/Wordpress/CustomPostType/Timeframe.php:104 +#: src/Wordpress/CustomPostType/Timeframe.php:495 msgid "Type" msgstr "Typ" -#: includes/OptionsArray.php:1147 +#: includes/OptionsArray.php:1277 msgid "Select Type of this timeframe (e.g. bookable, repair, holidays, booking). See Documentation for detailed information." msgstr "Wähle den Typ dieses Zeitrahmens (z.B. buchbar, Reparatur, Urlaub, Buchung). Ausführliche Informationen findest Du in der Dokumentation." -#: includes/OptionsArray.php:1153 +#: includes/OptionsArray.php:1283 msgid "Location-Fields" msgstr "Standort-Felder" -#: includes/OptionsArray.php:1154 -#: includes/OptionsArray.php:1161 +#: includes/OptionsArray.php:1285 +#: includes/OptionsArray.php:1294 msgid "Just add field names, no matter if its a post- or a meta-field. Comma separated list. Beside the standard post fields and standard postmeta-fields, the following custom meta fields are available. Copy only the values in [] in the field without the brackets. %s" msgstr "Fügen weitere Feldnamen hinzu, egal ob es sich um ein Post- oder ein Metafelder handelt. Kommagetrennte Liste. Neben den Standard-Postfeldern und Standard-Postmeta-Feldern stehen die folgenden benutzerdefinierten Metafelder zur Verfügung. Kopieren nur die Werte in [] in das Feld ohne die Klammern. %s" -#: includes/OptionsArray.php:1160 +#: includes/OptionsArray.php:1292 msgid "Item-Fields" msgstr "Artikel-Felder" -#: includes/OptionsArray.php:1167 +#: includes/OptionsArray.php:1301 msgid "User-Fields" msgstr "User-Felder" -#: includes/OptionsArray.php:1168 +#: includes/OptionsArray.php:1302 msgid "Just add field names, no matter if its a userfield or a meta-field. Comma separated list." msgstr "Fügen Sie einfach Feldnamen hinzu, egal ob es sich um ein Benutzerfeld oder ein Metafeld handelt. Kommagetrennte Liste." -#: includes/OptionsArray.php:1173 +#: includes/OptionsArray.php:1307 msgid "Export start date" msgstr "Export Startdatum" -#: includes/OptionsArray.php:1183 +#: includes/OptionsArray.php:1317 msgid "Export end date" msgstr "Export-Enddatum" -#: includes/OptionsArray.php:1200 +#: includes/OptionsArray.php:1334 msgid "Cron settings for timeframes export" msgstr "Cron-Einstellungen für den Zeitrahmenexport" -#: includes/OptionsArray.php:1204 +#: includes/OptionsArray.php:1338 msgid "Run as cronjob" msgstr "Als Cronjob anlegen" -#: includes/OptionsArray.php:1209 +#: includes/OptionsArray.php:1343 msgid "Export interval" msgstr "Exportintervall" -#: includes/OptionsArray.php:1213 -#: includes/OptionsArray.php:1214 +#: includes/OptionsArray.php:1347 +#: includes/OptionsArray.php:1348 msgid "minutes" msgstr "Minuten" -#: includes/OptionsArray.php:1215 +#: includes/OptionsArray.php:1349 msgid "daily" msgstr "täglich" -#: includes/OptionsArray.php:1219 +#: includes/OptionsArray.php:1353 msgid "Export timerange" msgstr "Export-Zeitbereich" -#: includes/OptionsArray.php:1220 +#: includes/OptionsArray.php:1354 msgid "Export timerange in days." msgstr "Exportiere diesen Zeitraum (in Tagen)" -#: includes/OptionsArray.php:1229 +#: includes/OptionsArray.php:1363 msgid "Filepath" msgstr "Dateipfad" -#: includes/OptionsArray.php:1230 +#: includes/OptionsArray.php:1364 msgid "Absolute path on your webserver (including trailing slash) where export file will be saved to." msgstr "Absoluter Pfad auf deinem Webserver (einschließlich abschließender Schrägstrich), in dem die Exportdatei gespeichert wird." -#: includes/OptionsArray.php:1242 -#: includes/OptionsArray.php:1270 +#: includes/OptionsArray.php:1376 +#: includes/OptionsArray.php:1404 msgid "API" msgstr "Schnittstelle" -#: includes/OptionsArray.php:1246 +#: includes/OptionsArray.php:1380 msgid "Configure API Access" msgstr "Konfigurieren des API-Zugriffs" -#: includes/OptionsArray.php:1250 +#: includes/OptionsArray.php:1384 msgid "Activate API" msgstr "API aktivieren" -#: includes/OptionsArray.php:1251 +#: includes/OptionsArray.php:1385 msgid "If selected, the API is enabled. See more information in the documentation: API documentation" msgstr "Wenn diese Option ausgewählt ist, ist die API aktiviert. Weitere Informationen in der Dokumentation: API-Dokumentation" -#: includes/OptionsArray.php:1256 +#: includes/OptionsArray.php:1390 msgid "Enable API Access without API-Key" msgstr "Aktiviert den API-Zugang ohne API-Schlüssel" -#: includes/OptionsArray.php:1257 +#: includes/OptionsArray.php:1391 msgid "If selected, the API is accessible without an API-Key. For details see: API documentation" msgstr "Wenn diese Option ausgewählt ist, ist die API ohne API-Schlüssel zugänglich. Weitere Informationen findest du unter: API-Dokumentation" -#: includes/OptionsArray.php:1264 +#: includes/OptionsArray.php:1398 msgid "API shares" msgstr "API Freigaben" -#: includes/OptionsArray.php:1265 +#: includes/OptionsArray.php:1399 msgid "You can define on or more API shares. Read the documentation for more information about API shares and configuration API documentation" msgstr "Du kannst ein oder mehrere API-Freigaben definieren. Weitere Informationen zu API-Freigaben und zur Konfiguration findest du in der API-Dokumentation" -#: includes/OptionsArray.php:1271 +#: includes/OptionsArray.php:1405 msgid "Add Another API" msgstr "Weitere API hinzufügen" -#: includes/OptionsArray.php:1272 +#: includes/OptionsArray.php:1406 msgid "Remove API" msgstr "API entfernen" -#: includes/OptionsArray.php:1279 +#: includes/OptionsArray.php:1413 msgid "API name" msgstr "Schnittstellen Name" -#: includes/OptionsArray.php:1280 +#: includes/OptionsArray.php:1414 msgid "Internal name for this API share" msgstr "Interner Name für diese API-Freigabe" -#: includes/OptionsArray.php:1285 +#: includes/OptionsArray.php:1419 msgid "API enabled" msgstr "Schnittelle aktiviert" -#: includes/OptionsArray.php:1286 +#: includes/OptionsArray.php:1420 msgid "If checked this API share is enabled" msgstr "Wenn ausgewählt, ist diese API-Freigabe aktiviert" -#: includes/OptionsArray.php:1291 +#: includes/OptionsArray.php:1425 msgid "Push URL" msgstr "Push URL" -#: includes/OptionsArray.php:1292 +#: includes/OptionsArray.php:1426 msgid "URL that gets push information everytime there was a change on CommonsBooking data" msgstr "URL, welche eine Push-Information bekommt, sobald es Änderungen den CommonsBooking Daten gibt" -#: includes/OptionsArray.php:1297 +#: includes/OptionsArray.php:1431 msgid "API Key" msgstr "API Schlüssel" -#: includes/OptionsArray.php:1300 +#: includes/OptionsArray.php:1434 msgid " You must set an API-Key. The API key should consist of alphanumeric characters and be at least 24 characters long." msgstr " Du musst einen API-Key setzen. Der API-Schlüssel sollte aus alphanumerischen Zeichen bestehen und mindestens 24 Zeichen lang sein." -#: includes/OptionsArray.php:1303 +#: includes/OptionsArray.php:1437 msgid "API Owner" msgstr "API-Besitzer" -#: includes/OptionsArray.php:1304 +#: includes/OptionsArray.php:1438 msgid "The owner value is provided by the API. It is set to the blog name by default in this version. In future versions you may be able to change this information" msgstr "Der API-Besitzer wird von der API bereitgestellt. In dieser Version ist standardmäßig der Blogname festgelegt. In zukünftigen Versionen können diese Informationen möglicherweise selbst geändert werden" -#: includes/OptionsArray.php:1324 +#: includes/OptionsArray.php:1458 msgid "Advanced Options" msgstr "Erweiterte Optionen" -#: includes/OptionsArray.php:1328 +#: includes/OptionsArray.php:1462 msgid "Set Custom metadata to locations and items" msgstr "Festlegen von benutzerdefinierten Metadaten für Standorte und Artikel" -#: includes/OptionsArray.php:1329 +#: includes/OptionsArray.php:1464 msgid "This is an advanced feature and should only be used if you are experienced or instructed how to set it up properly. In future versions we will add more detailed information and documentation." msgstr "Dies ist eine erweiterte Funktion und sollte nur verwendet werden, wenn du erfahren oder in der Konfiguration unterwiesen wurdest . In zukünftigen Versionen werden wir detailliertere Informationen und Dokumentationen hinzufügen." -#: includes/OptionsArray.php:1335 +#: includes/OptionsArray.php:1472 msgid "Meta Data" msgstr "Metadaten" -#: includes/OptionsArray.php:1336 +#: includes/OptionsArray.php:1474 msgid "" "Use only this format, separated by semicolon and each entry in a new line:
post_type(item/location);field-name;label(english),type(checkbox,number,text),description(in english)
\n" " Example: item;waterproof;Waterproof material;checkbox;\"This item is waterproof and can be used in heavy rain\" " msgstr "Verwende nur dieses Format, getrennt durch Semikolon und jeden Eintrag in einer neuen Zeile:
post_type(item/location);field-name;label(english),type(checkbox,number,text),description(in english)
Beispiel: item;wasserdicht; Wasserdichtes Material;Checkbox;\" Dieser Artikel ist wasserdicht und kann bei starkem Regen verwendet werden\" " -#: includes/OptionsArray.php:1344 +#: includes/OptionsArray.php:1486 msgid "iCalendar Feed" msgstr "iCalendar Feed" -#: includes/OptionsArray.php:1345 +#: includes/OptionsArray.php:1488 msgid "Enables users to copy a url for a dynamic iCalendar feed into their own digital calendars. This feature is experimental." msgstr "Erlaubt Nutzenden eine URL für einen dynamischen iCalendar in ihre eigenen digitalen Kalender zu kopieren. Dieses Feature ist experimentell." -#: includes/OptionsArray.php:1350 +#: includes/OptionsArray.php:1496 msgid "Enable iCalendar feed" msgstr "iCalendar Feed aktivieren" -#: includes/OptionsArray.php:1355 +#: includes/OptionsArray.php:1501 msgid "Event title" msgstr "Termin Titel" -#: includes/OptionsArray.php:1356 -#: includes/OptionsArray.php:1364 +#: includes/OptionsArray.php:1502 +#: includes/OptionsArray.php:1514 msgid "You can use template tags here as well" msgstr "Hier können auch Template Tags verwendet werden" -#: includes/OptionsArray.php:1363 +#: includes/OptionsArray.php:1513 msgid "Event description" msgstr "Terminbeschreibung" -#: includes/OptionsArray.php:1365 +#: includes/OptionsArray.php:1516 msgid "" "\n" "Pick up: {{booking:pickupDatetime}}\n" @@ -1102,32 +1098,32 @@ msgstr "" "{{location:formattedPickupInstructions}}\n" "{{booking:formattedBookingCode}} " -#: includes/OptionsArray.php:1377 +#: includes/OptionsArray.php:1531 msgid "Advanced caching settings" msgstr "Erweiterte Cachingoptionen" -#: includes/OptionsArray.php:1380 +#: includes/OptionsArray.php:1534 msgid "Allows you to change options regarding the caching system" msgstr "Erlaubt die Anpassung der Optionen für das Caching-System" -#: includes/OptionsArray.php:1389 +#: includes/OptionsArray.php:1543 msgid "Filesystem cache path" msgstr "Dateisystem-Cache Pfad" -#: includes/OptionsArray.php:1390 +#: includes/OptionsArray.php:1544 msgid "Where the filesystem cache should be created. Only change when filesystem caching is not working." msgstr "Wo der Dateisystem-Cache angelegt werden soll. Nur ändern, wenn das Dateisystem-Caching nicht funktioniert." -#: includes/OptionsArray.php:1396 -#: includes/OptionsArray.php:1413 +#: includes/OptionsArray.php:1550 +#: includes/OptionsArray.php:1567 msgid "Current connection status" msgstr "Aktueller Verbindungsstatus" -#: includes/OptionsArray.php:1402 +#: includes/OptionsArray.php:1556 msgid "Enable REDIS Caching (experimental)" msgstr "REDIS-Caching aktivieren (experimentell)" -#: includes/OptionsArray.php:1407 +#: includes/OptionsArray.php:1561 msgid "REDIS DSN (REDIS Server URL)" msgstr "REDIS DSN (REDIS-Server-URL)" @@ -1156,8 +1152,8 @@ msgid "Please enter your phone number" msgstr "Bitte gib Deine Telefonnummer ein" #: src/CB/CB1UserFields.php:90 -#: src/CB/CB1UserFields.php:281 -#: src/Wordpress/CustomPostType/Location.php:219 +#: src/CB/CB1UserFields.php:280 +#: src/Wordpress/CustomPostType/Location.php:221 #: templates/booking-single.php:77 msgid "Address" msgstr "Adresse" @@ -1179,23 +1175,23 @@ msgid "Please accept the terms & conditions" msgstr "Bitte akzeptiere die Nutzungsbedingungen" #. translators: %s = terms and service url -#: src/CB/CB1UserFields.php:185 +#: src/CB/CB1UserFields.php:188 msgid "Read the terms and services" msgstr "Lies die Nutzungsbedingungen" -#: src/CB/CB1UserFields.php:269 +#: src/CB/CB1UserFields.php:268 msgid "Extra Fields" msgstr "Zusatzfelder" -#: src/CB/CB1UserFields.php:273 +#: src/CB/CB1UserFields.php:272 msgid "Phone number" msgstr "Telefonnummer" -#: src/CB/CB1UserFields.php:289 +#: src/CB/CB1UserFields.php:288 msgid "Terms and conditions" msgstr "Nutzungsbedingungen" -#: src/CB/CB1UserFields.php:295 +#: src/CB/CB1UserFields.php:298 msgid "Accepted Terms & Conditions" msgstr "Nutzungsbedingungen akzeptiert" @@ -1208,190 +1204,190 @@ msgstr "Karte ist nicht veröffentlicht" msgid "no valid map id provided" msgstr "keine gültige Karten-ID angegeben" -#: src/Map/MapShortcode.php:49 +#: src/Map/MapShortcode.php:51 msgid "opening hours" msgstr "Öffnungszeiten" -#: src/Map/MapShortcode.php:50 +#: src/Map/MapShortcode.php:52 msgid "contact" msgstr "Kontakt" -#: src/Map/MapShortcode.php:51 +#: src/Map/MapShortcode.php:53 msgid "from" msgstr "von" -#: src/Map/MapShortcode.php:52 +#: src/Map/MapShortcode.php:54 msgid "until" msgstr "bis %s" -#: src/Map/MapShortcode.php:53 +#: src/Map/MapShortcode.php:55 msgid "for at least" msgstr "mindestens" -#: src/Map/MapShortcode.php:54 +#: src/Map/MapShortcode.php:56 msgid "day(s)" msgstr "Tag(e)" -#: src/Map/MapShortcode.php:55 +#: src/Map/MapShortcode.php:57 msgid "Sorry, no locations found." msgstr "Leider wurden keine Standorte gefunden." -#: src/Map/MapShortcode.php:56 -#: src/Wordpress/CustomPostType/Map.php:535 +#: src/Map/MapShortcode.php:58 +#: src/Wordpress/CustomPostType/Map.php:533 msgid "filter" msgstr "Filter" -#: src/Map/MapShortcode.php:57 -#: src/Wordpress/CustomPostType/Map.php:517 +#: src/Map/MapShortcode.php:59 +#: src/Wordpress/CustomPostType/Map.php:515 msgid "availability" msgstr "Verfügbarkeit" -#: src/Map/MapShortcode.php:58 -#: src/Wordpress/CustomPostType/Map.php:526 +#: src/Map/MapShortcode.php:60 +#: src/Wordpress/CustomPostType/Map.php:524 msgid "categories" msgstr "Kategorien" -#: src/Map/MapShortcode.php:59 -#: src/Wordpress/CustomPostType/Map.php:478 +#: src/Map/MapShortcode.php:61 +#: src/Wordpress/CustomPostType/Map.php:476 msgid "distance" msgstr "Entfernung" -#: src/Map/MapShortcode.php:60 +#: src/Map/MapShortcode.php:62 msgid "address" msgstr "Adresse" -#: src/Map/MapShortcode.php:61 +#: src/Map/MapShortcode.php:63 msgid "Sorry, an error occured during your request. Please try again later." msgstr "Es ist leider ein Fehler während der Anfrage aufgetreten. Versuche es später erneut." -#: src/Map/MapShortcode.php:62 +#: src/Map/MapShortcode.php:64 msgid "The service is currently not available. Please try again later." msgstr "Der Dienst ist derzeit nicht verfügbar. Versuche später erneut." -#: src/Map/MapShortcode.php:63 +#: src/Map/MapShortcode.php:65 msgid "comming soon" msgstr "Bald verfügbar" -#: src/Messages/Message.php:133 +#: src/Messages/Message.php:141 msgid "Could not send email because mail-template was not available. Check options -> templates" msgstr "E-Mail konnte nicht gesendet werden, da keine E-Mail-Vorlage verfügbar war. Optionen überprüfen -> Vorlagen" #. translators: %s = Booking code -#: src/Model/Booking.php:145 +#: src/Model/Booking.php:142 msgid "Your booking code is: %s" msgstr "Dein Buchungscode lautet: %s" #. translators: %s = date in WordPress defined format -#: src/Model/Booking.php:441 +#: src/Model/Booking.php:436 msgid " on %s " msgstr " am %s " #. translators: %1 = startdate, %2 = enddate in WordPress defined format -#: src/Model/Booking.php:444 +#: src/Model/Booking.php:439 msgid " from %1$s until %2$s " msgstr " von %1$s bis %2$s " -#: src/Model/Booking.php:576 +#: src/Model/Booking.php:570 msgid "Please check your booking and click confirm booking" msgstr "Bitte überprüfe die Buchung und klicke auf „Buchung bestätigen“" -#: src/Model/Booking.php:582 +#: src/Model/Booking.php:576 msgid "Your booking has been canceled at %s." msgstr "Die Buchung wurde storniert am %s." -#: src/Model/Booking.php:584 +#: src/Model/Booking.php:578 msgid "Your booking has been canceled" msgstr "Die Buchung wurde storniert" -#: src/Model/Booking.php:671 +#: src/Model/Booking.php:664 msgid "Link to your booking" msgstr "Link zu deiner Buchung" -#: src/Model/Location.php:124 +#: src/Model/Location.php:130 msgid "Please contact the contact persons at the location directly if you have any questions regarding collection or return:" msgstr "Bitte kontaktiere die Kontaktpersonen vor Ort direkt, wenn du Fragen zur Abholung oder Rückgabe hast:" -#: src/Model/Restriction.php:242 -#: src/Model/Restriction.php:266 +#: src/Model/Restriction.php:241 +#: src/Model/Restriction.php:265 msgid "Not set" msgstr "Nicht gesetzt" -#: src/Model/Timeframe.php:253 +#: src/Model/Timeframe.php:252 msgid "Available here" msgstr "Hier verfügbar" #. translators: %s = date in WordPress defined format -#: src/Model/Timeframe.php:258 +#: src/Model/Timeframe.php:257 msgid "on %s" msgstr "am %s" #. translators: %s = date in WordPress defined format -#: src/Model/Timeframe.php:263 +#: src/Model/Timeframe.php:262 msgid "from %s" msgstr "von %s" -#: src/Model/Timeframe.php:267 +#: src/Model/Timeframe.php:266 msgid "permanently" msgstr "dauerhaft" #. translators: %1$s = startdate, second %2$s = enddate in WordPress defined format -#: src/Model/Timeframe.php:273 +#: src/Model/Timeframe.php:272 msgid "from %1$s until %2$s" msgstr "von %1$s bis %2$s" #. translators: %s = enddate in WordPress defined format -#: src/Model/Timeframe.php:280 +#: src/Model/Timeframe.php:279 msgid "until %s" msgstr "bis %s" -#: src/Model/Timeframe.php:604 +#: src/Model/Timeframe.php:607 msgid "A pickup time but no return time has been set. Please set the return time." msgstr "Eine Abholzeit, aber keine Rückgabezeit wurde festgelegt. Lege bitte eine Rückgabezeit fest." -#: src/Model/Timeframe.php:612 +#: src/Model/Timeframe.php:617 msgid "End date is before start date. Please set a valid end date." msgstr "Enddatum liegt vor dem Startdatum. Bitte setze ein gültiges Enddatum." -#: src/Model/Timeframe.php:645 +#: src/Model/Timeframe.php:652 msgid "Item is already bookable at another location within the same date range. See other timeframe ID: %1$s: %2$s" msgstr "Artikel ist bereits an einem anderen Ort innerhalb desselben Datumsbereichs buchbar. Siehe andere Zeitrahmen ID: %1$s: %2$s" -#: src/Plugin.php:309 -#: src/Plugin.php:310 +#: src/Plugin.php:311 +#: src/Plugin.php:312 msgid "Item Categories" msgstr "Artikel-Kategorien" -#: src/Plugin.php:319 -#: src/Plugin.php:320 +#: src/Plugin.php:321 +#: src/Plugin.php:322 msgid "Location Categories" msgstr "Standort-Kategorien" -#: src/Plugin.php:435 -#: src/Plugin.php:467 +#: src/Plugin.php:437 +#: src/Plugin.php:470 msgid "Item Category" msgstr "Artikel-Kategorie" -#: src/Plugin.php:497 +#: src/Plugin.php:500 msgid "Location Category" msgstr "Standort-Kategorie" -#: src/Repository/BookingCodes.php:332 +#: src/Repository/BookingCodes.php:337 msgid "No booking codes could be created because there were no booking codes to choose from. Please set some booking codes in the CommonsBooking settings." msgstr "Es konnten keine Buchungscodes erstellt werden, da keine Buchungscodes zur Auswahl standen. Bitte lege einige Buchungscodes in den CommonsBooking-Einstellungen fest." -#: src/Repository/BookingCodes.php:339 +#: src/Repository/BookingCodes.php:344 msgid "No booking codes could be created because the location of the timeframe could not be found." msgstr "Es konnten keine Buchungscodes erstellt werden, da der Standort nicht gefunden wurde." -#: src/Repository/BookingCodes.php:345 +#: src/Repository/BookingCodes.php:350 msgid "No booking codes could be created because the item of the timeframe could not be found." msgstr "Es konnten keine Buchungscodes erstellt werden, da der Artikel nicht gefunden wurde." -#: src/Service/Cache.php:303 +#: src/Service/Cache.php:305 msgid "Connection status:" msgstr "Aktueller Verbindungsstatus:" -#: src/Service/Cache.php:310 +#: src/Service/Cache.php:312 msgid "Successfully connected to REDIS database!" msgstr "Erfolgreich mit REDIS-Datenbank verbunden!" @@ -1399,80 +1395,80 @@ msgstr "Erfolgreich mit REDIS-Datenbank verbunden!" msgid "REDIS database not enabled" msgstr "REDIS-Datenbank nicht aktiviert" -#: src/Service/Cache.php:347 +#: src/Service/Cache.php:346 msgid "Directory %s is writeable." msgstr "Der Ordner %s ist beschreibbar." -#: src/Service/Cache.php:352 +#: src/Service/Cache.php:350 msgid "Directory %s could not be written to." msgstr "Der Ordner %s ist nicht beschreibbar." #: src/View/Admin/Filter.php:58 -#: src/Wordpress/CustomPostType/Booking.php:769 -#: src/Wordpress/CustomPostType/Restriction.php:446 -#: src/Wordpress/CustomPostType/Timeframe.php:700 +#: src/Wordpress/CustomPostType/Booking.php:771 +#: src/Wordpress/CustomPostType/Restriction.php:455 +#: src/Wordpress/CustomPostType/Timeframe.php:712 msgid "Start date" msgstr "Startdatum" #: src/View/Admin/Filter.php:62 -#: src/Wordpress/CustomPostType/Booking.php:786 -#: src/Wordpress/CustomPostType/Restriction.php:456 -#: src/Wordpress/CustomPostType/Timeframe.php:724 +#: src/Wordpress/CustomPostType/Booking.php:788 +#: src/Wordpress/CustomPostType/Restriction.php:465 +#: src/Wordpress/CustomPostType/Timeframe.php:736 msgid "End date" msgstr "Enddatum" -#: src/View/Booking.php:156 +#: src/View/Booking.php:154 msgid "Details" msgstr "Details" -#: src/View/Booking.php:162 +#: src/View/Booking.php:160 msgid "Use this link to import the data into your own calendar. Usually you just need to provide the URL as an external source and the calendar will figure it out. Do not try to download this file." msgstr "Benutze diesen Link um die Buchungsdaten automatisch in deinem Kalender zu abonnieren. Bitte gib die URL in deinem Kalenderprogramm an und versuche nicht die Datei herunterzuladen." -#: src/View/Booking.php:163 +#: src/View/Booking.php:161 msgid "iCalendar Link:" msgstr "iCalendar Link:" -#: src/View/Booking.php:170 -#: src/View/Booking.php:172 +#: src/View/Booking.php:167 +#: src/View/Booking.php:169 msgid "Not available" msgstr "Nicht verfügbar" -#: src/View/Booking.php:193 +#: src/View/Booking.php:190 #: src/View/MassOperations.php:38 -#: src/Wordpress/CustomPostType/Booking.php:441 -#: src/Wordpress/CustomPostType/Timeframe.php:99 +#: src/Wordpress/CustomPostType/Booking.php:443 +#: src/Wordpress/CustomPostType/Timeframe.php:103 #: templates/shortcode-bookings.php:73 msgid "User" msgstr "Nutzende*r" -#: src/View/Booking.php:197 +#: src/View/Booking.php:194 #: src/View/MassOperations.php:42 -#: src/Wordpress/CustomPostType/Booking.php:959 -#: src/Wordpress/CustomPostType/Restriction.php:472 +#: src/Wordpress/CustomPostType/Booking.php:961 +#: src/Wordpress/CustomPostType/Restriction.php:481 msgid "Status" msgstr "Status" -#: src/View/Booking.php:206 +#: src/View/Booking.php:203 msgid "Code" msgstr "Code" -#: src/View/BookingCodes.php:360 +#: src/View/BookingCodes.php:393 msgid "The file will be exported as tab delimited .txt file so you can choose wether you want to print it, open it in a separate application (like Word, Excel etc.)" msgstr "Die Datei wird als .txt Datei durch Tabstopp getrennt exportiert, sodass Sie auswählen können, ob Sie sie drucken möchten, öffnen Sie sie in einer separaten Anwendung (wie Word, Excel usw.)." -#: src/View/BookingCodes.php:374 +#: src/View/BookingCodes.php:407 msgid "Booking codes list" msgstr "Liste der Buchungscodes" #: src/View/Calendar.php:225 -#: src/Wordpress/CustomPostType/Booking.php:442 -#: src/Wordpress/CustomPostType/Booking.php:751 -#: src/Wordpress/CustomPostType/Booking.php:975 -#: src/Wordpress/CustomPostType/Item.php:115 +#: src/Wordpress/CustomPostType/Booking.php:444 +#: src/Wordpress/CustomPostType/Booking.php:753 +#: src/Wordpress/CustomPostType/Booking.php:977 +#: src/Wordpress/CustomPostType/Item.php:117 #: src/Wordpress/CustomPostType/Restriction.php:54 -#: src/Wordpress/CustomPostType/Restriction.php:434 -#: src/Wordpress/CustomPostType/Timeframe.php:101 +#: src/Wordpress/CustomPostType/Restriction.php:443 +#: src/Wordpress/CustomPostType/Timeframe.php:105 #: templates/shortcode-bookings.php:72 msgid "Item" msgstr "Artikel" @@ -1482,28 +1478,28 @@ msgid "No items found." msgstr "Keine Artikel gefunden." #: src/View/Calendar.php:226 -#: src/Wordpress/CustomPostType/Booking.php:443 -#: src/Wordpress/CustomPostType/Booking.php:757 -#: src/Wordpress/CustomPostType/Booking.php:971 -#: src/Wordpress/CustomPostType/Location.php:122 +#: src/Wordpress/CustomPostType/Booking.php:445 +#: src/Wordpress/CustomPostType/Booking.php:759 +#: src/Wordpress/CustomPostType/Booking.php:973 +#: src/Wordpress/CustomPostType/Location.php:123 #: src/Wordpress/CustomPostType/Restriction.php:55 -#: src/Wordpress/CustomPostType/Restriction.php:428 -#: src/Wordpress/CustomPostType/Timeframe.php:102 -#: src/Wordpress/CustomPostType/Timeframe.php:494 +#: src/Wordpress/CustomPostType/Restriction.php:437 +#: src/Wordpress/CustomPostType/Timeframe.php:106 +#: src/Wordpress/CustomPostType/Timeframe.php:503 #: templates/shortcode-bookings.php:74 msgid "Location" msgstr "Standort" -#: src/View/Dashboard.php:41 -#: src/View/Dashboard.php:80 +#: src/View/Dashboard.php:48 +#: src/View/Dashboard.php:94 msgid "at" msgstr "bei" -#: src/View/Item.php:124 +#: src/View/Item.php:123 msgid "No bookable items found." msgstr "Keine Buchungen im Papierkorb gefunden." -#: src/View/Location.php:127 +#: src/View/Location.php:128 msgid "No locations found." msgstr "Leider wurden keine Standorte gefunden." @@ -1527,75 +1523,75 @@ msgstr "Für die eingegebene Adresse konnten keine GPS-Daten gefunden we msgid "We could not detect a version of an older CommonsBooking Installation (Version 0.X)." msgstr "Es konnte keine ältere Version von CommonsBooking (kleiner Version 1.0) gefunden werden." -#: src/View/Migration.php:31 +#: src/View/Migration.php:33 msgid "Found a version of an older CommonsBooking Installation (Version 0.X). You can migrate." msgstr "Es wurde eine Version einer älteren CommonsBooking Installation (Version 0.X) gefunden. Du kannst migrieren." -#: src/View/Migration.php:37 +#: src/View/Migration.php:41 msgid " Locations updated/saved" msgstr " Standorte aktualisiert / gespeichert" -#: src/View/Migration.php:38 +#: src/View/Migration.php:42 msgid " Items updated/saved" msgstr " Artikel aktualisiert / gespeichert" -#: src/View/Migration.php:39 +#: src/View/Migration.php:43 msgid " Timeframes updated/saved" msgstr " Zeitrahmen aktualisiert / gespeichert" -#: src/View/Migration.php:40 +#: src/View/Migration.php:44 msgid " Bookings updated/saved" msgstr " Buchungen aktualisiert / gespeichert" -#: src/View/Migration.php:41 +#: src/View/Migration.php:45 msgid " Booking Codes updated/saved" msgstr " Buchungscodes aktualisiert / gespeichert" -#: src/View/Migration.php:42 +#: src/View/Migration.php:46 msgid " Terms & Urls updated/saved" msgstr " Nutzungsbedingungen/URLs aktualisiert / gespeichert" -#: src/View/Migration.php:43 +#: src/View/Migration.php:47 msgid " Taxonomies updated/saved" msgstr " Kategorien aktualisiert / gespeichert" -#: src/View/Migration.php:44 +#: src/View/Migration.php:48 msgid " Options updated/saved" msgstr " Optionen aktualisiert / gespeichert" -#: src/View/Migration.php:48 +#: src/View/Migration.php:52 msgid "migration in process .. please wait ...
This could take several minutes. Do not close this browser tab" msgstr "Migration wird durchgeführt .. Bitte warten...
Dies kann einige Minuten dauern. Browserfenster bitte nicht schließen" #: src/View/MassOperations.php:99 -#: src/View/Migration.php:53 -#: src/View/Migration.php:98 +#: src/View/Migration.php:57 +#: src/View/Migration.php:103 msgid "Migration finished" msgstr "Migration beendet" -#: src/View/Migration.php:65 +#: src/View/Migration.php:69 msgid "Retrieve location geo coordinates." msgstr "Abrufen von Standort-Geokoordinaten." -#: src/View/Migration.php:67 +#: src/View/Migration.php:71 msgid "If this option is enabled, CommonsBooking will try to derive the matching geo-coordinates from the address data of the locations during import. We use an interface to a GeoCoder service (Nominatim) for this task. This service allows only one query per second, so the runtime of the migration is increased by 1 second per location. The geo-coordinates are needed to use the location map integrated in CommonsBooking." msgstr "Wenn diese Option aktiviert ist, versucht CommonsBooking beim Import die passenden Geo-Koordinaten aus den Adressdaten der Standorte abzuleiten. Für diese Aufgabe verwenden wir eine Schnittstelle zu einem GeoCoder-Dienst (Nominatim). Dieser Dienst erlaubt nur eine Abfrage pro Sekunde, so dass sich die Laufzeit der Migration um 1 Sekunde pro Standort erhöht. Die Geokoordinaten werden benötigt, um die in CommonsBooking integrierte Standortkarte zu nutzen." #: src/View/MassOperations.php:94 -#: src/View/Migration.php:93 +#: src/View/Migration.php:98 msgid "migration in process .. please wait ..." msgstr "Migration wird durchgeführt … bitte warten ..." #: src/View/MassOperations.php:104 -#: src/View/Migration.php:103 +#: src/View/Migration.php:108 msgid "Migration failed" msgstr "Migration fehlgeschlagen" -#: src/View/Restriction.php:35 +#: src/View/Restriction.php:34 msgid "Send" msgstr "Senden" -#: src/View/Restriction.php:43 +#: src/View/Restriction.php:42 msgid "Sent" msgstr "Gesendet" @@ -1607,223 +1603,223 @@ msgstr "CSV Herunterladen" msgid "Download Export" msgstr "Download Export" -#: src/Model/Booking.php:1028 -#: src/Service/TimeframeExport.php:523 +#: src/Model/Booking.php:1022 #: src/Service/TimeframeExport.php:533 -#: src/Service/TimeframeExport.php:539 +#: src/Service/TimeframeExport.php:543 #: src/Service/TimeframeExport.php:549 -#: src/Service/TimeframeExport.php:559 +#: src/Service/TimeframeExport.php:561 +#: src/Service/TimeframeExport.php:574 msgid "Unknown" msgstr "Unbekannt" -#: src/Wordpress/CustomPostType/Booking.php:107 +#: src/Wordpress/CustomPostType/Booking.php:106 msgid "Admin-Booking" msgstr "Admin-Buchung" #. translators: $s = id of the item -#: src/Wordpress/CustomPostType/Booking.php:256 +#: src/Wordpress/CustomPostType/Booking.php:258 msgid "Item does not exist. (%s)" msgstr "Artikel existiert nicht. (%s)" #. translators: $s = id of the location -#: src/Wordpress/CustomPostType/Booking.php:260 +#: src/Wordpress/CustomPostType/Booking.php:262 msgid "Location does not exist. (%s)" msgstr "Standort existiert nicht. (%s)" -#: src/Wordpress/CustomPostType/Booking.php:264 +#: src/Wordpress/CustomPostType/Booking.php:266 msgid "Start- and/or end-date is missing." msgstr "Das Start- und/oder Enddatum fehlt." -#: src/Wordpress/CustomPostType/Booking.php:295 +#: src/Wordpress/CustomPostType/Booking.php:297 msgid "Booking canceled." msgstr "Buchung storniert." -#: src/Wordpress/CustomPostType/Booking.php:311 +#: src/Wordpress/CustomPostType/Booking.php:313 msgid "There is already a booking in this time-range. This notice may also appear if there is an unconfirmed booking in the requested period. Unconfirmed bookings are deleted after about 10 minutes. Please try again in a few minutes." msgstr "Es gibt bereits eine Buchung in diesem Zeitraum. Dieser Hinweis kann auch erscheinen, wenn es eine unbestätigte Buchung in dem gewünschten Zeitraum gibt. Unbestätigte Buchungen werden nach etwa 10 Minuten gelöscht. Bitte versuche es in ein paar Minuten erneut." -#: src/Wordpress/CustomPostType/Booking.php:319 +#: src/Wordpress/CustomPostType/Booking.php:321 msgid "status changed by admin user via frontend. New status: " msgstr "Status wurde vom Administrierenden über das Frontend geändert. Neuer Status: " -#: src/Wordpress/CustomPostType/Booking.php:326 -#: src/Wordpress/CustomPostType/Booking.php:518 -#: src/Wordpress/CustomPostType/Booking.php:702 -#: src/Wordpress/CustomPostType/Timeframe.php:135 +#: src/Wordpress/CustomPostType/Booking.php:328 +#: src/Wordpress/CustomPostType/Booking.php:520 +#: src/Wordpress/CustomPostType/Booking.php:704 +#: src/Wordpress/CustomPostType/Timeframe.php:138 msgid "Booking" msgstr "Buchung" -#: src/Wordpress/CustomPostType/Booking.php:370 +#: src/Wordpress/CustomPostType/Booking.php:372 msgid "There was an error while saving the booking. Please try again. Thrown error:" msgstr "Es gab einen Fehler während der Buchung. Geworfener Fehler:" -#: src/Wordpress/CustomPostType/Booking.php:387 +#: src/Wordpress/CustomPostType/Booking.php:389 msgid "There was an error while saving the booking. Please try again. Resulting WP_ERROR: " msgstr "Es gab einen Fehler während der Buchung. WP_ERROR: " -#: src/Wordpress/CustomPostType/Booking.php:444 +#: src/Wordpress/CustomPostType/Booking.php:446 msgid "Bookingdate" msgstr "Buchungsdatum" -#: src/Wordpress/CustomPostType/Booking.php:445 +#: src/Wordpress/CustomPostType/Booking.php:447 #: src/Wordpress/CustomPostType/Restriction.php:56 -#: src/Wordpress/CustomPostType/Timeframe.php:103 -#: src/Wordpress/CustomPostType/Timeframe.php:766 +#: src/Wordpress/CustomPostType/Timeframe.php:107 +#: src/Wordpress/CustomPostType/Timeframe.php:788 msgid "Start Date" msgstr "Startdatum" -#: src/Wordpress/CustomPostType/Booking.php:446 +#: src/Wordpress/CustomPostType/Booking.php:448 #: src/Wordpress/CustomPostType/Restriction.php:57 -#: src/Wordpress/CustomPostType/Timeframe.php:104 +#: src/Wordpress/CustomPostType/Timeframe.php:108 msgid "End Date" msgstr "Enddatum" -#: src/Wordpress/CustomPostType/Booking.php:447 +#: src/Wordpress/CustomPostType/Booking.php:449 msgid "Booking Status" msgstr "Buchungsstatus" -#: src/Wordpress/CustomPostType/Booking.php:448 -#: src/Wordpress/CustomPostType/Booking.php:967 -#: src/Wordpress/CustomPostType/Timeframe.php:479 +#: src/Wordpress/CustomPostType/Booking.php:450 +#: src/Wordpress/CustomPostType/Booking.php:969 +#: src/Wordpress/CustomPostType/Timeframe.php:488 msgid "Comment" msgstr "Kommentar" -#: src/Wordpress/CustomPostType/Booking.php:517 +#: src/Wordpress/CustomPostType/Booking.php:519 #: templates/dashboard-index.php:45 msgid "Bookings" msgstr "Buchungen" -#: src/Wordpress/CustomPostType/Booking.php:519 -#: src/Wordpress/CustomPostType/Item.php:116 -#: src/Wordpress/CustomPostType/Location.php:123 -#: src/Wordpress/CustomPostType/Restriction.php:310 -#: src/Wordpress/CustomPostType/Timeframe.php:1146 +#: src/Wordpress/CustomPostType/Booking.php:521 +#: src/Wordpress/CustomPostType/Item.php:118 +#: src/Wordpress/CustomPostType/Location.php:124 +#: src/Wordpress/CustomPostType/Restriction.php:313 +#: src/Wordpress/CustomPostType/Timeframe.php:1180 msgid "Add new" msgstr "Neu hinzufügen" -#: src/Wordpress/CustomPostType/Booking.php:520 #: src/Wordpress/CustomPostType/Booking.php:522 +#: src/Wordpress/CustomPostType/Booking.php:524 msgid "Add new booking" msgstr "Neue Buchung hinzufügen" -#: src/Wordpress/CustomPostType/Booking.php:521 -#: src/Wordpress/CustomPostType/Booking.php:733 +#: src/Wordpress/CustomPostType/Booking.php:523 +#: src/Wordpress/CustomPostType/Booking.php:735 msgid "Edit booking" msgstr "Buchung bearbeiten" -#: src/Wordpress/CustomPostType/Booking.php:523 +#: src/Wordpress/CustomPostType/Booking.php:525 msgid "Show booking" msgstr "Buchung anzeigen" -#: src/Wordpress/CustomPostType/Booking.php:524 +#: src/Wordpress/CustomPostType/Booking.php:526 msgid "Show bookings" msgstr "Buchungen anzeigen" -#: src/Wordpress/CustomPostType/Booking.php:525 +#: src/Wordpress/CustomPostType/Booking.php:527 msgid "Search bookings" msgstr "Buchungen suchen" -#: src/Wordpress/CustomPostType/Timeframe.php:1153 +#: src/Wordpress/CustomPostType/Timeframe.php:1187 msgid "Timeframes not found" msgstr "Zeitrahmen wurden nicht gefunden" -#: src/Wordpress/CustomPostType/Booking.php:527 +#: src/Wordpress/CustomPostType/Booking.php:529 msgid "No bookings found in trash" msgstr "Keine Buchungen im Papierkorb gefunden" -#: src/Wordpress/CustomPostType/Booking.php:528 +#: src/Wordpress/CustomPostType/Booking.php:530 msgid "Parent bookings:" msgstr "Übergeordnete Buchungen:" -#: src/Wordpress/CustomPostType/Booking.php:529 +#: src/Wordpress/CustomPostType/Booking.php:531 msgid "All bookings" msgstr "Alle Buchungen" -#: src/Wordpress/CustomPostType/Booking.php:530 -#: src/Wordpress/CustomPostType/Timeframe.php:1157 +#: src/Wordpress/CustomPostType/Booking.php:532 +#: src/Wordpress/CustomPostType/Timeframe.php:1191 msgid "Timeframe archive" msgstr "Zeitrahmenarchiv" -#: src/Wordpress/CustomPostType/Booking.php:531 -#: src/Wordpress/CustomPostType/Timeframe.php:1158 +#: src/Wordpress/CustomPostType/Booking.php:533 +#: src/Wordpress/CustomPostType/Timeframe.php:1192 msgid "Timeframe attributes" msgstr "Zeitrahmenattribute" -#: src/Wordpress/CustomPostType/Booking.php:532 +#: src/Wordpress/CustomPostType/Booking.php:534 msgid "Add to booking" msgstr "Der Buchung hinzufügen" -#: src/Wordpress/CustomPostType/Booking.php:533 +#: src/Wordpress/CustomPostType/Booking.php:535 msgid "Added to booking" msgstr "Zur Buchung hinzugefügt" -#: src/Wordpress/CustomPostType/Booking.php:534 -#: src/Wordpress/CustomPostType/Timeframe.php:1161 +#: src/Wordpress/CustomPostType/Booking.php:536 +#: src/Wordpress/CustomPostType/Timeframe.php:1195 msgid "Timeframe image" msgstr "Zeitrahmenbild" -#: src/Wordpress/CustomPostType/Booking.php:535 +#: src/Wordpress/CustomPostType/Booking.php:537 msgid "set booking image" msgstr "Buchungsbild festlegen" -#: src/Wordpress/CustomPostType/Booking.php:536 +#: src/Wordpress/CustomPostType/Booking.php:538 msgid "remove booking image" msgstr "Buchungsbild entfernen" -#: src/Wordpress/CustomPostType/Booking.php:537 +#: src/Wordpress/CustomPostType/Booking.php:539 msgid "use as booking image" msgstr "als Buchungsbild verwenden" -#: src/Wordpress/CustomPostType/Booking.php:538 -#: src/Wordpress/CustomPostType/Timeframe.php:1144 -#: src/Wordpress/CustomPostType/Timeframe.php:1165 +#: src/Wordpress/CustomPostType/Booking.php:540 +#: src/Wordpress/CustomPostType/Timeframe.php:1178 +#: src/Wordpress/CustomPostType/Timeframe.php:1199 #: templates/dashboard-index.php:37 msgid "Timeframes" msgstr "Zeitrahmen" -#: src/Wordpress/CustomPostType/Booking.php:842 +#: src/Wordpress/CustomPostType/Booking.php:844 msgid "External comment" msgstr "Öffentlicher Kommentar" -#: src/Wordpress/CustomPostType/Booking.php:843 +#: src/Wordpress/CustomPostType/Booking.php:845 msgid "This comment can be seen by users in booking details. It can be set by users during the booking confirmation process if comments are enabled in settings." msgstr "Dieser Kommentar ist intern für Zeitrahmen wie buchbar, Reparatur, Urlaub. Wenn es sich um eine Buchung handelt, kann dieser Kommentar von den Benutzenden während des Buchungsbestätigungsprozesses eingegeben werden." -#: src/Wordpress/CustomPostType/Booking.php:848 -#: templates/booking-single.php:130 +#: src/Wordpress/CustomPostType/Booking.php:850 +#: templates/booking-single.php:131 msgid "Internal comment" msgstr "Interner Kommentar" -#: src/Wordpress/CustomPostType/Booking.php:849 +#: src/Wordpress/CustomPostType/Booking.php:851 msgid "This internal comment can only be seen in the backend by privileged users like admins or cb-managers" msgstr "Dieser interne Kommentar kann im Backend nur von autorisierten Nutzenden wie Admins oder CB-Managern gesehen werden" -#: src/Wordpress/CustomPostType/Booking.php:770 +#: src/Wordpress/CustomPostType/Booking.php:772 msgid "Set the start date. You must set the time to 00:00 if you want to book the full day " msgstr "Lege das Startdatum fest. Setze die Uhrzeit auf 00:00, wenn du den ganzen Tag buchen willst " -#: src/Wordpress/CustomPostType/Booking.php:787 +#: src/Wordpress/CustomPostType/Booking.php:789 msgid "Set the end date. You must set time to 23:59 if you want to book the full day" msgstr "Lege das Enddatum fest. Setze die Zeit auf 23:59 Uhr, wenn du den ganzen Tag buchen willst" -#: src/Wordpress/CustomPostType/Booking.php:803 +#: src/Wordpress/CustomPostType/Booking.php:805 #: templates/booking-single.php:59 msgid "Booking Code" msgstr "Buchungscode" -#: src/Wordpress/CustomPostType/Booking.php:809 +#: src/Wordpress/CustomPostType/Booking.php:811 msgid "Booking User" msgstr "Buchende Person" -#: src/Wordpress/CustomPostType/Booking.php:824 +#: src/Wordpress/CustomPostType/Booking.php:826 msgid "Admin Booking User" msgstr "Admin Booking Konto" -#: src/Wordpress/CustomPostType/Booking.php:835 +#: src/Wordpress/CustomPostType/Booking.php:837 msgid "This is the admin user who created or modified this booking." msgstr "Dies ist der/die Admin-Nutzende, der diese Buchung erstellt oder geändert hat." -#: src/Wordpress/CustomPostType/Booking.php:877 +#: src/Wordpress/CustomPostType/Booking.php:879 msgid "" "Bookings should be created via frontend booking calendar.
\n" "\t\tAs an admin you can create bookings via this admin interface. Please be aware that admin bookings are not validated\n" @@ -1836,329 +1832,329 @@ msgstr "" "\t\tund überprüft werden. Verwende diese Funktion mit Vorsicht.
Klicke auf Vorschau, um Buchungsdetails im Frontend anzuzeigen
Zur Suche und Filterung von Buchungen binde bitte die Frontend-Buchungsliste per Shortcode ein. \r\n" "\t\tMehr dazu: Buchungsliste anzeigen" -#: src/Wordpress/CustomPostType/CustomPostType.php:317 +#: src/Wordpress/CustomPostType/CustomPostType.php:331 msgid "Filter By Category " msgstr "Nach Kategorie filtern " -#: src/Wordpress/CustomPostType/Item.php:114 -#: src/Wordpress/CustomPostType/Item.php:135 +#: src/Wordpress/CustomPostType/Item.php:116 +#: src/Wordpress/CustomPostType/Item.php:137 #: templates/dashboard-index.php:33 msgid "Items" msgstr "Artikel" -#: src/Wordpress/CustomPostType/Item.php:117 #: src/Wordpress/CustomPostType/Item.php:119 +#: src/Wordpress/CustomPostType/Item.php:121 msgid "Add new item" msgstr "Neuen Artikel hinzufügen" -#: src/Wordpress/CustomPostType/Item.php:118 +#: src/Wordpress/CustomPostType/Item.php:120 msgid "Edit item" msgstr "Artikel bearbeiten" -#: src/Wordpress/CustomPostType/Item.php:120 +#: src/Wordpress/CustomPostType/Item.php:122 msgid "Show item" msgstr "Artikel anzeigen" -#: src/Wordpress/CustomPostType/Item.php:121 +#: src/Wordpress/CustomPostType/Item.php:123 msgid "Show items" msgstr "Artikel anzeigen" -#: src/Wordpress/CustomPostType/Item.php:122 +#: src/Wordpress/CustomPostType/Item.php:124 msgid "Search items" msgstr "Artikel suchen" -#: src/Wordpress/CustomPostType/Item.php:123 +#: src/Wordpress/CustomPostType/Item.php:125 msgid "items not found" msgstr "Artikel nicht gefunden" -#: src/Wordpress/CustomPostType/Item.php:124 +#: src/Wordpress/CustomPostType/Item.php:126 msgid "No items found in trash" msgstr "Keine Einträge im Papierkorb gefunden" -#: src/Wordpress/CustomPostType/Item.php:125 +#: src/Wordpress/CustomPostType/Item.php:127 msgid "Parent items:" msgstr "Übergeordnete Elemente:" -#: src/Wordpress/CustomPostType/Item.php:126 +#: src/Wordpress/CustomPostType/Item.php:128 msgid "All items" msgstr "Alle Artikel" -#: src/Wordpress/CustomPostType/Item.php:127 +#: src/Wordpress/CustomPostType/Item.php:129 msgid "Item archive" msgstr "Artikelarchiv" -#: src/Wordpress/CustomPostType/Item.php:128 +#: src/Wordpress/CustomPostType/Item.php:130 msgid "Item attributes" msgstr "Artikel Attribute" -#: src/Wordpress/CustomPostType/Item.php:129 +#: src/Wordpress/CustomPostType/Item.php:131 msgid "Add to item" msgstr "Zum Artikel hinzufügen" -#: src/Wordpress/CustomPostType/Item.php:130 +#: src/Wordpress/CustomPostType/Item.php:132 msgid "Added to item" msgstr "Zum Artikel hinzugefügt" -#: src/Wordpress/CustomPostType/Item.php:131 +#: src/Wordpress/CustomPostType/Item.php:133 msgid "Item image" msgstr "Artikelbild" -#: src/Wordpress/CustomPostType/Item.php:132 +#: src/Wordpress/CustomPostType/Item.php:134 msgid "set item image" msgstr "Festlegen des Artikelbildes" -#: src/Wordpress/CustomPostType/Item.php:133 +#: src/Wordpress/CustomPostType/Item.php:135 msgid "remove item image" msgstr "Artikelbild entfernen" -#: src/Wordpress/CustomPostType/Item.php:134 +#: src/Wordpress/CustomPostType/Item.php:136 msgid "use as item image" msgstr "Als Artikelbild verwenden" -#: src/Wordpress/CustomPostType/Item.php:231 +#: src/Wordpress/CustomPostType/Item.php:233 msgid "Item Info" msgstr "Artikel-Information" -#: src/Wordpress/CustomPostType/Item.php:249 +#: src/Wordpress/CustomPostType/Item.php:252 msgid "Item Admin(s)" msgstr "Artikel-Administrierende" -#: src/Wordpress/CustomPostType/Item.php:250 +#: src/Wordpress/CustomPostType/Item.php:253 msgid "choose one or more users to give them the permisssion to edit and manage this specific item. Only users with the role cb_manager can be selected here" msgstr "Wähle einen oder mehrere Benutzer aus, um ihnen die Möglichkeit zu geben, diesen bestimmten Artikel zu bearbeiten und zu verwalten. Hier können nur Benutzer mit der Rolle cb_manager ausgewählt werden" -#: src/Wordpress/CustomPostType/Item.php:255 +#: src/Wordpress/CustomPostType/Item.php:258 msgid "Select item admins." msgstr "Wähle Artikel-Administrierende aus." -#: src/Wordpress/CustomPostType/Item.php:261 +#: src/Wordpress/CustomPostType/Item.php:266 msgid "Item maintainer email" msgstr "E-Mail-Adresse des Artikelbetreuers" -#: src/Wordpress/CustomPostType/Item.php:262 +#: src/Wordpress/CustomPostType/Item.php:267 msgid "Email addresses to which notifications about a change of item status (restriction, breakdown) shall be sent. You can enter multiple addresses separated by commas." msgstr "E-Mail-Adressen die benachrichtigt werden soll, wenn eine Nutzungseinschränkung für den Artikel eingerichtet wurde (Hinweis oder Totalausfall). Es können mehrere Adressen durch Komma getrennt eingeben werden." -#: src/Wordpress/CustomPostType/Item.php:277 +#: src/Wordpress/CustomPostType/Item.php:286 msgid "Item Meta-Data" msgstr "Artikel Metadaten" -#: src/Wordpress/CustomPostType/Location.php:121 -#: src/Wordpress/CustomPostType/Location.php:142 +#: src/Wordpress/CustomPostType/Location.php:122 +#: src/Wordpress/CustomPostType/Location.php:143 #: templates/dashboard-index.php:35 msgid "Locations" msgstr "Standorte" -#: src/Wordpress/CustomPostType/Location.php:124 -#: src/Wordpress/CustomPostType/Location.php:126 +#: src/Wordpress/CustomPostType/Location.php:125 +#: src/Wordpress/CustomPostType/Location.php:127 msgid "Add new location" msgstr "Neuen Standort hinzufügen" -#: src/Wordpress/CustomPostType/Location.php:125 +#: src/Wordpress/CustomPostType/Location.php:126 msgid "Edit location" msgstr "Standort bearbeiten" -#: src/Wordpress/CustomPostType/Location.php:127 +#: src/Wordpress/CustomPostType/Location.php:128 msgid "Show location" msgstr "Standort anzeigen" -#: src/Wordpress/CustomPostType/Location.php:128 +#: src/Wordpress/CustomPostType/Location.php:129 msgid "Show locations" msgstr "Standorte anzeigen" -#: src/Wordpress/CustomPostType/Location.php:129 +#: src/Wordpress/CustomPostType/Location.php:130 msgid "Search locations" msgstr "Standorte suchen" -#: src/Wordpress/CustomPostType/Location.php:130 +#: src/Wordpress/CustomPostType/Location.php:131 msgid "location not found" msgstr "Standort nicht gefunden" -#: src/Wordpress/CustomPostType/Location.php:131 +#: src/Wordpress/CustomPostType/Location.php:132 msgid "No locations found in trash" msgstr "Keine Standorte im Papierkorb gefunden" -#: src/Wordpress/CustomPostType/Location.php:132 +#: src/Wordpress/CustomPostType/Location.php:133 msgid "Parent location:" msgstr "Übergeordneter Standort:" -#: src/Wordpress/CustomPostType/Location.php:133 +#: src/Wordpress/CustomPostType/Location.php:134 msgid "All locations" msgstr "Alle Standorte" -#: src/Wordpress/CustomPostType/Location.php:134 +#: src/Wordpress/CustomPostType/Location.php:135 msgid "Location archive" msgstr "Standortarchiv" -#: src/Wordpress/CustomPostType/Location.php:135 +#: src/Wordpress/CustomPostType/Location.php:136 msgid "Location attributes" msgstr "Standort-Attribute" -#: src/Wordpress/CustomPostType/Location.php:136 +#: src/Wordpress/CustomPostType/Location.php:137 msgid "Add to location" msgstr "Hinzufügen zum Standort" -#: src/Wordpress/CustomPostType/Location.php:137 +#: src/Wordpress/CustomPostType/Location.php:138 msgid "Added to location" msgstr "Zum Standort hinzugefügt" -#: src/Wordpress/CustomPostType/Location.php:138 +#: src/Wordpress/CustomPostType/Location.php:139 msgid "Location image" msgstr "Standort Bild" -#: src/Wordpress/CustomPostType/Location.php:139 +#: src/Wordpress/CustomPostType/Location.php:140 msgid "set location image" msgstr "Standortbild festlegen" -#: src/Wordpress/CustomPostType/Location.php:140 +#: src/Wordpress/CustomPostType/Location.php:141 msgid "remove location image" msgstr "Standortbild entfernen" -#: src/Wordpress/CustomPostType/Location.php:141 +#: src/Wordpress/CustomPostType/Location.php:142 msgid "use as location image" msgstr "Verwendung als Standortbild" -#: src/Wordpress/CustomPostType/Location.php:228 +#: src/Wordpress/CustomPostType/Location.php:232 msgid "Street / No." msgstr "Straße / Nr." -#: src/Wordpress/CustomPostType/Location.php:239 +#: src/Wordpress/CustomPostType/Location.php:245 msgid "Postcode" msgstr "Postleitzahl" -#: src/Wordpress/CustomPostType/Location.php:250 +#: src/Wordpress/CustomPostType/Location.php:258 msgid "City" msgstr "Stadt" -#: src/Wordpress/CustomPostType/Location.php:261 +#: src/Wordpress/CustomPostType/Location.php:271 msgid "Country" msgstr "Land" -#: src/Wordpress/CustomPostType/Location.php:270 +#: src/Wordpress/CustomPostType/Location.php:282 msgid "Set / Update GPS and map" msgstr "GPS und Karte einstellen / aktualisieren" -#: src/Wordpress/CustomPostType/Location.php:281 +#: src/Wordpress/CustomPostType/Location.php:294 msgid "Latitude" msgstr "Breitengrad" -#: src/Wordpress/CustomPostType/Location.php:282 +#: src/Wordpress/CustomPostType/Location.php:295 msgid "The latitude is calculated automatically when you click the \"set / update GPS\" button after entering the street, postal code and city." msgstr "Der Breitengrad wird automatisch berechnet, wenn du nach Eingabe von Straße, Postleitzahl und Ort auf GPS-Koordinaten abrufen / aktualisieren klickst." -#: src/Wordpress/CustomPostType/Location.php:290 +#: src/Wordpress/CustomPostType/Location.php:305 msgid "Longitude" msgstr "Längengrad" -#: src/Wordpress/CustomPostType/Location.php:291 +#: src/Wordpress/CustomPostType/Location.php:306 msgid "The longitude is calculated automatically when you click the \"set / update GPS\" button after entering the street, postal code and city." msgstr "Der Längengrad wird automatisch berechnet, wenn du nach Eingabe von Straße, Postleitzahl und Ort auf GPS-Koordinaten abrufen / aktualisieren klickst." -#: src/Wordpress/CustomPostType/Location.php:299 +#: src/Wordpress/CustomPostType/Location.php:316 msgid "Position" msgstr "Position" -#: src/Wordpress/CustomPostType/Location.php:308 +#: src/Wordpress/CustomPostType/Location.php:327 msgid "Show location map on item view" msgstr "Positionskarte in der Artikelansicht anzeigen" -#: src/Wordpress/CustomPostType/Location.php:309 +#: src/Wordpress/CustomPostType/Location.php:328 msgid "If enabled, a map showing the location will be displayed on the location details page." msgstr "Wenn diese Option aktiviert ist, wird auf der Seite mit den Standortdetails eine Karte mit dem Standort angezeigt." -#: src/Wordpress/CustomPostType/Location.php:318 +#: src/Wordpress/CustomPostType/Location.php:339 msgid "General Location information" msgstr "Allgemeine Standortinformationen" -#: src/Wordpress/CustomPostType/Location.php:327 +#: src/Wordpress/CustomPostType/Location.php:350 msgid "Location email" msgstr "Standort E-Mail" -#: src/Wordpress/CustomPostType/Location.php:350 +#: src/Wordpress/CustomPostType/Location.php:379 #: templates/booking-single.php:86 #: templates/location-single-meta.php:53 msgid "Pickup instructions" msgstr "Abhol-Hinweise" -#: src/Wordpress/CustomPostType/Location.php:351 +#: src/Wordpress/CustomPostType/Location.php:380 msgid "Type in information about the pickup process (e.g. detailed route description, opening hours, etc.). This will be shown to user in booking process and booking confirmation mail" msgstr "Gib hier Informationen über den Abholvorgang ein (z.B. detaillierte Routenbeschreibung, Öffnungszeiten usw.). Dies wird dem Benutzenden im Buchungsprozess und in der Buchungsbestätigungs-Email angezeigt" -#: src/Wordpress/CustomPostType/Location.php:361 +#: src/Wordpress/CustomPostType/Location.php:394 msgid "Location contact information" msgstr "Standortkontaktinformationen" -#: src/Wordpress/CustomPostType/Location.php:362 +#: src/Wordpress/CustomPostType/Location.php:395 msgid "information about how to contact the location (e.g. contact person, phone number, e-mail etc.). This will be shown to user in booking process and booking confirmation mail" msgstr "Informationen zur Kontaktaufnahme mit dem Standort (z. B. Ansprechpartner, Telefonnummer, E-Mail usw.). Dies wird dem Nutzenden im Buchungsprozess und bei der Buchungsbestätigungs-Email angezeigt" -#: src/Wordpress/CustomPostType/Location.php:378 +#: src/Wordpress/CustomPostType/Location.php:415 msgid "Location Admin(s)" msgstr "Standort-Administrator(en)" -#: src/Wordpress/CustomPostType/Location.php:379 +#: src/Wordpress/CustomPostType/Location.php:416 msgid "choose one or more users to give them the permisssion to edit and manage this specific location. Only users with the role CommonsBooking Manager can be selected here." msgstr "Wähle einen oder mehrere Benutzer aus, um ihnen die Möglichkeit zu geben, diesen bestimmten Standort zu bearbeiten und zu verwalten. Hier können nur Benutzer mit der Rolle CommonsBooking Manager ausgewählt werden." -#: src/Wordpress/CustomPostType/Location.php:385 +#: src/Wordpress/CustomPostType/Location.php:424 msgid "Select location admins." msgstr "Wähle Standort-Admins." -#: src/Wordpress/CustomPostType/Location.php:454 +#: src/Wordpress/CustomPostType/Location.php:501 msgid "Allow locked day overbooking" msgstr "Überbuchen von geblockten Tagen erlauben" -#: src/Wordpress/CustomPostType/Location.php:455 +#: src/Wordpress/CustomPostType/Location.php:502 msgid "If selected, all not selected days in any bookable timeframe that is connected to this location can be overbooked. Read the documentation Create Locations for more information." msgstr "Wenn ausgewählt, können nicht aktivierte Tagen bei der Buchung überbucht werden. Dies gilt für alle Zeitrahmen vom Typ „buchbar“, die mit diesem Standort verknüpft sind. Lies die Dokumentation unter Standorte anlegen für mehr Informationen." -#: src/Wordpress/CustomPostType/Location.php:423 +#: src/Wordpress/CustomPostType/Location.php:470 msgid "Location Meta-Data" msgstr "Standort-Metadaten" -#: src/Wordpress/CustomPostType/Map.php:618 +#: src/Wordpress/CustomPostType/Map.php:616 #: templates/dashboard-index.php:55 msgid "Maps" msgstr "Karten" -#: src/Wordpress/CustomPostType/Map.php:619 +#: src/Wordpress/CustomPostType/Map.php:617 msgid "Map" msgstr "Karte" -#: src/Wordpress/CustomPostType/Map.php:620 -#: src/Wordpress/CustomPostType/Map.php:623 +#: src/Wordpress/CustomPostType/Map.php:618 +#: src/Wordpress/CustomPostType/Map.php:621 msgid "create CB map" msgstr "CB-Karte erstellen" -#: src/Wordpress/CustomPostType/Map.php:621 +#: src/Wordpress/CustomPostType/Map.php:619 msgid "create Commons Booking map" msgstr "Commons Booking Karte erstellen" -#: src/Wordpress/CustomPostType/Map.php:622 +#: src/Wordpress/CustomPostType/Map.php:620 msgid "edit Commons Booking map" msgstr "CommonsBooking Karte bearbeiten" -#: src/Wordpress/CustomPostType/Map.php:624 +#: src/Wordpress/CustomPostType/Map.php:622 msgid "view CB map" msgstr "CB-Karte anzeigen" -#: src/Wordpress/CustomPostType/Map.php:625 +#: src/Wordpress/CustomPostType/Map.php:623 msgid "search CB maps" msgstr "CB-Karten suchen" -#: src/Wordpress/CustomPostType/Map.php:626 +#: src/Wordpress/CustomPostType/Map.php:624 msgid "no Commons Booking map found" msgstr "Keine Commons Booking Karte gefunden" -#: src/Wordpress/CustomPostType/Map.php:627 +#: src/Wordpress/CustomPostType/Map.php:625 msgid "no Commons Booking map found in the trash" msgstr "Keine Commons Booking Karte im Papierkorb gefunden" -#: src/Wordpress/CustomPostType/Map.php:628 +#: src/Wordpress/CustomPostType/Map.php:626 msgid "parent CB maps" msgstr "Übergeordnete CB-Karten" -#: src/Wordpress/CustomPostType/Map.php:657 +#: src/Wordpress/CustomPostType/Map.php:655 msgid "Maps to show Commons Booking Locations and their Items" msgstr "Karten, um CommonsBooking Standorte und deren Artikel anzuzeigen" @@ -2166,101 +2162,101 @@ msgstr "Karten, um CommonsBooking Standorte und deren Artikel anzuzeigen" msgid "Restriction Status" msgstr "Status der Einschränkung" -#: src/Wordpress/CustomPostType/Restriction.php:75 -#: src/Wordpress/CustomPostType/Timeframe.php:245 +#: src/Wordpress/CustomPostType/Restriction.php:73 +#: src/Wordpress/CustomPostType/Timeframe.php:249 msgid "Filter By Type " msgstr "Filtern nach Typ " -#: src/Wordpress/CustomPostType/Restriction.php:101 -#: src/Wordpress/CustomPostType/Timeframe.php:271 +#: src/Wordpress/CustomPostType/Restriction.php:99 +#: src/Wordpress/CustomPostType/Timeframe.php:275 msgid "Filter By Item " msgstr "Filtern nach Artikel " -#: src/Wordpress/CustomPostType/Restriction.php:128 -#: src/Wordpress/CustomPostType/Timeframe.php:298 +#: src/Wordpress/CustomPostType/Restriction.php:126 +#: src/Wordpress/CustomPostType/Timeframe.php:302 msgid "Filter By Location " msgstr "Filtern nach Standort " -#: src/Wordpress/CustomPostType/Restriction.php:141 -#: src/Wordpress/CustomPostType/Timeframe.php:316 +#: src/Wordpress/CustomPostType/Restriction.php:139 +#: src/Wordpress/CustomPostType/Timeframe.php:319 msgid "Filter By Status " msgstr "Filtern nach Status " -#: src/Wordpress/CustomPostType/Restriction.php:309 -#: src/Wordpress/CustomPostType/Restriction.php:390 +#: src/Wordpress/CustomPostType/Restriction.php:312 +#: src/Wordpress/CustomPostType/Restriction.php:393 msgid "Restriction" msgstr "Einschränkung" -#: src/Wordpress/CustomPostType/Restriction.php:311 -#: src/Wordpress/CustomPostType/Restriction.php:313 +#: src/Wordpress/CustomPostType/Restriction.php:314 +#: src/Wordpress/CustomPostType/Restriction.php:316 msgid "Add new Restriction" msgstr "Neue Einschränkung hinzufügen" -#: src/Wordpress/CustomPostType/Restriction.php:312 +#: src/Wordpress/CustomPostType/Restriction.php:315 msgid "Edit Restriction" msgstr "Einschränkung bearbeiten" -#: src/Wordpress/CustomPostType/Restriction.php:314 +#: src/Wordpress/CustomPostType/Restriction.php:317 msgid "Show Restriction" msgstr "Einschränkung anzeigen" -#: src/Wordpress/CustomPostType/Restriction.php:315 +#: src/Wordpress/CustomPostType/Restriction.php:318 msgid "Show Restrictions" msgstr "Einschränkungen anzeigen" -#: src/Wordpress/CustomPostType/Restriction.php:316 +#: src/Wordpress/CustomPostType/Restriction.php:319 msgid "Search Restrictions" msgstr "Einschränkungen suchen" -#: src/Wordpress/CustomPostType/Restriction.php:317 +#: src/Wordpress/CustomPostType/Restriction.php:320 msgid "Restrictions not found" msgstr "Einschränkungen nicht gefunden" -#: src/Wordpress/CustomPostType/Restriction.php:318 +#: src/Wordpress/CustomPostType/Restriction.php:321 msgid "No Restrictions found in trash" msgstr "Keine Einschränkungen im Papierkorb gefunden" -#: src/Wordpress/CustomPostType/Restriction.php:319 +#: src/Wordpress/CustomPostType/Restriction.php:322 msgid "Parent Restrictions:" msgstr "Übergeordnete Einschränkungen:" -#: src/Wordpress/CustomPostType/Restriction.php:320 +#: src/Wordpress/CustomPostType/Restriction.php:323 msgid "All Restrictions" msgstr "Alle Einschränkungen" -#: src/Wordpress/CustomPostType/Restriction.php:321 +#: src/Wordpress/CustomPostType/Restriction.php:324 msgid "Restriction archive" msgstr "Einschränkungsarchiv" -#: src/Wordpress/CustomPostType/Restriction.php:322 +#: src/Wordpress/CustomPostType/Restriction.php:325 msgid "Restriction attributes" msgstr "Einschränkungsattribute" -#: src/Wordpress/CustomPostType/Restriction.php:323 +#: src/Wordpress/CustomPostType/Restriction.php:326 msgid "Add to Restriction" msgstr "Zur Einschränkung hinzufügen" -#: src/Wordpress/CustomPostType/Restriction.php:324 +#: src/Wordpress/CustomPostType/Restriction.php:327 msgid "Added to Restriction" msgstr "Zur Einschränkung hinzugefügt" -#: src/Wordpress/CustomPostType/Restriction.php:325 +#: src/Wordpress/CustomPostType/Restriction.php:328 msgid "Restriction image" msgstr "Einschränkungs-Bild" -#: src/Wordpress/CustomPostType/Restriction.php:326 +#: src/Wordpress/CustomPostType/Restriction.php:329 msgid "set Restriction image" msgstr "Festlegen des Einschränkungsbilds" -#: src/Wordpress/CustomPostType/Restriction.php:327 +#: src/Wordpress/CustomPostType/Restriction.php:330 msgid "remove Restriction image" msgstr "Einschränkungsbild entfernen" -#: src/Wordpress/CustomPostType/Restriction.php:328 +#: src/Wordpress/CustomPostType/Restriction.php:331 msgid "use as Restriction image" msgstr "Verwendung als Einschränkungsbild" -#: src/Wordpress/CustomPostType/Restriction.php:418 +#: src/Wordpress/CustomPostType/Restriction.php:423 msgid "" "Select the type of restriction.
\n" "\t\t\t\tSelect Notice, the item can still be used and if e.g. only one part is missing or defective.
\n" @@ -2271,28 +2267,28 @@ msgstr "" "Wähle den Typ der Einschränkung aus.
Wähle Hinweis, wenn der Artikel weiterhin verwendet werden kann und wenn z.B. nur ein Teil fehlt oder defekt ist.
Wähle Totalausfall, wenn der Fehler bedeutet, dass der Artikel nicht mehr verwendet werden kann. Wenn du Totalausfall auswählst, \n" "\t\t\twerden alle betroffenen Buchungen nach Aktivierung dieser Einschränkung und nach Anklicken des Senden-Buttons der Informations-E-Mail automatisch storniert " -#: src/Wordpress/CustomPostType/Timeframe.php:822 +#: src/Wordpress/CustomPostType/Timeframe.php:845 #: templates/shortcode-bookings.php:54 msgid "All" msgstr "Alle" -#: src/Wordpress/CustomPostType/Restriction.php:440 +#: src/Wordpress/CustomPostType/Restriction.php:449 msgid "Hint" msgstr "Erläuterung" -#: src/Wordpress/CustomPostType/Restriction.php:442 +#: src/Wordpress/CustomPostType/Restriction.php:451 msgid "Please enter here a short information about the reason and possible effects of the usage restriction.
The explanation will be displayed on the article page and in the notification e-mail." msgstr "Bitte gib hier eine kurze Information über den Grund und mögliche Auswirkungen der Nutzungsbeschränkung ein.
Die Erklärung wird auf der Artikelseite und in der Benachrichtigungs-E-Mail angezeigt." -#: src/Wordpress/CustomPostType/Restriction.php:447 +#: src/Wordpress/CustomPostType/Restriction.php:456 msgid "Set the start date and time" msgstr "Startdatums und der Startzeit festlegen" -#: src/Wordpress/CustomPostType/Restriction.php:457 +#: src/Wordpress/CustomPostType/Restriction.php:466 msgid "Set the estimated end date and time" msgstr "Das geschätzte Enddatum und die geschätzten Endzeit festlegen" -#: src/Wordpress/CustomPostType/Restriction.php:474 +#: src/Wordpress/CustomPostType/Restriction.php:484 msgid "" "Choose status of this restriction.
\n" "\t\t\t\tSet to None if you want to deactivate the restriction.
\n" @@ -2304,195 +2300,195 @@ msgstr "" "Wähle den Status dieser Einschränkung aus.
Wähle Keine wenn du die Einschränkung deaktivieren möchtest.
Wähle Aktiv, wenn die Einschränkung aktiv ist.
Wähle Problem gelöst, wenn die Einschränkung nicht mehr besteht.
Je nach ausgewähltem Status erhalten betroffene Nutzende entsprechende Benachrichtigungs-E-Mails.\n" "Wähle den gewünschten Status aus und klicke dann auf die Schaltfläche \"Senden\", um die E-Mail zu senden. Commonsbooking -> Tab Restrictions" msgstr "Wichtig: Bitte speichere diese Einschränkung, bevor du auf den Senden-Button klickst. Abhängig vom Status der Einschränkung werden die entsprechenden Benachrichtigungen an alle betroffenen Nutzenden und Standortadministrierenden gesendet. Du kannst die E-Mail-Vorlagen über Optionen -> CommonsBooking -> Einschränkungen konfigurieren" -#: src/Wordpress/CustomPostType/Restriction.php:504 +#: src/Wordpress/CustomPostType/Restriction.php:518 msgid "Total breakdown" msgstr "Totalausfall" -#: src/Wordpress/CustomPostType/Restriction.php:505 +#: src/Wordpress/CustomPostType/Restriction.php:519 msgid "Notice" msgstr "Hinweis" -#: src/Wordpress/CustomPostType/Restriction.php:515 +#: src/Wordpress/CustomPostType/Restriction.php:529 msgid "Not active" msgstr "Nicht aktiv" -#: src/Wordpress/CustomPostType/Restriction.php:516 +#: src/Wordpress/CustomPostType/Restriction.php:530 msgid "Active" msgstr "Aktiv" -#: src/Wordpress/CustomPostType/Restriction.php:517 +#: src/Wordpress/CustomPostType/Restriction.php:531 msgid "Problem solved" msgstr "Problem gelöst" -#: src/Wordpress/CustomPostType/Timeframe.php:105 +#: src/Wordpress/CustomPostType/Timeframe.php:109 msgid "Max. Booking Duration" msgstr "Maximale Buchungsdauer" -#: src/Wordpress/CustomPostType/Timeframe.php:130 +#: src/Wordpress/CustomPostType/Timeframe.php:133 msgid "Bookable" msgstr "Buchbar" -#: src/Wordpress/CustomPostType/Timeframe.php:131 +#: src/Wordpress/CustomPostType/Timeframe.php:134 msgid "Holidays or location closed" msgstr "Feiertage oder Station geschlossen" -#: src/Wordpress/CustomPostType/Timeframe.php:134 +#: src/Wordpress/CustomPostType/Timeframe.php:137 msgid "Blocked (not overbookable)" msgstr "Geblockt (nicht überbuchbar)" -#: src/Wordpress/CustomPostType/Timeframe.php:451 -#: src/Wordpress/CustomPostType/Timeframe.php:1145 +#: src/Wordpress/CustomPostType/Timeframe.php:460 +#: src/Wordpress/CustomPostType/Timeframe.php:1179 msgid "Timeframe" msgstr "Zeitrahmen" -#: src/Wordpress/CustomPostType/Timeframe.php:480 +#: src/Wordpress/CustomPostType/Timeframe.php:489 msgid "This comment is internal for timeframes like bookable, repair, holiday. If timeframe is a booking this comment can be set by users during the booking confirmation process." msgstr "Dieser Kommentar ist intern für Zeitrahmen wie buchbar, Reparatur, Urlaub. Wenn es sich um eine Buchung handelt, kann dieser Kommentar von den Benutzenden während des Buchungsbestätigungsprozesses eingegeben werden." -#: src/Wordpress/CustomPostType/Timeframe.php:487 +#: src/Wordpress/CustomPostType/Timeframe.php:496 msgid "Select Type of this timeframe: Bookable or Location Closed. See Documentation for detailed information." msgstr "Wähle den Typ dieses Zeitrahmens: Buchbar oder Urlaub / Station geschlossen. Ausführliche Informationen findest Du in der Dokumentation." -#: src/Wordpress/CustomPostType/Timeframe.php:513 -#: src/Wordpress/CustomPostType/Timeframe.php:551 +#: src/Wordpress/CustomPostType/Timeframe.php:522 +#: src/Wordpress/CustomPostType/Timeframe.php:560 msgid "Please select" msgstr "— Bitte auswählen —" -#: src/Wordpress/CustomPostType/Timeframe.php:556 +#: src/Wordpress/CustomPostType/Timeframe.php:565 msgid "Configure bookings" msgstr "Buchungen konfigurieren" -#: src/Wordpress/CustomPostType/Timeframe.php:561 +#: src/Wordpress/CustomPostType/Timeframe.php:570 msgid "Maximum" msgstr "Maximal" -#: src/Wordpress/CustomPostType/Timeframe.php:562 +#: src/Wordpress/CustomPostType/Timeframe.php:571 msgid "days in a row" msgstr "Tage am Stück" -#: src/Wordpress/CustomPostType/Timeframe.php:574 +#: src/Wordpress/CustomPostType/Timeframe.php:583 msgid "Lead time:" msgstr "Vorlauf:" -#: src/Wordpress/CustomPostType/Timeframe.php:575 +#: src/Wordpress/CustomPostType/Timeframe.php:584 msgid "Enter the number of days that should be blocked for bookings as a booking lead time (calculated from the current day)." msgstr "Bitte gib die Anzahl der Tage ein, die zwischen Buchung und Abholung des Artikels liegen sollen. Die Rechnung geht vom heutigen Tag aus." -#: src/Wordpress/CustomPostType/Timeframe.php:587 +#: src/Wordpress/CustomPostType/Timeframe.php:596 msgid "Calendar shows as bookable" msgstr "Kalender zeigt als buchbar" -#: src/Wordpress/CustomPostType/Timeframe.php:588 +#: src/Wordpress/CustomPostType/Timeframe.php:597 msgid "Select for how many days in advance the calendar should display bookable days. Calculated from the current date." msgstr "Wähle aus, wie viele Tage im Voraus der Kalender als buchbare Tage anzeigen soll. Berechnet ab dem aktuellen Datum." -#: src/Wordpress/CustomPostType/Timeframe.php:600 +#: src/Wordpress/CustomPostType/Timeframe.php:609 msgid "Allowed for" msgstr "Erlaubt für" -#: src/Wordpress/CustomPostType/Timeframe.php:602 +#: src/Wordpress/CustomPostType/Timeframe.php:611 msgid "
Select one or more user roles that will be allowed to book the item exclusively.
Leave this blank to allow all users to book the item. " msgstr "
Wähle eine oder mehrere Benutzer:innen-Rollen aus, die den Artikel exklusiv buchen dürfen.
Leer lassen um das Buchen für alle zu erlauben. " -#: src/Wordpress/CustomPostType/Timeframe.php:606 +#: src/Wordpress/CustomPostType/Timeframe.php:615 msgid "User roles" msgstr "Benutzer:innen-Rollen" -#: src/Wordpress/CustomPostType/Timeframe.php:611 +#: src/Wordpress/CustomPostType/Timeframe.php:620 msgid "Configure timeframe" msgstr "Konfigurieren des Zeitrahmens" -#: src/Wordpress/CustomPostType/Timeframe.php:616 +#: src/Wordpress/CustomPostType/Timeframe.php:625 msgid "Full day" msgstr "Ganzer Tag" -#: src/Wordpress/CustomPostType/Timeframe.php:617 +#: src/Wordpress/CustomPostType/Timeframe.php:626 msgid "If this option is selected, users can choose only whole days for pickup and return. No specific time slots for pickup or return are offered. Select this option if the pickup/return should be arranged personally between the location and the user. " msgstr "Wenn diese Option ausgewählt ist, können Nutzende nur ganze Tage für die Abholung und Rückgabe auswählen. Es werden keine spezifischen Zeitfenster für Abholung oder Rückgabe angeboten. Wähle diese Option aus, wenn die Abholung/Rückgabe persönlich zwischen dem Standort und dem Benutzer vereinbart werden soll. " -#: src/Wordpress/CustomPostType/Timeframe.php:626 +#: src/Wordpress/CustomPostType/Timeframe.php:636 msgid "Grid" msgstr "Raster" -#: src/Wordpress/CustomPostType/Timeframe.php:627 +#: src/Wordpress/CustomPostType/Timeframe.php:637 msgid "Choose whether users can only select the entire from/to time period when booking (full slot) or book within the time period in an hourly grid. See the documentation: Manage Booking Timeframes" msgstr "Wähle aus, ob Nutzende bei der Buchung nur den gesamten Zeitraum (gesamter Slot) auswählen oder innerhalb des Zeitraums in einem stündlichen Raster buchen können. Weitere Informationen findest Du in der Dokumentation: Buchungszeiträume verwalten" -#: src/Wordpress/CustomPostType/Timeframe.php:634 +#: src/Wordpress/CustomPostType/Timeframe.php:644 msgid "Start time" msgstr "Startzeit" -#: src/Wordpress/CustomPostType/Timeframe.php:651 +#: src/Wordpress/CustomPostType/Timeframe.php:661 msgid "End time" msgstr "Endzeit" -#: src/Wordpress/CustomPostType/Timeframe.php:668 +#: src/Wordpress/CustomPostType/Timeframe.php:678 msgid "Timeframe Repetition" msgstr "Zeitrahmenwiederholung" -#: src/Wordpress/CustomPostType/Timeframe.php:669 +#: src/Wordpress/CustomPostType/Timeframe.php:679 msgid "Choose whether the time frame should repeat at specific intervals. The repetitions refer to the unit of a day. With the start and end date you define when the repetition interval starts and ends. If you choose \"weekly\", you can select specific days of the week below. Read the documentation for more information and examples." msgstr "Wähle aus, ob sich der Zeitrahmen in bestimmten Intervallen wiederholen soll. Die Wiederholungen beziehen sich auf die Einheit eines Tages. Mit dem Start- und Enddatum legst Du fest, wann das Wiederholungsintervall beginnt und endet. Wenn Du \"wöchentlich\" wählst, kannst Du bestimmte Tage der Woche unten auswählen. Lies die Dokumentation für weitere Informationen und Beispiele." -#: src/Wordpress/CustomPostType/Timeframe.php:687 +#: src/Wordpress/CustomPostType/Timeframe.php:699 msgid "Configure repetition" msgstr "Konfigurieren der Wiederholung" -#: src/Wordpress/CustomPostType/Timeframe.php:688 +#: src/Wordpress/CustomPostType/Timeframe.php:700 msgid "Below you can make settings regarding the time frame repetition. " msgstr "Unten kannst Du Einstellungen bezüglich der Zeitrahmenwiederholung vornehmen. " -#: src/Wordpress/CustomPostType/Timeframe.php:701 +#: src/Wordpress/CustomPostType/Timeframe.php:713 msgid "Set the start date. If you have selected repetition, this is the start date of the interval. " msgstr "Lege das Startdatum fest. Wenn Du Wiederholung ausgewählt hast, ist dies das Startdatum des Intervalls. " -#: src/Wordpress/CustomPostType/Timeframe.php:709 +#: src/Wordpress/CustomPostType/Timeframe.php:721 msgid "Weekdays" msgstr "Wochentage" -#: src/Wordpress/CustomPostType/Timeframe.php:713 +#: src/Wordpress/CustomPostType/Timeframe.php:725 msgid "Monday" msgstr "Montag" -#: src/Wordpress/CustomPostType/Timeframe.php:714 +#: src/Wordpress/CustomPostType/Timeframe.php:726 msgid "Tuesday" msgstr "Dienstag" -#: src/Wordpress/CustomPostType/Timeframe.php:715 +#: src/Wordpress/CustomPostType/Timeframe.php:727 msgid "Wednesday" msgstr "Mittwoch" -#: src/Wordpress/CustomPostType/Timeframe.php:716 +#: src/Wordpress/CustomPostType/Timeframe.php:728 msgid "Thursday" msgstr "Donnerstag" -#: src/Wordpress/CustomPostType/Timeframe.php:717 +#: src/Wordpress/CustomPostType/Timeframe.php:729 msgid "Friday" msgstr "Freitag" -#: src/Wordpress/CustomPostType/Timeframe.php:718 +#: src/Wordpress/CustomPostType/Timeframe.php:730 msgid "Saturday" msgstr "Samstag" -#: src/Wordpress/CustomPostType/Timeframe.php:719 +#: src/Wordpress/CustomPostType/Timeframe.php:731 msgid "Sunday" msgstr "Sonntag" -#: src/Wordpress/CustomPostType/Timeframe.php:725 +#: src/Wordpress/CustomPostType/Timeframe.php:738 msgid "" "Set the end date. If you have selected repetition, this is the end date of the interval. Leave blank if you do not want to set an end date.\n" "
Notice: If you want to select only one day (e.g. for holidays or blocked days) set the start and the end date to same day." msgstr "Lege das Enddatum fest. Wenn Du Wiederholung ausgewählt hast, ist dies das Enddatum des Intervalls. Lasse das Feld leer, wenn Du kein Enddatum festlegen möchten.
Hinweis: Wenn das Enddatum leer ist und keine Wiederholung ausgewählt wurde, gilt dieser Zeitrahmen nur für das festgelegte Startdatum. Wenn du nur einen Tag auswählen willst (z.B. für Feiertage / blockierte Tage), setzte das Start- und Enddatum auf den selben Tag." -#: src/Wordpress/CustomPostType/Timeframe.php:735 +#: src/Wordpress/CustomPostType/Timeframe.php:753 msgid "" "You can automatically generate booking codes. Codes can be generated only with the following settings:
\n" "\t\t\t\t- Whole day is enabled
\n" @@ -2504,112 +2500,112 @@ msgstr "" "\t\t\t\tWeitere Informationen in der Dokumentation\n" "\t\t\t\t" -#: src/Wordpress/CustomPostType/Timeframe.php:744 +#: src/Wordpress/CustomPostType/Timeframe.php:766 msgid "Create Booking Codes" msgstr "Buchungscodes generieren" -#: src/Wordpress/CustomPostType/Timeframe.php:745 +#: src/Wordpress/CustomPostType/Timeframe.php:767 msgid "Select to generate booking codes for each day within the start/end date. The booking codes will be generated after clicking \"Save / Update\"." msgstr "Wähle diese Option aus, um Buchungscodes für jeden Tag innerhalb des Start-/Enddatums zu generieren. Die Buchungscodes werden generiert, nachdem Du auf \"Speichern / Aktualisieren\" geklickt hast." -#: src/Wordpress/CustomPostType/Timeframe.php:751 +#: src/Wordpress/CustomPostType/Timeframe.php:773 msgid "Show Booking Codes" msgstr "Zeige Buchungs-Codes" -#: src/Wordpress/CustomPostType/Timeframe.php:752 +#: src/Wordpress/CustomPostType/Timeframe.php:774 msgid "Select whether users should be shown a booking code when booking." msgstr "Wähle aus, ob den Nutzenden bei der Buchung ein Buchungscode angezeigt werden soll." -#: src/Wordpress/CustomPostType/Timeframe.php:832 +#: src/Wordpress/CustomPostType/Timeframe.php:856 msgid "Full slot" msgstr "Gesamter Slot" -#: src/Wordpress/CustomPostType/Timeframe.php:833 +#: src/Wordpress/CustomPostType/Timeframe.php:857 msgid "Hourly" msgstr "Stündlich" -#: src/Wordpress/CustomPostType/Timeframe.php:845 +#: src/Wordpress/CustomPostType/Timeframe.php:870 msgid "Daily" msgstr "Täglich" -#: src/Wordpress/CustomPostType/Timeframe.php:846 +#: src/Wordpress/CustomPostType/Timeframe.php:871 msgid "Weekly" msgstr "Wöchentlich" -#: src/Wordpress/CustomPostType/Timeframe.php:847 +#: src/Wordpress/CustomPostType/Timeframe.php:872 msgid "Monthly" msgstr "Monatlich" -#: src/Wordpress/CustomPostType/Timeframe.php:848 +#: src/Wordpress/CustomPostType/Timeframe.php:873 msgid "Yearly" msgstr "Jährlich" -#: src/Wordpress/CustomPostType/Timeframe.php:1147 -#: src/Wordpress/CustomPostType/Timeframe.php:1149 +#: src/Wordpress/CustomPostType/Timeframe.php:1181 +#: src/Wordpress/CustomPostType/Timeframe.php:1183 msgid "Add new timeframe" msgstr "Hinzufügen eines neuen Zeitrahmens" -#: src/Wordpress/CustomPostType/Timeframe.php:1148 +#: src/Wordpress/CustomPostType/Timeframe.php:1182 msgid "Edit timeframe" msgstr "Zeitrahmen bearbeiten" -#: src/Wordpress/CustomPostType/Timeframe.php:1150 +#: src/Wordpress/CustomPostType/Timeframe.php:1184 msgid "Show timeframe" msgstr "Zeitrahmen anzeigen" -#: src/Wordpress/CustomPostType/Timeframe.php:1151 +#: src/Wordpress/CustomPostType/Timeframe.php:1185 msgid "Show timeframes" msgstr "Zeitrahmen anzeigen" -#: src/Wordpress/CustomPostType/Timeframe.php:1152 +#: src/Wordpress/CustomPostType/Timeframe.php:1186 msgid "Search timeframes" msgstr "Zeitrahmen suchen" -#: src/Wordpress/CustomPostType/Timeframe.php:1154 +#: src/Wordpress/CustomPostType/Timeframe.php:1188 msgid "No timeframes found in trash" msgstr "Keine Zeitrahmen im Papierkorb gefunden" -#: src/Wordpress/CustomPostType/Timeframe.php:1155 +#: src/Wordpress/CustomPostType/Timeframe.php:1189 msgid "Parent timeframes:" msgstr "Übergeordnete Zeitrahmen:" -#: src/Wordpress/CustomPostType/Timeframe.php:1156 +#: src/Wordpress/CustomPostType/Timeframe.php:1190 msgid "All timeframes" msgstr "Alle Zeitrahmen" -#: src/Wordpress/CustomPostType/Timeframe.php:1159 +#: src/Wordpress/CustomPostType/Timeframe.php:1193 msgid "Add to timeframe" msgstr "Zum Zeitrahmen hinzufügen" -#: src/Wordpress/CustomPostType/Timeframe.php:1160 +#: src/Wordpress/CustomPostType/Timeframe.php:1194 msgid "Added to timeframe" msgstr "Zum Zeitrahmen hinzugefügt" -#: src/Wordpress/CustomPostType/Timeframe.php:1162 +#: src/Wordpress/CustomPostType/Timeframe.php:1196 msgid "set timeframe image" msgstr "Festlegen des Zeitrahmenbilds" -#: src/Wordpress/CustomPostType/Timeframe.php:1163 +#: src/Wordpress/CustomPostType/Timeframe.php:1197 msgid "remove timeframe image" msgstr "Zeitrahmenbild entfernen" -#: src/Wordpress/CustomPostType/Timeframe.php:1164 +#: src/Wordpress/CustomPostType/Timeframe.php:1198 msgid "use as timeframe image" msgstr "Verwendung als Zeitrahmenbild" -#: src/Wordpress/Options/AdminOptions.php:54 +#: src/Wordpress/Options/AdminOptions.php:53 msgid "Default values for following fields automatically set or restored, because they were empty:
" msgstr "Standardwerte für folgende Felder wurden automatisch festgelegt oder wiederhergestellt, da sie leer waren:
" -#: src/Wordpress/Options/OptionsTab.php:56 +#: src/Wordpress/Options/OptionsTab.php:55 msgid "CommonsBooking" msgstr "CommonsBooking" -#: src/Wordpress/Options/OptionsTab.php:148 +#: src/Wordpress/Options/OptionsTab.php:146 msgid "The export path does not exist or is not readable." msgstr "Der Exportpfad ist nicht vorhanden oder nicht lesbar." -#: src/Wordpress/Options/OptionsTab.php:156 +#: src/Wordpress/Options/OptionsTab.php:154 msgid "The export path is not writeable." msgstr "Der Exportpfad ist nicht beschreibbar." @@ -2637,25 +2633,25 @@ msgstr "

  • Mein Profil
  • " msgid "
  • Log out
  • " msgstr "
  • Abmelden
  • " -#: src/Wordpress/Widget/UserWidget.php:85 +#: src/Wordpress/Widget/UserWidget.php:83 msgid "You are not logged in." msgstr "Du bist nicht angemeldet." #. translators: $s = wp login url -#: src/Wordpress/Widget/UserWidget.php:88 +#: src/Wordpress/Widget/UserWidget.php:86 msgid "
  • Login
  • " msgstr "
  • Anmelden
  • " #. translators: $s = wp registration url -#: src/Wordpress/Widget/UserWidget.php:90 +#: src/Wordpress/Widget/UserWidget.php:88 msgid "
  • Register
  • " msgstr "
  • Registrieren
  • " -#: src/Wordpress/Widget/UserWidget.php:109 +#: src/Wordpress/Widget/UserWidget.php:106 msgid "Title:" msgstr "Titel:" -#: src/Wordpress/Widget/UserWidget.php:115 +#: src/Wordpress/Widget/UserWidget.php:112 msgid "Text:" msgstr "Text:" @@ -2675,8 +2671,8 @@ msgstr "Buchung stornieren" msgid "You are not allowed to access this booking." msgstr "Du darfst nicht auf diese Buchung zugreifen." -#: templates/booking-single-notallowed.php:14 -#: templates/timeframe-notallowed.php:14 +#: templates/booking-single-notallowed.php:15 +#: templates/timeframe-notallowed.php:15 msgid "Login to your account" msgstr "Login zu deinem Nutzerkonto" @@ -2707,27 +2703,27 @@ msgstr "Deine Profildaten" msgid "Admin Booking by" msgstr "Admin-Buchung von" -#: templates/booking-single.php:140 +#: templates/booking-single.php:142 msgid "Your E-Mail" msgstr "Deine E-Mail" -#: templates/calendar-key.php:12 +#: templates/calendar-key.php:11 msgid "Color legend" msgstr "Farblegende" -#: templates/calendar-key.php:13 +#: templates/calendar-key.php:12 msgid "bookable" msgstr "buchbar" -#: templates/calendar-key.php:14 +#: templates/calendar-key.php:13 msgid "booked/blocked" msgstr "gebucht / gesperrt" -#: templates/calendar-key.php:15 +#: templates/calendar-key.php:14 msgid "station closed" msgstr "Standort geschlossen" -#: templates/calendar-key.php:16 +#: templates/calendar-key.php:15 msgid "not bookable" msgstr "nicht buchbar" @@ -2784,333 +2780,333 @@ msgid "No returns today" msgstr "Keine Rückgaben heute" #. translators: %1$s: wp_login_url, 1$s: wp_registration_url -#: templates/item-single.php:42 -#: templates/location-single.php:42 +#: templates/item-single.php:44 +#: templates/location-single.php:43 msgid "To be able to book, you must first login or register." msgstr "Um buchen zu können, musst du dich zuerst anmelden oder registrieren." -#: templates/location-calendar-header.php:31 +#: templates/location-calendar-header.php:33 msgid "Pickup instructions:" msgstr "Abhol-Hinweise:" -#: templates/location-single-meta.php:23 +#: templates/location-single-meta.php:22 msgid "Adress" msgstr "Adresse" -#: templates/location-single-meta.php:34 +#: templates/location-single-meta.php:33 msgid "Location contact" msgstr "Standort-Kontakt" -#: src/Wordpress/CustomPostType/Map.php:76 +#: src/Wordpress/CustomPostType/Map.php:74 msgid "base map" msgstr "Basiskarte" -#: src/Wordpress/CustomPostType/Map.php:77 +#: src/Wordpress/CustomPostType/Map.php:75 msgid "the base map defines the rendering style of the map tiles" msgstr "Die Grundkarte definiert den Rendering-Stil der Kartenkacheln" -#: src/Wordpress/CustomPostType/Map.php:81 +#: src/Wordpress/CustomPostType/Map.php:79 msgid "OSM - mapnik" msgstr "OSM - mapnik" -#: src/Wordpress/CustomPostType/Map.php:82 +#: src/Wordpress/CustomPostType/Map.php:80 msgid "OSM - german style" msgstr "OSM - deutscher Stil" -#: src/Wordpress/CustomPostType/Map.php:92 +#: src/Wordpress/CustomPostType/Map.php:90 msgid "show scale" msgstr "Maßstab anzeigen" -#: src/Wordpress/CustomPostType/Map.php:98 +#: src/Wordpress/CustomPostType/Map.php:96 msgid "map height" msgstr "Kartenhöhe" -#: src/Wordpress/CustomPostType/Map.php:99 +#: src/Wordpress/CustomPostType/Map.php:97 msgid "the height the map is rendered with - the width is the same as of the parent element" msgstr "Die Höhe, mit der die Karte gerendert wird - die Breite ist die gleiche wie beim übergeordneten Element" -#: src/Wordpress/CustomPostType/Map.php:109 +#: src/Wordpress/CustomPostType/Map.php:107 msgid "no locations message" msgstr "Meldung, wenn keine Standorte gefunden wurden" -#: src/Wordpress/CustomPostType/Map.php:110 +#: src/Wordpress/CustomPostType/Map.php:108 msgid "in case a user filters locations and gets no result, a message is shown - here the text can be customized" msgstr "Falls ein Benutzer Standorte filtert und kein Ergebnis erhält, wird eine Meldung angezeigt - hier kann der Text angepasst werden" -#: src/Wordpress/CustomPostType/Map.php:116 +#: src/Wordpress/CustomPostType/Map.php:114 msgid "enable data export" msgstr "Datenexport aktivieren" -#: src/Wordpress/CustomPostType/Map.php:117 +#: src/Wordpress/CustomPostType/Map.php:115 msgid "activate to enable a button that allows the export of map data (geojson format)" msgstr "Aktiviere, um eine Schaltfläche zu aktivieren, die den Export von Kartendaten ermöglicht (Geojson-Format)" -#: src/Wordpress/CustomPostType/Map.php:123 +#: src/Wordpress/CustomPostType/Map.php:121 msgid "Zoom" msgstr "Zoom" -#: src/Wordpress/CustomPostType/Map.php:129 +#: src/Wordpress/CustomPostType/Map.php:127 msgid "min. zoom level" msgstr "min. Zoomstufe" -#: src/Wordpress/CustomPostType/Map.php:130 +#: src/Wordpress/CustomPostType/Map.php:128 msgid "the minimal zoom level a user can choose" msgstr "die minimale Zoomstufe, die ein*e Benutzer*in auswählen kann" -#: src/Wordpress/CustomPostType/Map.php:142 +#: src/Wordpress/CustomPostType/Map.php:140 msgid "max. zoom level" msgstr "max. Zoomstufe" -#: src/Wordpress/CustomPostType/Map.php:143 +#: src/Wordpress/CustomPostType/Map.php:141 msgid "the maximal zoom level a user can choose" msgstr "die maximale Zoomstufe, die ein*e Benutzer*in auswählen kann" -#: src/Wordpress/CustomPostType/Map.php:155 +#: src/Wordpress/CustomPostType/Map.php:153 msgid "start zoom level" msgstr "Initiale Zoomstufe" -#: src/Wordpress/CustomPostType/Map.php:156 +#: src/Wordpress/CustomPostType/Map.php:154 msgid "the zoom level that will be set when the map is loaded" msgstr "die Zoomstufe, die beim Laden der Karte festgelegt wird" -#: src/Wordpress/CustomPostType/Map.php:168 +#: src/Wordpress/CustomPostType/Map.php:166 msgid "enable scroll wheel zoom" msgstr "Scrollradzoom aktivieren" -#: src/Wordpress/CustomPostType/Map.php:169 +#: src/Wordpress/CustomPostType/Map.php:167 msgid "when activated users can zoom the map using the scroll wheel" msgstr "Wenn aktiviert, können Benutzende die Karte mit dem Scrollrad zoomen" -#: src/Wordpress/CustomPostType/Map.php:183 +#: src/Wordpress/CustomPostType/Map.php:181 msgid "start latitude" msgstr "Start-Breitengrad" -#: src/Wordpress/CustomPostType/Map.php:184 +#: src/Wordpress/CustomPostType/Map.php:182 msgid "the latitude of the map center when the map is loaded" msgstr "der Breitengrad des Kartenzentrums, wenn die Karte geladen wird" -#: src/Wordpress/CustomPostType/Map.php:190 +#: src/Wordpress/CustomPostType/Map.php:188 msgid "start longitude" msgstr "Initialer Längengrad" -#: src/Wordpress/CustomPostType/Map.php:191 +#: src/Wordpress/CustomPostType/Map.php:189 msgid "the longitude of the map center when the map is loaded" msgstr "der Breitengrad des Kartenzentrums, wenn die Karte geladen wird" -#: src/Wordpress/CustomPostType/Map.php:197 +#: src/Wordpress/CustomPostType/Map.php:195 msgid "initial adjustment to marker bounds" msgstr "anfängliche Anpassung an Markergrenzen" -#: src/Wordpress/CustomPostType/Map.php:198 +#: src/Wordpress/CustomPostType/Map.php:196 msgid "adjust map section to bounds of shown markers automatically when map is loaded" msgstr "Kartenabschnitt automatisch an Grenzen der angezeigten Marker anpassen, wenn die Karte geladen wird" -#: src/Wordpress/CustomPostType/Map.php:204 +#: src/Wordpress/CustomPostType/Map.php:202 msgid "adjustment to marker bounds on filter" msgstr "Anpassung an Markergrenzen am Filter" -#: src/Wordpress/CustomPostType/Map.php:205 +#: src/Wordpress/CustomPostType/Map.php:203 msgid "adjust map section to bounds of shown markers automatically when filtered by users" msgstr "Kartenabschnitt automatisch an die Grenzen der angezeigten Marker anpassen, wenn sie von Benutzern gefiltert werden" -#: src/Wordpress/CustomPostType/Map.php:213 +#: src/Wordpress/CustomPostType/Map.php:211 msgid "Marker Tooltip" msgstr "Kartenmarker Tooltip" -#: src/Wordpress/CustomPostType/Map.php:220 +#: src/Wordpress/CustomPostType/Map.php:218 msgid "activate to show the marker tooltips permanently" msgstr "aktivieren, um die Marker-Tooltips dauerhaft anzuzeigen" -#: src/Wordpress/CustomPostType/Map.php:227 +#: src/Wordpress/CustomPostType/Map.php:225 msgid "Marker Popup" msgstr "Marker Popup" -#: src/Wordpress/CustomPostType/Map.php:233 +#: src/Wordpress/CustomPostType/Map.php:231 msgid "show item availability" msgstr "Artikelverfügbarkeit anzeigen" -#: src/Wordpress/CustomPostType/Map.php:234 +#: src/Wordpress/CustomPostType/Map.php:232 msgid "activate to show the item availability in the marker popup" msgstr "aktivieren, um die Artikelverfügbarkeit im Marker-Popup anzuzeigen" -#: src/Wordpress/CustomPostType/Map.php:239 +#: src/Wordpress/CustomPostType/Map.php:237 msgid "Max. available days in popup" msgstr "Max. Anzahl verfügbare Tage im Popup" -#: src/Wordpress/CustomPostType/Map.php:240 +#: src/Wordpress/CustomPostType/Map.php:238 msgid "Set how many days are displayed on the popup (starting from today)" msgstr "Lege fest, wie viele Tage im Popup angezeigt werden (ab heute)" -#: src/Wordpress/CustomPostType/Map.php:251 +#: src/Wordpress/CustomPostType/Map.php:249 msgid "Maximum days to choose in map availabilty filter " msgstr "Maximal Anzahl an Tagen, die im Verfügbarkeitsfilter gewählt werden können " -#: src/Wordpress/CustomPostType/Map.php:252 +#: src/Wordpress/CustomPostType/Map.php:250 msgid "Notice: Defines the maximun days a user can choose in the availabilty filter in frontend map" msgstr "Hinweis: Definiert die maximalen Tage, die ein Benutzer im Verfügbarkeitsfilter in der Frontend-Karte auswählen kann" -#: src/Wordpress/CustomPostType/Map.php:264 +#: src/Wordpress/CustomPostType/Map.php:262 msgid "Custom Marker" msgstr "Benutzerdefinierter Marker" -#: src/Wordpress/CustomPostType/Map.php:270 +#: src/Wordpress/CustomPostType/Map.php:268 msgid "image file" msgstr "Bilddatei" -#: src/Wordpress/CustomPostType/Map.php:271 -#: src/Wordpress/CustomPostType/Map.php:348 -#: src/Wordpress/CustomPostType/Map.php:404 +#: src/Wordpress/CustomPostType/Map.php:269 +#: src/Wordpress/CustomPostType/Map.php:346 +#: src/Wordpress/CustomPostType/Map.php:402 msgid "the default marker icon can be replaced by a custom image" msgstr "Das Standardmarkersymbol kann durch ein benutzerdefiniertes Bild ersetzt werden" -#: src/Wordpress/CustomPostType/Map.php:285 -#: src/Wordpress/CustomPostType/Map.php:296 -#: src/Wordpress/CustomPostType/Map.php:362 -#: src/Wordpress/CustomPostType/Map.php:373 -#: src/Wordpress/CustomPostType/Map.php:418 -#: src/Wordpress/CustomPostType/Map.php:429 +#: src/Wordpress/CustomPostType/Map.php:283 +#: src/Wordpress/CustomPostType/Map.php:294 +#: src/Wordpress/CustomPostType/Map.php:360 +#: src/Wordpress/CustomPostType/Map.php:371 +#: src/Wordpress/CustomPostType/Map.php:416 +#: src/Wordpress/CustomPostType/Map.php:427 msgid "the size of the custom marker icon image as it is shown on the map" msgstr "die Größe des benutzerdefinierten Markersymbolbildes, wie es auf der Karte angezeigt wird" -#: src/Wordpress/CustomPostType/Map.php:306 -#: src/Wordpress/CustomPostType/Map.php:316 -#: src/Wordpress/CustomPostType/Map.php:439 -#: src/Wordpress/CustomPostType/Map.php:449 +#: src/Wordpress/CustomPostType/Map.php:304 +#: src/Wordpress/CustomPostType/Map.php:314 +#: src/Wordpress/CustomPostType/Map.php:437 +#: src/Wordpress/CustomPostType/Map.php:447 msgid "anchor point" msgstr "Ankerpunkt" -#: src/Wordpress/CustomPostType/Map.php:307 -#: src/Wordpress/CustomPostType/Map.php:317 -#: src/Wordpress/CustomPostType/Map.php:440 -#: src/Wordpress/CustomPostType/Map.php:450 +#: src/Wordpress/CustomPostType/Map.php:305 +#: src/Wordpress/CustomPostType/Map.php:315 +#: src/Wordpress/CustomPostType/Map.php:438 +#: src/Wordpress/CustomPostType/Map.php:448 msgid "the position of the anchor point of the icon image, seen from the left top corner of the icon, often it is half of the width and full height of the icon size - this point is used to place the marker on the geo coordinates" msgstr "die Position des Ankerpunkts des Symbolbildes, von der linken oberen Ecke des Symbols aus gesehen, oft ist es die Hälfte der Breite und der vollen Höhe der Symbolgröße - dieser Punkt wird verwendet, um den Marker auf den Geo-Koordinaten zu platzieren" -#: src/Wordpress/CustomPostType/Map.php:328 +#: src/Wordpress/CustomPostType/Map.php:326 msgid "Cluster" msgstr "Cluster" -#: src/Wordpress/CustomPostType/Map.php:334 +#: src/Wordpress/CustomPostType/Map.php:332 msgid "max. cluster radius" msgstr "max. Clusterradius" -#: src/Wordpress/CustomPostType/Map.php:335 +#: src/Wordpress/CustomPostType/Map.php:333 msgid "combine markers to a cluster within given radius - 0 for deactivation" msgstr "Marker zu einem Cluster innerhalb eines bestimmten Radius kombinieren - 0 für die Deaktivierung" -#: src/Wordpress/CustomPostType/Map.php:347 +#: src/Wordpress/CustomPostType/Map.php:345 msgid "Custom Cluster Marker" msgstr "Benutzerdefinierte Cluster-Marker" -#: src/Wordpress/CustomPostType/Map.php:385 +#: src/Wordpress/CustomPostType/Map.php:383 msgid "Appearance by Item Status" msgstr "Darstellung nach Artikelstatus" -#: src/Wordpress/CustomPostType/Map.php:391 +#: src/Wordpress/CustomPostType/Map.php:389 msgid "appearance" msgstr "Erscheinen" -#: src/Wordpress/CustomPostType/Map.php:392 +#: src/Wordpress/CustomPostType/Map.php:390 msgid "how locations with items that are in draft status should be handled" msgstr "Wie Standorte mit Artikeln, die sich im Entwurfsstatus befinden, behandelt werden sollen" -#: src/Wordpress/CustomPostType/Map.php:396 +#: src/Wordpress/CustomPostType/Map.php:394 msgid "don't show drafts" msgstr "Entwürfe nicht anzeigen" -#: src/Wordpress/CustomPostType/Map.php:397 +#: src/Wordpress/CustomPostType/Map.php:395 msgid "show only drafts" msgstr "Nur Entwürfe anzeigen" -#: src/Wordpress/CustomPostType/Map.php:398 +#: src/Wordpress/CustomPostType/Map.php:396 msgid "show all together" msgstr "Alle anzeigen" -#: src/Wordpress/CustomPostType/Map.php:403 +#: src/Wordpress/CustomPostType/Map.php:401 msgid "Custom Item Draft Marker" msgstr "Benutzerdefinierte Artikel-Entwurfsmarkierung" -#: src/Wordpress/CustomPostType/Map.php:461 +#: src/Wordpress/CustomPostType/Map.php:459 msgid "Filter for Users" msgstr "Filter für Benutzer" -#: src/Wordpress/CustomPostType/Map.php:467 +#: src/Wordpress/CustomPostType/Map.php:465 msgid "show location distance filter" msgstr "Filter für Standort-Entfernung anzeigen" -#: src/Wordpress/CustomPostType/Map.php:468 +#: src/Wordpress/CustomPostType/Map.php:466 msgid "activate to show the location distance filter" msgstr "aktivieren, um den Standortentfernungsfilter anzuzeigen" -#: src/Wordpress/CustomPostType/Map.php:473 +#: src/Wordpress/CustomPostType/Map.php:471 msgid "label for location distance filter" msgstr "Bezeichnung für Standortentfernungsfilter" -#: src/Wordpress/CustomPostType/Map.php:474 +#: src/Wordpress/CustomPostType/Map.php:472 msgid "alternative label for the location distance filter" msgstr "alternative Bezeichnung für den Positionsentfernungsfilter" -#: src/Wordpress/CustomPostType/Map.php:482 -#: src/Wordpress/CustomPostType/Map.php:488 +#: src/Wordpress/CustomPostType/Map.php:480 +#: src/Wordpress/CustomPostType/Map.php:486 msgid "address search bounds - left bottom" msgstr "Begrenzung Adresssuche - links unten" -#: src/Wordpress/CustomPostType/Map.php:482 -#: src/Wordpress/CustomPostType/Map.php:494 +#: src/Wordpress/CustomPostType/Map.php:480 +#: src/Wordpress/CustomPostType/Map.php:492 msgid "longitude" msgstr "Längengrad" -#: src/Wordpress/CustomPostType/Map.php:488 -#: src/Wordpress/CustomPostType/Map.php:500 +#: src/Wordpress/CustomPostType/Map.php:486 +#: src/Wordpress/CustomPostType/Map.php:498 msgid "latitude" msgstr "Breitengrad" -#: src/Wordpress/CustomPostType/Map.php:494 -#: src/Wordpress/CustomPostType/Map.php:500 +#: src/Wordpress/CustomPostType/Map.php:492 +#: src/Wordpress/CustomPostType/Map.php:498 msgid "address search bounds - right top" msgstr "Begrenzung Adresssuche - rechts oben" -#: src/Wordpress/CustomPostType/Map.php:506 +#: src/Wordpress/CustomPostType/Map.php:504 msgid "show item availability filter" msgstr "Artikelverfügbarkeitsfilter anzeigen" -#: src/Wordpress/CustomPostType/Map.php:507 +#: src/Wordpress/CustomPostType/Map.php:505 msgid "activate to show the item availability filter" msgstr "aktivieren, um den Artikelverfügbarkeitsfilter anzuzeigen" -#: src/Wordpress/CustomPostType/Map.php:512 +#: src/Wordpress/CustomPostType/Map.php:510 msgid "label for item availability filter" msgstr "Bezeichnung für Artikelverfügbarkeitsfilter" -#: src/Wordpress/CustomPostType/Map.php:513 +#: src/Wordpress/CustomPostType/Map.php:511 msgid "alternative label for the item availability filter" msgstr "alternative Bezeichnung für den Artikelverfügbarkeitsfilter" -#: src/Wordpress/CustomPostType/Map.php:521 +#: src/Wordpress/CustomPostType/Map.php:519 msgid "label for item category filter" msgstr "Bezeichnung für Artikelkategoriefilter" -#: src/Wordpress/CustomPostType/Map.php:522 +#: src/Wordpress/CustomPostType/Map.php:520 msgid "alternative label for the item category filter" msgstr "Alternative Bezeichnung für den Artikelkategoriefilter" -#: src/Wordpress/CustomPostType/Map.php:530 +#: src/Wordpress/CustomPostType/Map.php:528 msgid "custom text for filter button" msgstr "Benutzerdefinierter Text für Filterschaltfläche" -#: src/Wordpress/CustomPostType/Map.php:531 +#: src/Wordpress/CustomPostType/Map.php:529 msgid "the text for the button used for filtering" msgstr "Der Text für die zum Filtern verwendete Schaltfläche" -#: src/Wordpress/CustomPostType/Map.php:593 +#: src/Wordpress/CustomPostType/Map.php:591 msgid "Filter Item Presets" msgstr "Vorfiltern nach Artikel-Kategorie" -#: src/Wordpress/CustomPostType/Map.php:594 +#: src/Wordpress/CustomPostType/Map.php:592 msgid "select the categories that are used to prefilter the items that are shown on the map - none for all items" msgstr "Wähle die Kategorien, die benutzt werden um die Artikel, die auf der Karte angezeigt werden, vorzufiltern - leer lassen, um alle Artikel anzuzeigen" -#: src/Wordpress/CustomPostType/Map.php:601 +#: src/Wordpress/CustomPostType/Map.php:599 msgid "Filter Location Presets" msgstr "Vorfiltern nach Standort-Kategorien" @@ -3196,45 +3192,45 @@ msgstr "Buchungen sind auf maximal %1$s Tage im Voraus beschränkt." msgid "It is not possible to access this timeframe on frontend. Please edit timeframe in backend. If you want to check the result of your timeframe settings visit the item or location in frontend to see the booking calender" msgstr "Es ist nicht möglich, diesen Zeitrahmen im Frontend abzurufen. Bitte bearbeite den Zeitrahmen im Backend. Wenn du das Ergebnis deiner Zeitrahmeneinstellungen überprüfen möchtest, rufe den Artikel oder Standort im Frontend auf, um den Buchungskalender zu sehen" -#: src/Model/Booking.php:1026 +#: src/Model/Booking.php:1020 msgid "Cancelled" msgstr "Storniert" -#: src/Model/Timeframe.php:620 +#: src/Model/Timeframe.php:627 msgid "The start- and end-time of the timeframe can not be the same. Please check the full-day checkbox if you want users to be able to book the full day." msgstr "Die Start- und Endzeit des Zeitrahmens dürfen nicht gleich sein. Wenn der gesamte Tag buchbar sein soll muss die Option \"Ganzer Tag\" angewählt sein." -#: src/Plugin.php:709 -#: src/Plugin.php:724 -#: src/Wordpress/CustomPostType/Booking.php:922 +#: src/Plugin.php:713 +#: src/Plugin.php:728 +#: src/Wordpress/CustomPostType/Booking.php:924 msgid "CommonsBooking Bookings" msgstr "CommonsBooking Buchungen" -#: src/Wordpress/CustomPostType/Booking.php:526 +#: src/Wordpress/CustomPostType/Booking.php:528 msgid "Bookings not found" msgstr "Keine Buchungen gefunden" -#: src/Wordpress/CustomPostType/Booking.php:947 +#: src/Wordpress/CustomPostType/Booking.php:949 msgid "Booking start" msgstr "Buchungsbeginn" -#: src/Wordpress/CustomPostType/Booking.php:951 +#: src/Wordpress/CustomPostType/Booking.php:953 msgid "Booking end" msgstr "Buchungsende" -#: src/Wordpress/CustomPostType/Booking.php:955 +#: src/Wordpress/CustomPostType/Booking.php:957 msgid "Time of booking" msgstr "Buchungszeit" -#: src/Wordpress/CustomPostType/Booking.php:963 +#: src/Wordpress/CustomPostType/Booking.php:965 msgid "Booking code" msgstr "Buchungscode" -#: src/Wordpress/CustomPostType/Booking.php:979 +#: src/Wordpress/CustomPostType/Booking.php:981 msgid "Time of cancellation" msgstr "Storniert am" -#: src/Wordpress/CustomPostType/Booking.php:983 +#: src/Wordpress/CustomPostType/Booking.php:985 msgid "Admin booking by" msgstr "Adminbuchung von" @@ -3254,107 +3250,107 @@ msgstr "" "\t\t\t\t\tWenn du Templates geändert hast, sichere sie bitte und wende deine Änderungen nach dem Update erneut an.
    \n" "\t\t\t\t\t

    Bitte lies auch die %1$sUpdate Informationen%2$s und erstelle ein komplettes Backup deiner Seite vor dem Upgrade." -#: includes/OptionsArray.php:145 +#: includes/OptionsArray.php:172 msgid "Global location settings" msgstr "Globale Standorteinstellungen" -#: includes/OptionsArray.php:146 +#: includes/OptionsArray.php:173 msgid "These settings are used for all locations. You can overwrite these settings for each location in the location settings." msgstr "Diese Einstellungen werden für alle Standorte verwendet. Die Einstellungen können Sie für jeden Standort individuell in den Standorteinstellungen überschreiben werden." -#: src/Wordpress/CustomPostType/Location.php:391 +#: src/Wordpress/CustomPostType/Location.php:432 msgid "Use global location settings" msgstr "Globale Standorteinstellungen nutzen" -#: src/Wordpress/CustomPostType/Location.php:392 +#: src/Wordpress/CustomPostType/Location.php:433 msgid "If selected, the global location settings (under the \"General\" tab) will be used for this location. If not selected, the settings below will be used." msgstr "Wenn diese Option ausgewählt ist, werden die globalen Standorteinstellungen ( im Reiter \"Allgemein\") für diesen Standort verwendet. Wenn sie nicht ausgewählt ist, werden die Einstellungen unten verwendet." -#: src/Wordpress/CustomPostType/Location.php:460 +#: src/Wordpress/CustomPostType/Location.php:507 msgid "Count locked days when overbooking" msgstr "Gesperrte Tage bei Überbuchung zählen" -#: src/Wordpress/CustomPostType/Location.php:466 +#: src/Wordpress/CustomPostType/Location.php:513 msgid "Count connected locked days as one" msgstr "Zusammenhängende gesperrte Tage werden als Einheit gezählt" -#: src/Wordpress/CustomPostType/Location.php:467 +#: src/Wordpress/CustomPostType/Location.php:514 msgid "Here you can specify, if a connected span of locked days should be counted individually or just use up x amount of the maximum quota the user is allowed to book. If you set this field to 0, every day will be counted individually. If you set this field to 1, all overbooked days, no matter how many, will always count for 1 day. If you set this to 2, they will count a maximum of two days and so on." msgstr "Hier kann festgelegt werden, ob eine zusammenhängende Spanne von überbuchten Tagen einzeln gezählt werden soll oder ob nur x Tage des maximalen Kontingents, das der Benutzer buchen darf, verbraucht werden sollen. Wenn dieses Feld auf 0 gesetzt wird, wird jeder Tag einzeln gezählt. Wenn dieses Feld auf 1 gesetzt wird, werden alle überbuchten Tage, egal wie viele, immer nur als 1 Tag gezählt. Wenn dieses Feld auf 2 gesetzt wird, werden maximal zwei Tage gezählt und so weiter." -#: src/Wordpress/CustomPostType/Location.php:461 +#: src/Wordpress/CustomPostType/Location.php:508 msgid "If selected, days that are overbooked will be counted towards the maximum number of bookable days. If this option is disabled, locked days that are overbooked will allow for bookings that are longer than the maximum number of bookable days configured for the timeframe." msgstr "Ist diese Option aktiviert, werden überbuchte Tage auf die maximale Anzahl buchbarer Tage angerechnet. Wenn diese Option deaktiviert ist, dann werden überbuchte Tage nicht zusätzlich gezählt und ermöglichen Buchungszeiträume die länger sind als die im Zeitrahmen konfigurierte maximale Anzahl an gebuchten Tagen." #. translators: first %s = timeframe-ID, second %s is timeframe post_title -#: src/Model/Timeframe.php:681 +#: src/Model/Timeframe.php:688 msgid "See overlapping timeframe ID: %1$s %2$s" msgstr "Sich überschneidende Zeitrahmen ID: %1$s %2$s" -#: src/Model/Timeframe.php:778 +#: src/Model/Timeframe.php:787 msgid "Overlapping bookable timeframes are only allowed to have the same grid." msgstr "Sich überschneidende buchbare Zeiträume müssen das gleiche Raster haben." -#: src/Model/Timeframe.php:808 +#: src/Model/Timeframe.php:817 msgid "Overlapping bookable timeframes are not allowed to have the same weekdays." msgstr "Mehrere buchbare Zeiträume überschneiden sich in den definierten Wochentagen." -#: src/Model/Timeframe.php:820 +#: src/Model/Timeframe.php:829 msgid "Overlapping bookable timeframes are not allowed to have the same dates." msgstr "Mehrere buchbare Zeiträume überschneiden sich in dem definierten Datumsbereich." -#: src/Model/Timeframe.php:827 -#: src/Model/Timeframe.php:834 +#: src/Model/Timeframe.php:836 +#: src/Model/Timeframe.php:843 msgid "The other timeframe is overlapping with your weekly configuration." msgstr "Der andere Zeitrahmen überschneidet sich mit einer wöchentlichen Konfiguration." -#: src/Wordpress/CustomPostType/Timeframe.php:161 +#: src/Wordpress/CustomPostType/Timeframe.php:164 msgid "Select Dates:" msgstr "Ausgewählte Daten:" -#: src/Wordpress/CustomPostType/Timeframe.php:693 +#: src/Wordpress/CustomPostType/Timeframe.php:705 msgid "Selected manual dates" msgstr "Manuell ausgewählte Daten" -#: src/Wordpress/CustomPostType/Timeframe.php:694 +#: src/Wordpress/CustomPostType/Timeframe.php:706 msgid "Enter the dates in the YYYY-MM-DD format here, the dates are separated by a comma.
    Example: 2023-05-24,2023-06-24
    You can also use the datepicker above to pick dates for this field." msgstr "Gib hier die Daten im JJJJ-MM-TT Format kommasepariert ein.
    Beispiel: 2023-05-24,2023-06-24
    Du kannst auch den obigen Kalender verwenden, um Daten für dieses Feld auszuwählen." -#: src/Wordpress/CustomPostType/Timeframe.php:843 +#: src/Wordpress/CustomPostType/Timeframe.php:868 msgid "No repetition" msgstr "Keine Wiederholung" -#: src/Wordpress/CustomPostType/Timeframe.php:844 +#: src/Wordpress/CustomPostType/Timeframe.php:869 msgid "Manual repetition" msgstr "Manuelle Wiederholung" -#: src/Service/Holiday.php:30 +#: src/Service/Holiday.php:34 msgid "Year" msgstr "Jahr" -#: src/Service/Holiday.php:56 +#: src/Service/Holiday.php:68 msgid "Load Holidays" msgstr "Feiertage laden" -#: src/Wordpress/CustomPostType/Timeframe.php:679 +#: src/Wordpress/CustomPostType/Timeframe.php:690 msgid "Import holidays" msgstr "Feiertage importieren" -#: src/Wordpress/CustomPostType/Timeframe.php:680 +#: src/Wordpress/CustomPostType/Timeframe.php:691 msgid "Select the year and state to import holidays for (as of now only German holidays are supported)" msgstr "Wählen Sie das Jahr und das Bundesland, für das Sie Feiertage importieren möchten (derzeit werden Feiertage in Deutschland unterstützt)" -#: src/Model/Timeframe.php:794 +#: src/Model/Timeframe.php:803 msgid "Daily repeated time periods are not allowed to overlap." msgstr "Täglich wiederholende Zeiträume dürfen sich nicht überschneiden." -#: includes/OptionsArray.php:156 -#: includes/OptionsArray.php:160 -#: includes/OptionsArray.php:167 +#: includes/OptionsArray.php:183 +#: includes/OptionsArray.php:187 +#: includes/OptionsArray.php:199 msgid "Booking codes" msgstr "Buchungscodes" -#: includes/OptionsArray.php:163 +#: includes/OptionsArray.php:191 msgid "" "Enter the booking codes to be generated in advance for booking types with all-day booking time frames. Enter booking codes as a comma separated list, e.g.: Code1,Code2,Code3,Code4\n" "
    More information in the documentation: Booking codes" @@ -3362,35 +3358,35 @@ msgstr "" "Geben Sie die Buchungscodes ein, die für Buchungen mit ganztägigen Buchungszeiträumen im Voraus generiert werden sollen. Geben Sie die Buchungscodes als kommagetrennte Liste ein, z.B.: Code1,Code2,Code3,Code4\n" "
    Mehr Informationen dazu in der Dokumentation: Buchungscodes" -#: includes/OptionsArray.php:172 +#: includes/OptionsArray.php:204 msgid "Show booking codes for x days" msgstr "Buchungscodes für x Tage anzeigen" -#: includes/OptionsArray.php:173 +#: includes/OptionsArray.php:205 msgid "Displays booking codes for the next x days on the timeframe page" msgstr "Zeigt Buchungscodes für die nächsten x Tage auf der Zeitrahmenseite an" -#: includes/OptionsArray.php:185 +#: includes/OptionsArray.php:217 msgid "Booking codes by email" msgstr "Buchungscodes per E-Mail" -#: includes/OptionsArray.php:188 +#: includes/OptionsArray.php:220 msgid "Send booking codes by email to location email(s) (automated by cron or ad hoc)" msgstr "Senden von Buchungscodes per E-Mail an die Standort-E-Mail(s) (automatisch per Cron oder ad hoc)" -#: includes/OptionsArray.php:191 +#: includes/OptionsArray.php:223 msgid "Subject for booking codes email" msgstr "Betreff für Buchungscodes E-Mail" -#: includes/OptionsArray.php:194 +#: includes/OptionsArray.php:226 msgid "Booking codes for {{codes:formatDateRange}} {{item:post_title}}" msgstr "Buchungscodes für {{codes:formatDateRange}} {{item:post_title}}" -#: includes/OptionsArray.php:197 +#: includes/OptionsArray.php:229 msgid "Body for booking codes email" msgstr "Nachricht für Buchungscodes E-Mail" -#: includes/OptionsArray.php:200 +#: includes/OptionsArray.php:233 msgid "" "\n" "

    Booking codes for {{item:post_title}} : {{codes:formatDateRange}}

    \n" @@ -3412,415 +3408,415 @@ msgstr "" "

    Danke, das Team.

    \n" " " -#: includes/OptionsArray.php:211 +#: includes/OptionsArray.php:248 msgid "Backup E-Mail for booking codes email" msgstr "Backup E-Mail für Buchungscodes E-Mail" -#: includes/OptionsArray.php:212 +#: includes/OptionsArray.php:249 msgid "Email address that receives a bcc copy of booking codes mailing (not used if empty)" msgstr "E-Mail-Adresse, die eine BCC-Kopie der Buchungscodes erhält (zum Deaktivieren Feld leer lassen)" -#: includes/OptionsArray.php:217 +#: includes/OptionsArray.php:254 msgid "Attach iCalendar file to booking codes email" msgstr "iCalendar-Datei an eine E-Mail mit Buchungscodes anhängen" -#: includes/OptionsArray.php:219 +#: includes/OptionsArray.php:256 msgid "Will attach an iCalendar compatible file with booking codes per day to import in their respective calendar application." msgstr "Fügt eine iCalendar-kompatible Datei mit Buchungscodes für die einzelnen Tage bei, um sie in die jeweilige Kalenderanwendung zu importieren." -#: src/Messages/BookingCodesMessage.php:50 +#: src/Messages/BookingCodesMessage.php:51 msgid "Unable to send Emails. No location email(s) configured, check location" msgstr "Emails können nicht gesendet werden. Keine Standort-E-Mail(s) konfiguriert, bitte Standort prüfen" -#: src/Messages/BookingCodesMessage.php:53 +#: src/Messages/BookingCodesMessage.php:57 msgid "Could not find booking codes for this timeframe/period" msgstr "Es konnten keine Buchungscodes für diesen Zeitrahmen/Zeitraum gefunden werden" -#: src/Messages/BookingCodesMessage.php:187 +#: src/Messages/BookingCodesMessage.php:208 msgid "booking code for item \"%1$s\": %2$s" msgstr "Buchungscodes für Artikel \"%1$s\": %2$s" -#: src/Service/BookingCodes.php:42 +#: src/Service/BookingCodes.php:45 msgid "Error sending booking codes by E-mail for Timeframe " msgstr "Fehler beim Senden von Buchungscodes per E-Mail für Zeitrahmen " -#: src/View/BookingCodes.php:175 -#: src/View/BookingCodes.php:276 +#: src/View/BookingCodes.php:178 +#: src/View/BookingCodes.php:287 msgid "No location configured for this timeframe" msgstr "Kein Standort für diesen Zeitraum konfiguriert" -#: src/View/BookingCodes.php:177 +#: src/View/BookingCodes.php:181 msgid "Unable to send emails. No location email configured, check location" msgstr "E-Mails konnten nicht gesendet werden. Keine Standort-E-Mail konfiguriert, bitte Standort prüfen" -#: src/View/BookingCodes.php:180 -#: src/View/BookingCodes.php:283 -#: src/View/BookingCodes.php:361 -#: src/View/BookingCodes.php:388 +#: src/View/BookingCodes.php:185 +#: src/View/BookingCodes.php:294 +#: src/View/BookingCodes.php:394 +#: src/View/BookingCodes.php:424 msgid "This timeframe has no booking codes. To generate booking codes you need to save the timeframe." msgstr "Dieser Zeitrahmen hat keine Buchungscodes. Um Buchungscodes zu generieren, muss der Zeitrahmen gespeichert werden." -#: src/View/BookingCodes.php:270 +#: src/View/BookingCodes.php:281 msgid "Send booking codes by email" msgstr "Buchungscodes per E-Mail versenden" -#: src/View/BookingCodes.php:279 +#: src/View/BookingCodes.php:290 msgid "Unable to send Emails. No location email configured, check location" msgstr "Emails konnten nicht gesendet werden. Keine Standort-E-Mail konfiguriert, bitte Standort prüfen" -#: src/View/BookingCodes.php:291 +#: src/View/BookingCodes.php:307 msgid "Email booking codes for the entire timeframe" msgstr "E-Mail mit Buchungscodes für den gesamten Zeitraum senden" -#: src/View/BookingCodes.php:294 +#: src/View/BookingCodes.php:310 msgid "All codes for the entire timeframe will be emailed to the location email(s), given in bold below." msgstr "Alle Codes für den gesamten Zeitraum werden an die unten fett gedruckte(n) E-Mail-Adresse(n) des Standorts geschickt." -#: src/View/BookingCodes.php:303 +#: src/View/BookingCodes.php:328 msgid "Email booking codes of current month" msgstr "E-Mail mit Buchungscodes für den aktuellen Monat senden" -#: src/View/BookingCodes.php:305 +#: src/View/BookingCodes.php:330 msgid "The codes of the current month will be sent to all the location email(s), given in bold below" msgstr "Die Codes des laufenden Monats werden an alle fettgedruckten E-Mail-Adressen der Standorte gesendet" -#: src/View/BookingCodes.php:314 +#: src/View/BookingCodes.php:348 msgid "Email booking codes of next month" msgstr "E-Mail mit Buchungscodes für den nächsten Monat senden" -#: src/View/BookingCodes.php:316 +#: src/View/BookingCodes.php:350 msgid "The codes of the next month will be sent to all the location email(s), given in bold below." msgstr "Die Codes des nächsten Monats werden an alle fettgedruckten E-Mail-Adressen der Standorte gesendet." -#: src/View/BookingCodes.php:318 +#: src/View/BookingCodes.php:352 msgid "Currently configured location email(s): " msgstr "Derzeit konfigurierte Standort-E-Mail(s): " -#: src/View/BookingCodes.php:327 +#: src/View/BookingCodes.php:360 msgid "Last booking codes email sent:" msgstr "Letzte Buchungscodes wurden per E-Mail verschickt am:" -#: src/View/BookingCodes.php:354 +#: src/View/BookingCodes.php:387 msgid "Download booking codes" msgstr "Buchungscodes herunterladen" -#: src/View/BookingCodes.php:359 +#: src/View/BookingCodes.php:392 msgid "Will download all available booking codes for this timeframe. If the timeframe has no end-date, the booking codes for the next %s days will be retrieved." msgstr "Lädt alle verfügbaren Buchungscodes für diesen Zeitrahmen herunter. Wenn der Zeitrahmen kein Enddatum hat, werden die Buchungscodes für die nächsten %s Tage abgerufen." -#: src/View/BookingCodes.php:382 +#: src/View/BookingCodes.php:419 msgid "Only showing booking codes for the next %s days." msgstr "Zeige nur Buchungscodes für die nächsten %s Tage." -#: src/View/BookingCodes.php:384 +#: src/View/BookingCodes.php:421 msgid "The amount of booking codes shown in the overview can be changed in the settings." msgstr "Die Anzahl der in der Übersicht angezeigten Buchungscodes kann in den Einstellungen geändert werden." -#: src/View/BookingCodes.php:473 +#: src/View/BookingCodes.php:510 msgid "Unable to retrieve booking codes" msgstr "Buchungscodes konnten nicht abgerufen werden" -#: src/View/BookingCodes.php:474 +#: src/View/BookingCodes.php:511 msgid "Missing ID of timeframe post" msgstr "Fehlende ID des Zeitrahmens" -#: src/View/BookingCodes.php:496 +#: src/View/BookingCodes.php:537 msgid "Error sending booking codes" msgstr "Fehler beim Senden von Buchungscodes" -#: src/View/BookingCodes.php:515 +#: src/View/BookingCodes.php:555 msgid "An unknown error occured" msgstr "Ein unbekannter Fehler ist aufgetreten" -#: src/View/BookingCodes.php:516 +#: src/View/BookingCodes.php:556 msgid "Email booking codes" msgstr "Buchungscodes per E-Mail versenden" -#: src/Wordpress/CustomPostType/Timeframe.php:764 +#: src/Wordpress/CustomPostType/Timeframe.php:786 msgid "Send booking codes automated by email" msgstr "Buchungscodes automatisch per E-Mail versenden" -#: src/Wordpress/CustomPostType/Timeframe.php:765 +#: src/Wordpress/CustomPostType/Timeframe.php:787 msgid "Enable automated sending of booking codes by email" msgstr "Automatisches Versenden von Buchungscodes per E-Mail aktivieren" -#: src/Wordpress/CustomPostType/Timeframe.php:767 +#: src/Wordpress/CustomPostType/Timeframe.php:789 msgid "First day to send Codes (List starts at next month)
    (Same day will be used for subsequent messages) " msgstr "Starttag für das regelmäßige Versenden von Codes (Liste startet im nächsten Monat)
    (Der gleiche Tag wird für die folgenden Nachrichten genutzt werden) " -#: src/Wordpress/CustomPostType/Timeframe.php:770 +#: src/Wordpress/CustomPostType/Timeframe.php:792 msgid "Months to send" msgstr "Anzahl an Monaten" -#: src/Wordpress/CustomPostType/Timeframe.php:771 +#: src/Wordpress/CustomPostType/Timeframe.php:793 msgid "Send booking codes for this amount of month's in one email" msgstr "Buchungscodes für diese Anzahl von Monaten in einer E-Mail versenden" -#: src/Wordpress/CustomPostType/Timeframe.php:773 +#: src/Wordpress/CustomPostType/Timeframe.php:795 msgid "Next email planned for: " msgstr "Nächste E-Mail geplant am: " -#: src/Wordpress/CustomPostType/Timeframe.php:774 +#: src/Wordpress/CustomPostType/Timeframe.php:796 msgid "(not planned)" msgstr "(nichts geplant)" -#: includes/OptionsArray.php:1383 -#: src/Service/Cache.php:370 +#: includes/OptionsArray.php:1537 +#: src/Service/Cache.php:368 msgid "Clear Cache" msgstr "Cache leeren" -#: src/Service/Cache.php:365 +#: src/Service/Cache.php:363 msgid "Clear all cache items" msgstr "Alle Cache-Elemente löschen" -#: src/Wordpress/Options/OptionsTab.php:167 +#: src/Wordpress/Options/OptionsTab.php:166 msgid "Cache cleared." msgstr "Cache geleert." -#: src/Wordpress/CustomPostType/Timeframe.php:502 +#: src/Wordpress/CustomPostType/Timeframe.php:511 msgid "Location Category Selection" msgstr "Standortkategorie auswählen" -#: src/Wordpress/CustomPostType/Timeframe.php:510 +#: src/Wordpress/CustomPostType/Timeframe.php:519 msgid "Location Selection" msgstr "Standort auswählen" -#: src/Wordpress/CustomPostType/Timeframe.php:518 +#: src/Wordpress/CustomPostType/Timeframe.php:527 msgid "Select one or more locations" msgstr "Wähle einen oder mehrere Standorte aus" -#: src/Wordpress/CustomPostType/Timeframe.php:525 +#: src/Wordpress/CustomPostType/Timeframe.php:534 msgid "Item Selection" msgstr "Artikel auswählen" -#: src/Wordpress/CustomPostType/Timeframe.php:533 +#: src/Wordpress/CustomPostType/Timeframe.php:542 msgid "Select one or more items" msgstr "Wähle einen oder mehrere Artikel aus" -#: src/Wordpress/CustomPostType/Timeframe.php:540 +#: src/Wordpress/CustomPostType/Timeframe.php:549 msgid "Item Category Selection" msgstr "Artikelkategorie auswählen" -#: src/Wordpress/CustomPostType/Timeframe.php:548 +#: src/Wordpress/CustomPostType/Timeframe.php:557 msgid "Item selection" msgstr "Artikel auswählen" -#: src/Wordpress/CustomPostType/Timeframe.php:820 +#: src/Wordpress/CustomPostType/Timeframe.php:843 msgid "Manual selection" msgstr "Manuelle Auswahl" -#: src/Wordpress/CustomPostType/Timeframe.php:821 +#: src/Wordpress/CustomPostType/Timeframe.php:844 msgid "Select by category" msgstr "Kategorie auswählen" -#: src/Service/Holiday.php:42 +#: src/Service/Holiday.php:50 msgctxt "territory" msgid "State" msgstr "Bundesland" -#: includes/OptionsArray.php:691 +#: includes/OptionsArray.php:770 msgid "Restrict bookings by booking rules" msgstr "Buchungen durch Buchungsregeln beschränken" -#: includes/OptionsArray.php:696 +#: includes/OptionsArray.php:775 msgid "Count cancelled bookings towards quota" msgstr "Stornierte Buchungen mitzählen" -#: includes/OptionsArray.php:697 +#: includes/OptionsArray.php:776 msgid "Check if bookings that have been cancelled in the booking period shall be counted towards the amount of booked days for the user. More info in the documentation" msgstr "Prüft, ob die Buchungen die während der Buchungsperiode storniert wurden zu den maximal buchbaren Tagen eines Nutzenden angerechnet werden sollen. Mehr Infos dazu in der Dokumentation." -#: includes/OptionsArray.php:706 +#: includes/OptionsArray.php:785 msgid "Rule " msgstr "Regel " -#: includes/OptionsArray.php:707 +#: includes/OptionsArray.php:786 msgid "Add another rule" msgstr "Weitere Regel hinzufügen" -#: includes/OptionsArray.php:708 +#: includes/OptionsArray.php:787 msgid "Remove rule" msgstr "Regel entfernen" -#: includes/OptionsArray.php:712 +#: includes/OptionsArray.php:791 msgid "Rule type" msgstr "Regeltyp" -#: includes/OptionsArray.php:713 +#: includes/OptionsArray.php:792 msgid "Select the kind of rule" msgstr "Regel auswählen" -#: includes/OptionsArray.php:723 +#: includes/OptionsArray.php:802 msgid "Rule description" msgstr "Regelbeschreibung" -#: includes/OptionsArray.php:741 +#: includes/OptionsArray.php:820 msgid "Select an option" msgstr "Wähle eine Option" -#: includes/OptionsArray.php:747 +#: includes/OptionsArray.php:826 msgid "Applies to all" msgstr "Auf alle anwenden" -#: includes/OptionsArray.php:748 +#: includes/OptionsArray.php:827 msgid "Check if this rule applies to all items" msgstr "Wähle, ob diese Regel für alle Artikel gelten soll" -#: includes/OptionsArray.php:753 +#: includes/OptionsArray.php:832 msgid "Applies to categories" msgstr "Auf Kategorien anwenden" -#: includes/OptionsArray.php:754 +#: includes/OptionsArray.php:833 msgid "Check the categories that these rules apply to" msgstr "Wähle die Kategorien für die diese Regel gelten soll" -#: includes/OptionsArray.php:764 +#: includes/OptionsArray.php:844 msgid "Groups exempt from rule" msgstr "Befreite Nutzergruppen" -#: includes/OptionsArray.php:765 +#: includes/OptionsArray.php:845 msgid "Here you can define if the rule should not apply to a specific user group. Will apply to all groups if left empty (Administrators and item / location admins are always excluded)." msgstr "Hier kannst du festlegen, ob diese Regel NICHT für eine bestimmte Nutzendengruppe gelten soll. Die Regel gilt für alle Gruppen, wenn dieses Feld leer gelassen wird (Administratoren und Artikel/Standort Admins sind immer von der Regel ausgenommen)" -#: src/Service/BookingRule.php:212 +#: src/Service/BookingRule.php:226 msgid "Forbid simultaneous Bookings" msgstr "Gleichzeitige Buchungen unterbinden" -#: src/Service/BookingRule.php:213 +#: src/Service/BookingRule.php:227 msgid "Users can no longer book two items on the same day." msgstr "Nutzende können nicht mehr als einen Artikel am gleichen Tag buchen." -#: src/Service/BookingRule.php:214 +#: src/Service/BookingRule.php:228 msgid "You can not book more than one item at a time." msgstr "Du kannst nicht mehr als einen Artikel gleichzeitig buchen." -#: src/Service/BookingRule.php:219 +#: src/Service/BookingRule.php:233 msgid "Prohibit chain-bookings" msgstr "Kettenbuchungen verhindern" -#: src/Service/BookingRule.php:220 +#: src/Service/BookingRule.php:234 msgid "Users can no longer work around the maximum booking limit by chaining two bookings directly after one another." msgstr "Nutzende können nicht mehr das maximale Buchungslimit umgehen indem sie zwei Buchungen direkt aneinanderhängen." -#: src/Service/BookingRule.php:221 -#: src/Service/BookingRule.php:228 -#: src/Service/BookingRule.php:246 -#: src/Service/BookingRule.php:283 -#: src/Service/BookingRule.php:301 +#: src/Service/BookingRule.php:235 +#: src/Service/BookingRule.php:242 +#: src/Service/BookingRule.php:260 +#: src/Service/BookingRule.php:297 +#: src/Service/BookingRule.php:315 msgid "You have reached your booking limit. Please leave some time in between bookings." msgstr "Du hast dein maximales Buchungslimit erreicht. Bitte lasse etwas Zeit zwischen deinen Buchungen." -#: src/Service/BookingRule.php:226 -#: src/Service/BookingRule.php:232 +#: src/Service/BookingRule.php:240 +#: src/Service/BookingRule.php:246 msgid "Maximum booked days per week" msgstr "Maximal buchbare Tage pro Woche" -#: src/Service/BookingRule.php:227 +#: src/Service/BookingRule.php:241 msgid "Users are only allowed to book a limited amount of days per week." msgstr "Nutzende können nur eine begrenzte Anzahl an Tagen pro Woche buchen." -#: src/Service/BookingRule.php:233 +#: src/Service/BookingRule.php:247 msgid "Number of days each user is allowed to book per week" msgstr "Anzahl der Tage, die jeder Nutzende pro Woche buchen darf" -#: src/Service/BookingRule.php:237 -#: src/Service/BookingRule.php:292 +#: src/Service/BookingRule.php:251 +#: src/Service/BookingRule.php:306 msgid "At what day of the week should the counter be reset?" msgstr "An welchem Wochentag soll der Zähler zurückgesetzt werden?" -#: src/Service/BookingRule.php:244 -#: src/Service/BookingRule.php:250 +#: src/Service/BookingRule.php:258 +#: src/Service/BookingRule.php:264 msgid "Maximum booked days per month" msgstr "Maximal buchbare Tage pro Monat" -#: src/Service/BookingRule.php:245 +#: src/Service/BookingRule.php:259 msgid "Users are only allowed to book a limited amount of days per month." msgstr "Nutzende können nur eine begrenzte Anzahl an Tagen pro Monat buchen." -#: src/Service/BookingRule.php:251 +#: src/Service/BookingRule.php:265 msgid "Number of days each user is allowed to book per month" msgstr "Anzahl der Tage, die jeder Nutzende pro Monat buchen darf" -#: src/Service/BookingRule.php:255 -#: src/Service/BookingRule.php:310 +#: src/Service/BookingRule.php:269 +#: src/Service/BookingRule.php:324 msgid "At what day of the month should the counter be reset?" msgstr "An welchem Tag im Monat soll der Zähler zurückgesetzt werden?" -#: src/Service/BookingRule.php:262 +#: src/Service/BookingRule.php:276 msgid "Maximum of bookable days in time period" msgstr "Maximal buchbare Tage im Zeitraum" -#: src/Service/BookingRule.php:263 +#: src/Service/BookingRule.php:277 msgid "Allow x booked days over the period of y days for user." msgstr "Nutzende können x Tage über einen Zeitraum von y Tagen buchen." -#: src/Service/BookingRule.php:264 +#: src/Service/BookingRule.php:278 msgid "Booking limit exceeded. " msgstr "Buchungslimit erschöpft. " -#: src/Service/BookingRule.php:268 +#: src/Service/BookingRule.php:282 msgid "Allow x booked days" msgstr "Erlaube X buchbare Tage" -#: src/Service/BookingRule.php:269 +#: src/Service/BookingRule.php:283 msgid "How many days are free to book in the given period of days" msgstr "Wie viele Tage während der angegebenen Buchungsperiode gebucht werden können" -#: src/Service/BookingRule.php:272 +#: src/Service/BookingRule.php:286 msgid "In the period of y days" msgstr "Über den Zeitraum von Y Tagen" -#: src/Service/BookingRule.php:273 +#: src/Service/BookingRule.php:287 msgid "The length of the period for which the booking is limited. This period always lies in the middle, so if you define 30 days, the 15 days before and after will count towards the maximum quota." msgstr "Die Länger der Periode in denen die Buchungen eingeschränkt werden. Die Periode liegt immer in der Mitte, wenn du also 30 Tage definierst werden 15 Tage davor und 15 Tage danach in die Buchungsperiode mit eingerechnet." -#: src/Service/BookingRule.php:281 -#: src/Service/BookingRule.php:287 +#: src/Service/BookingRule.php:295 +#: src/Service/BookingRule.php:301 msgid "Maximum number of bookings per week" msgstr "Maximale Anzahl an Buchungen pro Woche" -#: src/Service/BookingRule.php:282 +#: src/Service/BookingRule.php:296 msgid "Users are only allowed to make that many bookings per week (Irrespective of their length)." msgstr "Nutzende dürfen nur so viele Buchungen pro Woche tätigen (die Länge der Buchungen ist hierbei egal)" -#: src/Service/BookingRule.php:288 +#: src/Service/BookingRule.php:302 msgid "Number of bookings each user is allowed to make per week" msgstr "Anzahl der Buchungen die jeder Nutzende pro Woche tätigen darf" -#: src/Service/BookingRule.php:299 -#: src/Service/BookingRule.php:305 +#: src/Service/BookingRule.php:313 +#: src/Service/BookingRule.php:319 msgid "Maximum number of bookings per month" msgstr "Maximale Anzahl an Buchungen pro Monat" -#: src/Service/BookingRule.php:300 +#: src/Service/BookingRule.php:314 msgid "Users are only allowed to make that many bookings per month (Irrespective of their length)." msgstr "Nutzende dürfen nur so viele Buchungen pro Monat tätigen (die Länge der Buchungen ist hierbei egal)" -#: src/Service/BookingRule.php:306 +#: src/Service/BookingRule.php:320 msgid "Number of bookings each user is allowed to make per month" msgstr "Anzahl der Buchungen die jeder Nutzende pro Monat tätigen darf" -#: src/Service/BookingRule.php:433 +#: src/Service/BookingRule.php:455 msgid "You can only book %1$s days out of %2$s days. Please wait a while in-between bookings." msgstr "Du kannst maximal %1$s Tage alle %2$s Tage buchen. Bitte lass etwas Zeit zwischen deinen Buchungen." -#: src/Service/BookingRule.php:466 +#: src/Service/BookingRule.php:487 msgid "You can only book %1$s days per week, please try again after %2$s next week." msgstr "Du kannst maximal %1$s Tage pro Woche buchen. Bitte versuche es nochmal nach %2$s nächste Woche." -#: src/Service/BookingRule.php:484 +#: src/Service/BookingRule.php:505 msgid "You are only allowed to have %1$s booking(s) per week, please try again after %2$s next week." msgstr "Du kannst maximal %1$s Buchungen pro Woche tätigen. Bitte versuche es nochmal nach %2$s nächste Woche." -#: src/Service/BookingRule.php:515 +#: src/Service/BookingRule.php:534 msgid "You can only book %1$s days per month, please try again after the %2$s. next month." msgstr "Du kannst maximal %1$s Tage pro Monat buchen. Bitte versuche es nochmal nach dem %2$s. nächsten Monats." -#: src/Service/BookingRule.php:530 +#: src/Service/BookingRule.php:549 msgid "You are only allowed %1$s booking(s) per month, please try again after the %2$s. next month." msgstr "Du kannst maximal %1$s Buchungen pro Monat tätigen. Bitte versuche es nochmal nach dem %2$s. nächsten Monats." -#: src/Service/BookingRuleApplied.php:59 +#: src/Service/BookingRuleApplied.php:60 msgid "You need to specify a category, if the rule does not apply to all items" msgstr "Du musst eine Kategorie festlegen, wenn diese Regel nicht für alle Artikel gilt" @@ -3836,32 +3832,32 @@ msgstr "Buchungsregeln: Parameter müssen eine Zahl sein." msgid "Booking rules: Select parameter has not been properly set." msgstr "Buchungsregeln: Auswahl-Parameter wurde nicht richtig gesetzt." -#: src/Service/BookingRuleApplied.php:169 +#: src/Service/BookingRuleApplied.php:167 msgid "This affects the following bookings:" msgstr "Das betrifft folgende Buchungen:" -#: src/Service/BookingRuleApplied.php:240 +#: src/Service/BookingRuleApplied.php:239 msgid "Booking rules: No rule type specified." msgstr "Buchungsregeln: Kein Regeltyp festgelegt." -#: templates/booking-single.php:144 +#: templates/booking-single.php:146 msgid "Your data" msgstr "Deine Daten" -#: includes/OptionsArray.php:923 +#: includes/OptionsArray.php:1025 msgid "Reminder for locations before booking starts" msgstr "Erinnerung für Standorte vor Buchungsbeginn" -#: includes/OptionsArray.php:925 +#: includes/OptionsArray.php:1028 msgid "You can set here whether locations should receive a reminder email before the start of a booking.
    More Information in the documentation" msgstr "Hier kannst du einstellen, ob Standorte vor Beginn einer Buchung eine Erinnerungsmail erhalten sollen.
    Weitere Informationen in der Dokumentation" -#: includes/OptionsArray.php:934 -#: includes/OptionsArray.php:1003 +#: includes/OptionsArray.php:1039 +#: includes/OptionsArray.php:1122 msgid "The reminders need to be enabled for all locations individually. This is only the main on/off switch." msgstr "Die Erinnerungsfunktion muss für alle Standorte einzeln aktiviert werden. Dies ist nur der Hauptschalter zum Ein- und Ausschalten." -#: includes/OptionsArray.php:947 +#: includes/OptionsArray.php:1053 msgid "" "

    Hi,

    \n" "

    The booking period for the item {{item:post_title}} at {{location:post_title}} will start soon.
    \n" @@ -3877,38 +3873,38 @@ msgstr "" "\n" "{{booking:getEmailSignature}}" -#: includes/OptionsArray.php:973 -#: includes/OptionsArray.php:1044 +#: includes/OptionsArray.php:1086 +#: includes/OptionsArray.php:1171 msgid "Bookings of" msgstr "Buchungen von" -#: includes/OptionsArray.php:975 +#: includes/OptionsArray.php:1089 msgid "Define for which booking start day the notifications should be sent" msgstr "Definiert an welchem Tag nach vor Buchungsbeginn die Benachrichtigungen gesendet werden sollen" -#: includes/OptionsArray.php:982 -#: includes/OptionsArray.php:1053 +#: includes/OptionsArray.php:1098 +#: includes/OptionsArray.php:1183 msgid "current day" msgstr "Gleicher Tag" -#: includes/OptionsArray.php:983 -#: includes/OptionsArray.php:1054 +#: includes/OptionsArray.php:1099 +#: includes/OptionsArray.php:1184 msgid "next day" msgstr "Nächstem Tag" -#: includes/OptionsArray.php:992 +#: includes/OptionsArray.php:1108 msgid "Reminder for locations before booking ends" msgstr "Erinnerung für Standorte vor Buchungsende" -#: includes/OptionsArray.php:994 +#: includes/OptionsArray.php:1111 msgid "You can set here whether locations should receive a reminder email before the end of a booking.
    More Information in the documentation" msgstr "Hier kannst du einstellen, ob Standorte vor dem Ende einer Buchung eine Erinnerungs-E-Mail erhalten sollen.
    Mehr Informationen in der Dokumentation" -#: includes/OptionsArray.php:1010 +#: includes/OptionsArray.php:1129 msgid "Booking of {{item:post_title}} {{booking:formattedBookingDate}}" msgstr "Buchung von {{item:post_title}} {{booking:formattedBookingDate}}" -#: includes/OptionsArray.php:1016 +#: includes/OptionsArray.php:1136 msgid "" "

    Hi,

    \n" "

    The booking period for the item {{item:post_title}} at {{location:post_title}} will end soon.
    \n" @@ -3926,35 +3922,35 @@ msgstr "" "\n" "{{booking:getEmailSignature}}" -#: includes/OptionsArray.php:1046 +#: includes/OptionsArray.php:1174 msgid "Define for which booking end day the notifications should be sent" msgstr "Definiert an welchem Tag nach Buchungsendes die Benachrichtigungen gesendet werden sollen" -#: src/Wordpress/CustomPostType/Location.php:403 +#: src/Wordpress/CustomPostType/Location.php:446 msgid "Receive booking start reminder" msgstr "Erinnerungsmail zum Buchungsstart erhalten" -#: src/Wordpress/CustomPostType/Location.php:404 +#: src/Wordpress/CustomPostType/Location.php:447 msgid "If selected, this location receives reminder emails of bookings starting soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings." msgstr "Wenn diese Option ausgewählt ist, erhält dieser Standort Erinnerungs-E-Mails über startende Buchungen. Die Benachrichtigungen werden an alle in der E-Mail-Liste des Standorts angegebenen Adressen gesendet (zuerst als Empfänger, alle folgenden als BCC). Diese Art der Erinnerung muss in den CommonsBooking Einstellungen aktiviert werden." -#: src/Wordpress/CustomPostType/Location.php:410 +#: src/Wordpress/CustomPostType/Location.php:455 msgid "Receive booking end reminder" msgstr "Erinnerungsmail zum Buchungsende erhalten" -#: src/Wordpress/CustomPostType/Location.php:411 +#: src/Wordpress/CustomPostType/Location.php:456 msgid "If selected, this location receives reminder emails of bookings ending soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings." msgstr "Wenn diese Option ausgewählt ist, erhält dieser Standort Erinnerungs-E-Mails über bald endende Buchungen. Die Benachrichtigungen werden an alle in der E-Mail-Liste des Standorts angegebenen Adressen gesendet (zuerst als Empfänger, alle folgenden als BCC). Diese Art der Erinnerung muss in den CommonsBooking Einstellungen aktiviert werden." -#: src/Wordpress/CustomPostType/Location.php:328 +#: src/Wordpress/CustomPostType/Location.php:351 msgid "Email addresses of the owner of the station. Can be reminded about bookings / cancellations and will receive the booking codes (when configured in the timeframe). You can enter multiple addresses separated by commas." msgstr "E-Mail-Adressen des Eigentümers der Station. Kann an Buchungen / Stornierungen erinnert werden und erhält die Buchungscodes (wenn im Zeitrahmen konfiguriert). Du kannst mehrere Adressen durch Kommas getrennt eingeben." -#: src/Wordpress/CustomPostType/Location.php:341 +#: src/Wordpress/CustomPostType/Location.php:368 msgid "Send copy of bookings / cancellations to location email" msgstr "Kopie der Buchungen/Stornierungen per E-Mail an den Standort senden" -#: src/Wordpress/CustomPostType/Location.php:342 +#: src/Wordpress/CustomPostType/Location.php:369 msgid "If enabled, the location email will receive a copy of all booking and cancellation notifications." msgstr "Wenn die Option aktiviert ist, erhält der Standort eine Blindkopie aller Buchungs- und Stornierungsbenachrichtigungen." @@ -3971,19 +3967,19 @@ msgstr "Bitte melde dich an , um deine Buchungen zu sehe msgid "A WordPress plugin for the management and booking of common goods." msgstr "Ein WordPress-Plugin für die Verwaltung und Buchung von Gemeingütern." -#: src/Wordpress/CustomPostType/Booking.php:269 +#: src/Wordpress/CustomPostType/Booking.php:271 msgid "Your reservation has expired, please try to book again" msgstr "Deine Reservierung ist abgelaufen, bitte versuche erneut zu buchen" -#: includes/OptionsArray.php:1071 +#: includes/OptionsArray.php:1201 msgid "Finish upgrade to latest version" msgstr "Upgrade auf aktuelle Version beenden" -#: includes/OptionsArray.php:1073 +#: includes/OptionsArray.php:1203 msgid "Click here to finish the upgrade to the latest version.
    This needs to be done after updating the plugin to a new version.
    If you do not do this, the plugin may not work correctly." msgstr "Hier klicken, um das Upgrade auf die neueste Version fertig zu stellen.
    Dies ist erforderlich, nachdem das Plug-in auf eine neue Version aktualisiert wurde.
    Ansonsten kann es sein, dass das Plugin nicht richtig funktioniert." -#: includes/OptionsArray.php:1076 +#: includes/OptionsArray.php:1206 msgid "Finish upgrade" msgstr "Upgrade fertigstellen" @@ -3995,51 +3991,47 @@ msgstr "Es gibt einige Aufgaben, die ausgeführt werden müssen, um den Aktualis msgid "Click here to run the upgrade tasks." msgstr "Hier klicken, um die Upgrade-Aufgaben auszuführen." -#: src/View/Migration.php:120 +#: src/View/Migration.php:127 msgid "upgrade in process .. please wait ..." msgstr "Upgrade wird durchgeführt ... bitte warten ..." -#: src/View/Migration.php:125 +#: src/View/Migration.php:132 msgid "Upgrade finished" msgstr "Upgrade beendet" -#: src/View/Migration.php:129 +#: src/View/Migration.php:136 msgid "Start Upgrade" msgstr "Upgrade starten" -#: src/Service/TimeframeExport.php:89 +#: src/Service/TimeframeExport.php:88 msgid "Invalid start date" msgstr "Ungültiges Startdatum" -#: src/Service/TimeframeExport.php:93 +#: src/Service/TimeframeExport.php:92 msgid "Invalid end date" msgstr "Ungültiges Enddatum" -#: src/Service/TimeframeExport.php:96 +#: src/Service/TimeframeExport.php:95 msgid "Start date must not be after the end date." msgstr "Das Startdatum darf nicht nach dem Enddatum liegen." -#: src/Service/TimeframeExport.php:164 +#: src/Service/TimeframeExport.php:168 #: src/View/TimeframeExport.php:39 msgid "Export finished" msgstr "Export beendet" -#: src/Service/TimeframeExport.php:254 +#: src/Service/TimeframeExport.php:261 msgid "Export data is not complete. Please complete the process before trying to export." msgstr "Exportdaten konnten nicht vollständig gesammelt werden. Bitte den Vorgang abschließen, bevor der Export versucht wird." -#: src/Service/TimeframeExport.php:258 +#: src/Service/TimeframeExport.php:265 msgid "No data was found for the selected time period" msgstr "Es wurden keine Daten für den gewählten Zeitraum gefunden" -#: src/Service/TimeframeExport.php:263 +#: src/Service/TimeframeExport.php:270 msgid "You need to set an export path to execute the export" msgstr "Es muss ein Exportpfad angegeben werden, um den Export ausführen zu können" -#: src/Service/TimeframeExport.php:364 -msgid "Processed %d of %d bookings" -msgstr "%d von %d Buchungen bearbeitet" - #: src/View/TimeframeExport.php:32 msgid "preparing export .. please wait ..." msgstr "Export wird vorbereitet .. bitte warten ..." @@ -4052,39 +4044,39 @@ msgstr "Export fehlgeschlagen" msgid "Booking is saved as draft." msgstr "Buchung wurde als Entwurf gespeichert." -#: src/Exception/TimeframeInvalidException.php:15 +#: src/Exception/TimeframeInvalidException.php:14 msgid "Timeframe is saved as draft." msgstr "Zeitrahmen wurde als Entwurf gespeichert." -#: src/Model/Booking.php:613 +#: src/Model/Booking.php:607 msgid "Item not found" msgstr "Artikel nicht gefunden" -#: src/Model/Booking.php:622 +#: src/Model/Booking.php:616 msgid "Location not found" msgstr "Standort nicht gefunden" -#: src/Model/Booking.php:627 +#: src/Model/Booking.php:621 msgid "There is no timeframe for this booking. Please create a timeframe first." msgstr "Es existiert kein Zeitrahmen für diese Buchung. Bitte zuerst einen Zeitrahmen erstellen." -#: src/Model/Booking.php:648 +#: src/Model/Booking.php:641 msgid "There are one ore more overlapping bookings within the chosen timerange" msgstr "Es gibt eine oder mehrere sich überlappende Buchungen innerhalb des gewählten Zeitraums" -#: src/Model/Booking.php:649 +#: src/Model/Booking.php:642 msgid "Please adjust the start- or end-date." msgstr "Bitte passe das Start- oder Enddatum an." -#: src/Model/Booking.php:650 +#: src/Model/Booking.php:643 msgid "Affected Bookings: %s" msgstr "Betroffene Buchungen: %s" -#: src/Model/Timeframe.php:556 +#: src/Model/Timeframe.php:552 msgid "Could not get item or location. Please set a valid item and location." msgstr "Artikel oder Standort konnte nicht gefunden werden. Bitte wähle einen gültigen Artikel oder Standort." -#: src/Model/Timeframe.php:563 +#: src/Model/Timeframe.php:561 msgid "Item or location is missing. Please set item and location." msgstr "Artikel oder Standort fehlen. Bitte Artikel und Standort festlegen." @@ -4092,20 +4084,20 @@ msgstr "Artikel oder Standort fehlen. Bitte Artikel und Standort festlegen." msgid "No dates selected. Please select at least one date." msgstr "Kein Datum ausgewählt. Bitte mindestens ein Datum auswählen." -#: src/Model/Timeframe.php:582 +#: src/Model/Timeframe.php:584 msgid "The same date was selected multiple times. Please select each date only once." msgstr "Das gleiche Datum wurde mehrere Male ausgewählt. Bitte ein Datum nur einmal auswählen." -#: src/Model/Timeframe.php:591 +#: src/Model/Timeframe.php:593 msgid "Startdate is missing. Please enter a start date to publish this timeframe." msgstr "Das Startdatum fehlt. Ein Startdatum muss eingegeben werden, damit der Zeitrahmen veröffentlicht werden kann." -#: src/View/Booking.php:538 -#: src/Wordpress/CustomPostType/Booking.php:854 +#: src/View/Booking.php:537 +#: src/Wordpress/CustomPostType/Booking.php:856 msgid "Submit booking" msgstr "Buchung abschicken" -#: src/Wordpress/CustomPostType/Booking.php:735 +#: src/Wordpress/CustomPostType/Booking.php:737 msgid "" "

    Notice

    In this view, you as an admin can create or modify existing bookings. Please use it with caution.
    \n" "\t\t\t\t

      \n" @@ -4125,19 +4117,19 @@ msgstr "" "

      \n" "\t\t\t\t" -#: src/Wordpress/CustomPostType/Booking.php:763 +#: src/Wordpress/CustomPostType/Booking.php:765 msgid "Book full day" msgstr "Ganztägig buchen" -#: src/Wordpress/CustomPostType/Booking.php:766 +#: src/Wordpress/CustomPostType/Booking.php:768 msgid "The booking should apply to the entire day(s)" msgstr "Die Buchung soll auf den gesamten Tag / die gesamten Tage angewendet werden" -#: src/Wordpress/CustomPostType/Booking.php:806 +#: src/Wordpress/CustomPostType/Booking.php:808 msgid "Valid booking code will be automatically retrieved for bookings that apply to the full day." msgstr "Ein gültiger Buchungscode wird automatisch für Buchungen, die sich auf den ganzen Tag beziehen, generiert." -#: src/Wordpress/CustomPostType/Booking.php:815 +#: src/Wordpress/CustomPostType/Booking.php:817 msgid "" "Here you must select the user for whom the booking is made.
      \n" " If the booking was made by a user via frontend booking process, the user will be shown in this field.\n" @@ -4147,12 +4139,12 @@ msgstr "" " Wenn die Buchung von einem/einer Nutzenden über den Frontend-Buchungsprozess vorgenommen wurde, wird der/die Nutzende in diesem Feld angezeigt.\n" "
      Hinweis: Der/die Nutzende erhält eine Buchungsbestätigung, sobald die Buchung abgeschickt wurde." -#: src/Wordpress/CustomPostType/Booking.php:855 +#: src/Wordpress/CustomPostType/Booking.php:857 msgid "This will create the specified booking and send out the booking confirmation email." msgstr "Dadurch wird die angegebene Buchung erstellt und die Buchungsbestätigung per E-Mail verschickt." -#: src/Plugin.php:329 -#: src/Plugin.php:330 +#: src/Plugin.php:331 +#: src/Plugin.php:332 msgid "Mass Operations" msgstr "Massenverarbeitung" @@ -4188,11 +4180,11 @@ msgstr "Standortname" msgid "New location name" msgstr "Name des neuen Standorts" -#: src/Wordpress/CustomPostType/Timeframe.php:932 +#: src/Wordpress/CustomPostType/Timeframe.php:955 msgid "Orphaned bookings found, can migrate. Click here to migrate " msgstr "Verwaiste Buchungen gefunden, können migriert werden. Hier klicken um zu migrieren " -#: templates/massoperations-index.php:7 +#: templates/massoperations-index.php:8 msgid "Migrate orphaned bookings" msgstr "Verwaiste Buchungen migrieren" @@ -4205,147 +4197,147 @@ msgstr "Neuer Standort für Buchung mit ID %s konnte nicht gefunden werden" msgid "Error while clearing the cache." msgstr "Fehler beim Leeren des Caches." -#: includes/OptionsArray.php:677 +#: includes/OptionsArray.php:756 msgid "Restriction settings" msgstr "Einstellungen für Einschränkungen" -#: includes/OptionsArray.php:679 +#: includes/OptionsArray.php:758 msgid "Settings for restrictions.
      More Information in the documentation" msgstr "Einstellungen für Einschränkungen.
      Mehr Informationen in der Dokumentation" -#: includes/OptionsArray.php:682 +#: includes/OptionsArray.php:761 msgid "Do not cancel bookings on total breakdown" msgstr "Buchungen bei Totalausfall nicht stornieren" -#: includes/OptionsArray.php:685 +#: includes/OptionsArray.php:764 msgid "If checked, bookings will not be cancelled if the item has broken down. The user will be notified and once the item becomes available again, the old bookings are still valid." msgstr "Wenn ausgewählt, werden Buchungen nicht storniert, wenn ein Totalausfall für den Artikel gesetzt ist. Der / die Benutzer*in wird benachrichtigt und sobald der Artikel wieder verfügbar ist, sind die alten Buchungen weiterhin gültig." -#: src/Plugin.php:476 +#: src/Plugin.php:479 msgid "Add custom title for filter" msgstr "Benutzerdefinierten Titel für Filtergruppe hinzufügen" -#: src/Plugin.php:479 +#: src/Plugin.php:482 msgid "Define name that should be used for the category if it is displayed in the map as a filter group. You can also use this to add custom HTML to the category name. When left empty, the defined name of the category will be used." msgstr "Legt den Namen fest, der für die Kategorie verwendet werden soll, wenn sie in der Karte als Teil der Filtergruppe angezeigt wird. Hier kann auch benutzerdefinierter HTML-Code zum Kategorienamen hinzugefügt werden. Bleibt der Eintrag leer, wird der Standard Name der Kategorie verwendet." -#: src/Wordpress/CustomPostType/Map.php:45 +#: src/Wordpress/CustomPostType/Map.php:44 msgid "Map settings" msgstr "Karteneinstellungen" -#: src/Wordpress/CustomPostType/Map.php:59 +#: src/Wordpress/CustomPostType/Map.php:57 msgid "These settings help you to configure the usage and appearance of Commons Booking Map" msgstr "Mit diesen Einstellungen kann die Handhabung und das Aussehen der Commons Booking Karte konfiguriert werden" -#: src/Wordpress/CustomPostType/Map.php:70 +#: src/Wordpress/CustomPostType/Map.php:68 msgid "Presentation" msgstr "Darstellung" -#: src/Wordpress/CustomPostType/Map.php:93 +#: src/Wordpress/CustomPostType/Map.php:91 msgid "show the current scale in the bottom left corner of the map" msgstr "den aktuellen Maßstab in der unteren linken Ecke der Karte anzeigen" -#: src/Wordpress/CustomPostType/Map.php:113 +#: src/Wordpress/CustomPostType/Map.php:111 msgid "No locations found" msgstr "Keine Standorte gefunden" -#: src/Wordpress/CustomPostType/Map.php:177 +#: src/Wordpress/CustomPostType/Map.php:175 msgid "Positioning" msgstr "Positionierung" -#: src/Wordpress/CustomPostType/Map.php:219 +#: src/Wordpress/CustomPostType/Map.php:217 msgid "Show marker tooltip permanently" msgstr "Marker-Tooltip dauerhaft anzeigen" -#: src/Wordpress/CustomPostType/Map.php:284 -#: src/Wordpress/CustomPostType/Map.php:361 -#: src/Wordpress/CustomPostType/Map.php:417 +#: src/Wordpress/CustomPostType/Map.php:282 +#: src/Wordpress/CustomPostType/Map.php:359 +#: src/Wordpress/CustomPostType/Map.php:415 msgid "icon width" msgstr "Icon-Breite" -#: src/Wordpress/CustomPostType/Map.php:295 -#: src/Wordpress/CustomPostType/Map.php:372 -#: src/Wordpress/CustomPostType/Map.php:428 +#: src/Wordpress/CustomPostType/Map.php:293 +#: src/Wordpress/CustomPostType/Map.php:370 +#: src/Wordpress/CustomPostType/Map.php:426 msgid "icon height" msgstr "Icon-Höhe" -#: src/Wordpress/CustomPostType/Map.php:483 +#: src/Wordpress/CustomPostType/Map.php:481 msgid "defines the bounds of the address search - set the longitude of the left bottom corner of the bounding box" msgstr "definiert die Grenzen der Adressensuche - legt den Längengrad der linken unteren Ecke des Begrenzungsrahmens fest" -#: src/Wordpress/CustomPostType/Map.php:489 +#: src/Wordpress/CustomPostType/Map.php:487 msgid "defines the bounds of the address search - set the bottom left corner of the bounding box" msgstr "definiert die Grenzen der Adressensuche - legt die linke untere Ecke des Begrenzungsrahmens fest" -#: src/Wordpress/CustomPostType/Map.php:495 +#: src/Wordpress/CustomPostType/Map.php:493 msgid "defines the bounds of the address search - set the longitude of the right top corner of the bounding box" msgstr "definiert die Grenzen der Adressensuche - legt den Längengrad der rechten oberen Ecke des Begrenzungsrahmens fest" -#: src/Wordpress/CustomPostType/Map.php:501 +#: src/Wordpress/CustomPostType/Map.php:499 msgid "defines the bounds of the address search - set the latitude of the right top corner of the bounding box" msgstr "definiert die Grenzen der Adressensuche - legt den Breitengrad der rechten oberen Ecke des Begrenzungsrahmens fest" -#: src/Wordpress/CustomPostType/Map.php:539 +#: src/Wordpress/CustomPostType/Map.php:537 msgid "Filter groups" msgstr "Filtergruppen" -#: src/Wordpress/CustomPostType/Map.php:540 +#: src/Wordpress/CustomPostType/Map.php:538 msgid "Filter groups can group item or location categories together to allow for filtering in the map." msgstr "Filtergruppen können Artikel- oder Standortkategorien gruppieren, um eine Filterung auf der Karte zu ermöglichen." -#: src/Wordpress/CustomPostType/Map.php:545 +#: src/Wordpress/CustomPostType/Map.php:543 msgid "Filter group {#}" msgstr "Filtergruppe {#}" -#: src/Wordpress/CustomPostType/Map.php:546 +#: src/Wordpress/CustomPostType/Map.php:544 msgid "Add another filter group" msgstr "Weitere Filtergruppe hinzufügen" -#: src/Wordpress/CustomPostType/Map.php:547 +#: src/Wordpress/CustomPostType/Map.php:545 msgid "Remove filter group" msgstr "Filtergruppe entfernen" -#: src/Wordpress/CustomPostType/Map.php:552 +#: src/Wordpress/CustomPostType/Map.php:550 msgid "Name" msgstr "Name" -#: src/Wordpress/CustomPostType/Map.php:555 +#: src/Wordpress/CustomPostType/Map.php:553 msgid "The name of the filter group" msgstr "Der Name der Filtergruppe" -#: src/Wordpress/CustomPostType/Map.php:562 +#: src/Wordpress/CustomPostType/Map.php:560 msgid "This is not available yet. Which data source should be used for the filter group. Taxonomy stands for the assigned categories, post-meta can be individually configured custom fields for item posts. When this item field contains data, it will be included. If it does not contain data or does not exist, the item will be excluded." msgstr "Das ist noch nicht verfügbar. Welche Datenquelle soll für die Filtergruppe verwendet werden. Taxonomie steht für die zugeordneten Kategorien, Post-Meta können individuell konfigurierte benutzerdefinierte Felder für Artikel-Posts sein. Wenn dieses Feld des Artikels Daten enthält, wird es einbezogen. Wenn es keine Daten enthält oder nicht vorhanden ist, wird der Artikel ausgeschlossen." -#: src/Wordpress/CustomPostType/Map.php:564 +#: src/Wordpress/CustomPostType/Map.php:562 msgid "Taxonomy" msgstr "Taxonomie" -#: src/Wordpress/CustomPostType/Map.php:565 +#: src/Wordpress/CustomPostType/Map.php:563 msgid "Post-meta" msgstr "Post-Meta" -#: src/Wordpress/CustomPostType/Map.php:574 +#: src/Wordpress/CustomPostType/Map.php:572 msgid "Exclusive selection" msgstr "Ausschließende Auswahl" -#: src/Wordpress/CustomPostType/Map.php:577 +#: src/Wordpress/CustomPostType/Map.php:575 msgid "WARNING: This feature is only available for the cb_search shortcode, not for cb_map. If checked, only one category can be selected in this filter group. If unchecked, multiple categories can be selected." msgstr "WARNUNG: Diese Funktion ist nur für den Shortcode cb_search verfügbar, nicht für cb_map. Wenn diese Funktion aktiviert ist, kann nur eine Kategorie in dieser Filtergruppe ausgewählt werden. Wenn sie nicht markiert ist, können mehrere Kategorien ausgewählt werden." -#: src/Wordpress/CustomPostType/Map.php:580 +#: src/Wordpress/CustomPostType/Map.php:578 msgid "Categories" msgstr "Kategorien" -#: src/Wordpress/CustomPostType/Map.php:583 +#: src/Wordpress/CustomPostType/Map.php:581 msgid "The categories to be included in the filter group" msgstr "Die Kategorien, die in die Filtergruppe aufgenommen werden sollen" -#: src/Wordpress/CustomPostType/Map.php:602 +#: src/Wordpress/CustomPostType/Map.php:600 msgid "select the categories that are used to prefilter the locations that are shown on the map - none for all locations" msgstr "wähle die Kategorie, nach der die auf der Karte angezeigten Standorte vorgefiltert werden sollen - leer lassen für alle Standorte" -#: src/Wordpress/CustomPostType/Map.php:680 +#: src/Wordpress/CustomPostType/Map.php:677 msgid "Copy to clipboard" msgstr "In Zwischenablage kopieren" @@ -4357,10 +4349,14 @@ msgstr "Beim Umziehen der Buchungen ist ein Fehler aufgetreten." msgid "There is already a booking on the new location during the timeframe of booking with ID %s." msgstr "Es existiert bereits eine Buchung für den Standort in dem Zeitraum der existierenden Buchung mit der ID %s." -#: src/Model/Booking.php:1024 +#: src/Model/Booking.php:1018 #~ msgid "Unconfirmed" #~ msgstr "Unbestätigt" -#: src/Model/Booking.php:1022 +#: src/Model/Booking.php:1016 #~ msgid "Confirmed" #~ msgstr "Bestätigt" + +#: src/Service/TimeframeExport.php:374 +msgid "Processed %1$d of %2$d bookings" +msgstr "" diff --git a/languages/commonsbooking.pot b/languages/commonsbooking.pot index 18adf4322..115568bba 100644 --- a/languages/commonsbooking.pot +++ b/languages/commonsbooking.pot @@ -9,7 +9,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"POT-Creation-Date: 2025-01-14T16:53:50+00:00\n" +"POT-Creation-Date: 2025-02-05T19:38:33+00:00\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "X-Generator: WP-CLI 2.11.0\n" "X-Domain: commonsbooking\n" @@ -39,17 +39,16 @@ msgstr "" msgid "https://wielebenwir.de/" msgstr "" -#: includes/OptionsArray.php:40 +#: includes/OptionsArray.php:39 msgid "Welcome" msgstr "" -#: includes/OptionsArray.php:46 +#: includes/OptionsArray.php:45 #: templates/dashboard-index.php:8 msgid "Welcome to CommonsBooking" msgstr "" -#. translators: %s = version number -#: includes/OptionsArray.php:50 +#: includes/OptionsArray.php:51 msgid "" "You are using CommonsBooking Version %s\n" "\n" @@ -63,127 +62,124 @@ msgid "" " The future of this plugin depends on your support. You can support us by make a donation on our website: wielebenwir" msgstr "" -#: includes/OptionsArray.php:70 +#: includes/OptionsArray.php:76 msgid "General" msgstr "" -#: includes/OptionsArray.php:75 +#: includes/OptionsArray.php:81 msgid "Naming and permalinks" msgstr "" -#: includes/OptionsArray.php:79 +#: includes/OptionsArray.php:86 msgid "Customize names & slugs. You can set an individual slug for items and locations to create individual permalinks.
      Notice: If the new settings do not work directly (you will get a 404 page error on frontend pages), you must click on the Settings -> Permalinks page after saving these settings to refresh the Wordpress permalink settings." msgstr "" -#: includes/OptionsArray.php:84 +#: includes/OptionsArray.php:93 msgid "Items slug" msgstr "" -#. translators: %s = example url (like website.com/cb-items/) -#: includes/OptionsArray.php:88 +#: includes/OptionsArray.php:99 msgid "The slug for article detail page. Type in the slug without slashes. Example: cb_item or article. The url for the items detail will be like %s" msgstr "" -#: includes/OptionsArray.php:95 +#: includes/OptionsArray.php:110 msgid "Locations slug" msgstr "" -#. translators: %s = example url (like website.com/cb-locations/) -#: includes/OptionsArray.php:99 +#: includes/OptionsArray.php:116 msgid "The slug for location detail page. Type in the slug without slashes. Example: cb_location or location. The url for the items detail will be like %s" msgstr "" -#: includes/OptionsArray.php:106 +#: includes/OptionsArray.php:127 msgid "Bookings Page" msgstr "" -#. translators: %s = example url (like website.com/cb-locations/) -#: includes/OptionsArray.php:110 +#: includes/OptionsArray.php:133 msgid "The page where you included the [cb_bookings] shortcode. This is used in the Users Widget" msgstr "" -#: includes/OptionsArray.php:119 -#: includes/OptionsArray.php:133 +#: includes/OptionsArray.php:146 +#: includes/OptionsArray.php:160 msgid "Booking comment" msgstr "" -#: includes/OptionsArray.php:123 +#: includes/OptionsArray.php:150 msgid "Activate booking comments in booking page" msgstr "" -#: includes/OptionsArray.php:125 +#: includes/OptionsArray.php:152 msgid "If enabled, users can enter an internal comment about their booking on the booking confirmation page. This comment can be included in the booking confirmation email." msgstr "" -#: includes/OptionsArray.php:129 +#: includes/OptionsArray.php:156 msgid "Headline above the comment field in frontend" msgstr "" -#: includes/OptionsArray.php:131 +#: includes/OptionsArray.php:158 msgid "Text that will be shown above the comment field in the booking confirmation page." msgstr "" -#: includes/OptionsArray.php:136 +#: includes/OptionsArray.php:163 msgid "Description" msgstr "" -#: includes/OptionsArray.php:138 +#: includes/OptionsArray.php:165 msgid "Short infotext to inform the user how the comment field will be used (e.g. only internal comment etc.) " msgstr "" -#: includes/OptionsArray.php:140 +#: includes/OptionsArray.php:167 msgid "Here you can leave a comment about your booking. This will be sent to the station." msgstr "" -#: includes/OptionsArray.php:145 +#: includes/OptionsArray.php:172 msgid "Global location settings" msgstr "" -#: includes/OptionsArray.php:146 +#: includes/OptionsArray.php:173 msgid "These settings are used for all locations. You can overwrite these settings for each location in the location settings." msgstr "" -#: includes/OptionsArray.php:156 -#: includes/OptionsArray.php:160 -#: includes/OptionsArray.php:167 +#: includes/OptionsArray.php:183 +#: includes/OptionsArray.php:187 +#: includes/OptionsArray.php:199 msgid "Booking codes" msgstr "" -#: includes/OptionsArray.php:163 +#: includes/OptionsArray.php:191 msgid "" "Enter the booking codes to be generated in advance for booking types with all-day booking time frames. Enter booking codes as a comma separated list, e.g.: Code1,Code2,Code3,Code4\n" "
      More information in the documentation: Booking codes" msgstr "" -#: includes/OptionsArray.php:172 +#: includes/OptionsArray.php:204 msgid "Show booking codes for x days" msgstr "" -#: includes/OptionsArray.php:173 +#: includes/OptionsArray.php:205 msgid "Displays booking codes for the next x days on the timeframe page" msgstr "" -#: includes/OptionsArray.php:185 +#: includes/OptionsArray.php:217 msgid "Booking codes by email" msgstr "" -#: includes/OptionsArray.php:188 +#: includes/OptionsArray.php:220 msgid "Send booking codes by email to location email(s) (automated by cron or ad hoc)" msgstr "" -#: includes/OptionsArray.php:191 +#: includes/OptionsArray.php:223 msgid "Subject for booking codes email" msgstr "" -#: includes/OptionsArray.php:194 +#: includes/OptionsArray.php:226 msgid "Booking codes for {{codes:formatDateRange}} {{item:post_title}}" msgstr "" -#: includes/OptionsArray.php:197 +#: includes/OptionsArray.php:229 msgid "Body for booking codes email" msgstr "" -#: includes/OptionsArray.php:200 +#: includes/OptionsArray.php:233 msgid "" "\n" "

      Booking codes for {{item:post_title}} : {{codes:formatDateRange}}

      \n" @@ -196,58 +192,58 @@ msgid "" " " msgstr "" -#: includes/OptionsArray.php:211 +#: includes/OptionsArray.php:248 msgid "Backup E-Mail for booking codes email" msgstr "" -#: includes/OptionsArray.php:212 +#: includes/OptionsArray.php:249 msgid "Email address that receives a bcc copy of booking codes mailing (not used if empty)" msgstr "" -#: includes/OptionsArray.php:217 +#: includes/OptionsArray.php:254 msgid "Attach iCalendar file to booking codes email" msgstr "" -#: includes/OptionsArray.php:219 +#: includes/OptionsArray.php:256 msgid "Will attach an iCalendar compatible file with booking codes per day to import in their respective calendar application." msgstr "" -#: includes/OptionsArray.php:229 +#: includes/OptionsArray.php:266 msgid "Templates" msgstr "" -#: includes/OptionsArray.php:234 +#: includes/OptionsArray.php:271 msgid "Email templates" msgstr "" -#: includes/OptionsArray.php:238 -#: includes/OptionsArray.php:581 +#: includes/OptionsArray.php:275 +#: includes/OptionsArray.php:645 msgid "Mail-Header from E-Mail" msgstr "" -#: includes/OptionsArray.php:239 +#: includes/OptionsArray.php:276 msgid "E-Mail that will be shown as sender in generated emails" msgstr "" -#: includes/OptionsArray.php:245 -#: includes/OptionsArray.php:588 +#: includes/OptionsArray.php:282 +#: includes/OptionsArray.php:652 msgid "Mail-Header from Name" msgstr "" -#: includes/OptionsArray.php:246 -#: includes/OptionsArray.php:589 +#: includes/OptionsArray.php:283 +#: includes/OptionsArray.php:653 msgid "Name that will be shown as sender in generated emails" msgstr "" -#: includes/OptionsArray.php:252 +#: includes/OptionsArray.php:289 msgid "Mail-Signature" msgstr "" -#: includes/OptionsArray.php:253 +#: includes/OptionsArray.php:290 msgid "E-Mail signature that will appear wherever you put {{booking:getEmailSignature}}" msgstr "" -#: includes/OptionsArray.php:256 +#: includes/OptionsArray.php:294 msgid "" "\n" "

      \n" @@ -256,19 +252,19 @@ msgid "" "

      \t\t\t\t\t" msgstr "" -#: includes/OptionsArray.php:263 +#: includes/OptionsArray.php:305 msgid "Booking confirmed email subject" msgstr "" -#: includes/OptionsArray.php:267 +#: includes/OptionsArray.php:310 msgid "Your booking {{item:post_title}} at {{location:post_title}} {{booking:formattedBookingDate}} " msgstr "" -#: includes/OptionsArray.php:271 +#: includes/OptionsArray.php:317 msgid "Booking confirmed email body" msgstr "" -#: includes/OptionsArray.php:275 +#: includes/OptionsArray.php:322 msgid "" "\n" "Hi {{user:first_name}},
      \n" @@ -298,36 +294,36 @@ msgid "" " " msgstr "" -#: includes/OptionsArray.php:303 +#: includes/OptionsArray.php:354 msgid "Attach iCalendar file to booking email" msgstr "" -#: includes/OptionsArray.php:306 +#: includes/OptionsArray.php:357 msgid "Will attach an iCalendar compatible file for users to import in their respective calendar application." msgstr "" -#: includes/OptionsArray.php:309 +#: includes/OptionsArray.php:360 msgid "iCalendar event title" msgstr "" -#: includes/OptionsArray.php:312 +#: includes/OptionsArray.php:363 msgid "The title of the attached event" msgstr "" -#: includes/OptionsArray.php:313 -#: includes/OptionsArray.php:1357 +#: includes/OptionsArray.php:365 +#: includes/OptionsArray.php:1504 msgid "{{item:post_title}} at {{location:post_title}}" msgstr "" -#: includes/OptionsArray.php:317 +#: includes/OptionsArray.php:372 msgid "iCalendar event description" msgstr "" -#: includes/OptionsArray.php:320 +#: includes/OptionsArray.php:375 msgid "The description for the attached event." msgstr "" -#: includes/OptionsArray.php:321 +#: includes/OptionsArray.php:377 msgid "" " Pick up: {{booking:pickupDatetime}}\n" "Return date: {{booking:returnDatetime}}\n" @@ -335,19 +331,19 @@ msgid "" "{{booking:formattedBookingCode}} " msgstr "" -#: includes/OptionsArray.php:328 +#: includes/OptionsArray.php:387 msgid "Booking canceled email subject" msgstr "" -#: includes/OptionsArray.php:331 +#: includes/OptionsArray.php:390 msgid "Booking canceled: {{item:post_title}} at {{location:post_title}} {{booking:formattedBookingDate}}" msgstr "" -#: includes/OptionsArray.php:334 +#: includes/OptionsArray.php:393 msgid "Booking canceled email body" msgstr "" -#: includes/OptionsArray.php:337 +#: includes/OptionsArray.php:397 msgid "" "\n" "Hi {{user:first_name}},
      \n" @@ -358,270 +354,270 @@ msgid "" " " msgstr "" -#: includes/OptionsArray.php:351 +#: includes/OptionsArray.php:415 msgid "Template and booking process messages" msgstr "" -#: includes/OptionsArray.php:356 +#: includes/OptionsArray.php:420 msgid "Booking confirmed message" msgstr "" -#: includes/OptionsArray.php:359 +#: includes/OptionsArray.php:423 msgid "This text is shown as a status message on booking page after a user has confirmed the booking" msgstr "" -#: includes/OptionsArray.php:360 +#: includes/OptionsArray.php:424 msgid "Your booking is confirmed. A confirmation mail has been sent to you." msgstr "" -#: includes/OptionsArray.php:363 +#: includes/OptionsArray.php:427 msgid "Item not available" msgstr "" -#: includes/OptionsArray.php:366 +#: includes/OptionsArray.php:430 msgid "This text is shown on item listings (shortcode cb_items) and item detail page if there is no valid bookable timeframe set for this item" msgstr "" -#: includes/OptionsArray.php:367 +#: includes/OptionsArray.php:431 msgid "This item is currently not bookable." msgstr "" -#: includes/OptionsArray.php:370 +#: includes/OptionsArray.php:434 msgid "Location without available items" msgstr "" -#: includes/OptionsArray.php:373 +#: includes/OptionsArray.php:437 msgid "This text is shown on location listings and location detail page if there are no items available at this location" msgstr "" -#: includes/OptionsArray.php:374 +#: includes/OptionsArray.php:438 msgid "No items available at this location right now." msgstr "" -#: includes/OptionsArray.php:377 +#: includes/OptionsArray.php:441 msgid "Show contactdetails on booking without confirmation?" msgstr "" -#: includes/OptionsArray.php:380 +#: includes/OptionsArray.php:444 msgid "If activated the contactdetails (e.g. phone number, pickupinstructions) will be shown on booking page even if the booking is not confirmed by user. Otherwise these info will be shown only after booking is confirmed" msgstr "" -#: includes/OptionsArray.php:383 +#: includes/OptionsArray.php:447 msgid "Infotext hidden contactdetails" msgstr "" -#: includes/OptionsArray.php:386 +#: includes/OptionsArray.php:450 msgid "This text is displayed when contact details of the station are shown only after booking confirmation." msgstr "" -#: includes/OptionsArray.php:387 +#: includes/OptionsArray.php:451 msgid "Please confirm the booking to see the contact details for pickup and return." msgstr "" -#: includes/OptionsArray.php:390 +#: includes/OptionsArray.php:454 msgid "Text book this item on booking page" msgstr "" -#: includes/OptionsArray.php:393 +#: includes/OptionsArray.php:457 msgid "This text is displayed on a booking detail page above the booking calendar ." msgstr "" -#: includes/OptionsArray.php:394 +#: includes/OptionsArray.php:458 msgid "Book this item at this location" msgstr "" -#: includes/OptionsArray.php:397 +#: includes/OptionsArray.php:461 msgid "Label for booking button" msgstr "" -#: includes/OptionsArray.php:400 +#: includes/OptionsArray.php:464 msgid "This text is displayed on the booking button on item/location listing pages." msgstr "" -#: includes/OptionsArray.php:401 +#: includes/OptionsArray.php:465 msgid "Book item" msgstr "" -#: includes/OptionsArray.php:404 +#: includes/OptionsArray.php:468 msgid "User details on booking page" msgstr "" -#: includes/OptionsArray.php:407 +#: includes/OptionsArray.php:471 msgid "This textblock is displayed on the booking details page. Please use template-tags to fill in user details" msgstr "" -#: includes/OptionsArray.php:408 +#: includes/OptionsArray.php:472 msgid "{{[Phone: ]user:phone}}
      {{[Address: ]user:address}}" msgstr "" -#: includes/OptionsArray.php:418 +#: includes/OptionsArray.php:482 msgid "Image formatting" msgstr "" -#: includes/OptionsArray.php:423 +#: includes/OptionsArray.php:487 msgid "Listing image small width (in px)" msgstr "" -#: includes/OptionsArray.php:426 +#: includes/OptionsArray.php:490 msgid "Defines the image width of small images in location and item listings" msgstr "" -#: includes/OptionsArray.php:433 +#: includes/OptionsArray.php:497 msgid "Listing image small height (in px)" msgstr "" -#: includes/OptionsArray.php:436 +#: includes/OptionsArray.php:500 msgid "Defines the image height of small images in location and item listings" msgstr "" -#: includes/OptionsArray.php:443 +#: includes/OptionsArray.php:507 msgid "Listing image medium width (in px)" msgstr "" -#: includes/OptionsArray.php:446 +#: includes/OptionsArray.php:510 msgid "Defines the image width of medium images in location and item listings" msgstr "" -#: includes/OptionsArray.php:453 +#: includes/OptionsArray.php:517 msgid "Listing image medium height (in px)" msgstr "" -#: includes/OptionsArray.php:456 +#: includes/OptionsArray.php:520 msgid "Defines the image height of medium images in location and item listings" msgstr "" -#: includes/OptionsArray.php:463 +#: includes/OptionsArray.php:527 msgid "Crop images" msgstr "" -#: includes/OptionsArray.php:466 +#: includes/OptionsArray.php:530 msgid "If checked the image will be cropped to specified dimensions using center crop positions" msgstr "" -#: includes/OptionsArray.php:475 +#: includes/OptionsArray.php:539 msgid "Color schemes" msgstr "" -#: includes/OptionsArray.php:480 +#: includes/OptionsArray.php:544 msgid "Base color" msgstr "" -#: includes/OptionsArray.php:483 +#: includes/OptionsArray.php:547 msgid "Defines the color that is used in headings and buttons" msgstr "" -#: includes/OptionsArray.php:487 +#: includes/OptionsArray.php:551 msgid "Secondary color" msgstr "" -#: includes/OptionsArray.php:490 +#: includes/OptionsArray.php:554 msgid "The color shown when hovering a button or a link" msgstr "" -#: includes/OptionsArray.php:494 +#: includes/OptionsArray.php:558 msgid "Button color" msgstr "" -#: includes/OptionsArray.php:497 +#: includes/OptionsArray.php:561 msgid "The default color for buttons" msgstr "" -#: includes/OptionsArray.php:501 +#: includes/OptionsArray.php:565 msgid "Confirmation / Available Color" msgstr "" -#: includes/OptionsArray.php:504 +#: includes/OptionsArray.php:568 msgid "The color that is used to signify if an item is available or that an action has been completed successfully" msgstr "" -#: includes/OptionsArray.php:509 +#: includes/OptionsArray.php:573 msgid "Cancel / Not Available Color" msgstr "" -#: includes/OptionsArray.php:512 +#: includes/OptionsArray.php:576 msgid "The color that is used to signify if an item is unavailable or for buttons to abort actions" msgstr "" -#: includes/OptionsArray.php:517 +#: includes/OptionsArray.php:581 msgid "Temporarily Unavailable Color" msgstr "" -#: includes/OptionsArray.php:520 +#: includes/OptionsArray.php:584 msgid "The color that is used to signify if an item is temporarily unbookable (i.e. holiday)" msgstr "" -#: includes/OptionsArray.php:525 +#: includes/OptionsArray.php:589 msgid "Greyed out Color" msgstr "" -#: includes/OptionsArray.php:528 +#: includes/OptionsArray.php:592 msgid "The color used to signify that no timeframe has been created for an item or a button that is not yet clickable" msgstr "" -#: includes/OptionsArray.php:533 +#: includes/OptionsArray.php:597 msgid "Background Color" msgstr "" -#: includes/OptionsArray.php:536 +#: includes/OptionsArray.php:600 msgid "The color used for the background of tables and similar elements" msgstr "" -#: includes/OptionsArray.php:541 +#: includes/OptionsArray.php:605 msgid "Notice Background Color" msgstr "" -#: includes/OptionsArray.php:544 +#: includes/OptionsArray.php:608 msgid "The color used for the background of notices" msgstr "" -#: includes/OptionsArray.php:548 +#: includes/OptionsArray.php:612 msgid "Light text color" msgstr "" -#: includes/OptionsArray.php:551 +#: includes/OptionsArray.php:615 msgid "The color used for light text on dark backgrounds" msgstr "" -#: includes/OptionsArray.php:555 +#: includes/OptionsArray.php:619 msgid "Dark text color" msgstr "" -#: includes/OptionsArray.php:558 +#: includes/OptionsArray.php:622 msgid "The color used for dark text on light backgrounds" msgstr "" -#: includes/OptionsArray.php:571 -#: src/Wordpress/CustomPostType/Restriction.php:308 -#: src/Wordpress/CustomPostType/Restriction.php:329 +#: includes/OptionsArray.php:635 +#: src/Wordpress/CustomPostType/Restriction.php:311 +#: src/Wordpress/CustomPostType/Restriction.php:332 #: templates/dashboard-index.php:47 msgid "Restrictions" msgstr "" -#: includes/OptionsArray.php:576 +#: includes/OptionsArray.php:640 msgid "Manage Item Restriction Templates" msgstr "" -#: includes/OptionsArray.php:577 +#: includes/OptionsArray.php:641 msgid "Templates for restriction emails.
      More Information in the documentation" msgstr "" -#: includes/OptionsArray.php:582 +#: includes/OptionsArray.php:646 msgid "Email that will be shown as sender in generated emails" msgstr "" -#: includes/OptionsArray.php:597 +#: includes/OptionsArray.php:661 msgid "Breakdown email subject" msgstr "" -#: includes/OptionsArray.php:600 +#: includes/OptionsArray.php:664 msgid "Breakdown of {{item:post_title}} for your booking {{booking:formattedBookingDate}}" msgstr "" -#: includes/OptionsArray.php:603 +#: includes/OptionsArray.php:667 msgid "Breakdown email body" msgstr "" -#: includes/OptionsArray.php:606 +#: includes/OptionsArray.php:671 msgid "" "

      Hello {{user:first_name}},

      \n" "\n" @@ -638,19 +634,19 @@ msgid "" " " msgstr "" -#: includes/OptionsArray.php:623 +#: includes/OptionsArray.php:692 msgid "Usage restriction email subject" msgstr "" -#: includes/OptionsArray.php:626 +#: includes/OptionsArray.php:695 msgid "Restriction of use for {{item:post_title}} for your booking {{booking:formattedBookingDate}}" msgstr "" -#: includes/OptionsArray.php:629 +#: includes/OptionsArray.php:698 msgid "Restriction email body" msgstr "" -#: includes/OptionsArray.php:632 +#: includes/OptionsArray.php:702 msgid "" "

      Hello {{user:first_name}},

      \n" "

      \n" @@ -673,19 +669,19 @@ msgid "" " {{booking:getEmailSignature}}" msgstr "" -#: includes/OptionsArray.php:655 +#: includes/OptionsArray.php:729 msgid "Restriction cancelled subject" msgstr "" -#: includes/OptionsArray.php:658 +#: includes/OptionsArray.php:732 msgid "Restriction for article {{item:post_title}} no longer exists" msgstr "" -#: includes/OptionsArray.php:661 +#: includes/OptionsArray.php:735 msgid "Restriction cancelled email body" msgstr "" -#: includes/OptionsArray.php:664 +#: includes/OptionsArray.php:739 msgid "" "

      Hello {{user:first_name}},

      \n" "

      The article {{item:post_title}} is now fully usable again.

      \n" @@ -697,125 +693,125 @@ msgid "" " {{booking:getEmailSignature}}" msgstr "" -#: includes/OptionsArray.php:677 +#: includes/OptionsArray.php:756 msgid "Restriction settings" msgstr "" -#: includes/OptionsArray.php:679 +#: includes/OptionsArray.php:758 msgid "Settings for restrictions.
      More Information in the documentation" msgstr "" -#: includes/OptionsArray.php:682 +#: includes/OptionsArray.php:761 msgid "Do not cancel bookings on total breakdown" msgstr "" -#: includes/OptionsArray.php:685 +#: includes/OptionsArray.php:764 msgid "If checked, bookings will not be cancelled if the item has broken down. The user will be notified and once the item becomes available again, the old bookings are still valid." msgstr "" -#: includes/OptionsArray.php:691 +#: includes/OptionsArray.php:770 msgid "Restrict bookings by booking rules" msgstr "" -#: includes/OptionsArray.php:696 +#: includes/OptionsArray.php:775 msgid "Count cancelled bookings towards quota" msgstr "" -#: includes/OptionsArray.php:697 +#: includes/OptionsArray.php:776 msgid "Check if bookings that have been cancelled in the booking period shall be counted towards the amount of booked days for the user. More info in the documentation" msgstr "" -#: includes/OptionsArray.php:706 +#: includes/OptionsArray.php:785 msgid "Rule " msgstr "" -#: includes/OptionsArray.php:707 +#: includes/OptionsArray.php:786 msgid "Add another rule" msgstr "" -#: includes/OptionsArray.php:708 +#: includes/OptionsArray.php:787 msgid "Remove rule" msgstr "" -#: includes/OptionsArray.php:712 +#: includes/OptionsArray.php:791 msgid "Rule type" msgstr "" -#: includes/OptionsArray.php:713 +#: includes/OptionsArray.php:792 msgid "Select the kind of rule" msgstr "" -#: includes/OptionsArray.php:723 +#: includes/OptionsArray.php:802 msgid "Rule description" msgstr "" -#: includes/OptionsArray.php:741 +#: includes/OptionsArray.php:820 msgid "Select an option" msgstr "" -#: includes/OptionsArray.php:747 +#: includes/OptionsArray.php:826 msgid "Applies to all" msgstr "" -#: includes/OptionsArray.php:748 +#: includes/OptionsArray.php:827 msgid "Check if this rule applies to all items" msgstr "" -#: includes/OptionsArray.php:753 +#: includes/OptionsArray.php:832 msgid "Applies to categories" msgstr "" -#: includes/OptionsArray.php:754 +#: includes/OptionsArray.php:833 msgid "Check the categories that these rules apply to" msgstr "" -#: includes/OptionsArray.php:764 +#: includes/OptionsArray.php:844 msgid "Groups exempt from rule" msgstr "" -#: includes/OptionsArray.php:765 +#: includes/OptionsArray.php:845 msgid "Here you can define if the rule should not apply to a specific user group. Will apply to all groups if left empty (Administrators and item / location admins are always excluded)." msgstr "" -#: includes/OptionsArray.php:784 +#: includes/OptionsArray.php:864 msgid "Reminder" msgstr "" -#: includes/OptionsArray.php:790 +#: includes/OptionsArray.php:870 msgid "Booking reminder" msgstr "" -#: includes/OptionsArray.php:792 +#: includes/OptionsArray.php:873 msgid "You can set here whether users should receive a reminder email before the start of a booking.
      More Information in the documentation" msgstr "" -#: includes/OptionsArray.php:798 -#: includes/OptionsArray.php:895 -#: includes/OptionsArray.php:931 -#: includes/OptionsArray.php:1000 +#: includes/OptionsArray.php:881 +#: includes/OptionsArray.php:992 +#: includes/OptionsArray.php:1036 +#: includes/OptionsArray.php:1119 msgid "Activate" msgstr "" -#: includes/OptionsArray.php:804 -#: includes/OptionsArray.php:901 -#: includes/OptionsArray.php:938 -#: includes/OptionsArray.php:1007 +#: includes/OptionsArray.php:887 +#: includes/OptionsArray.php:998 +#: includes/OptionsArray.php:1043 +#: includes/OptionsArray.php:1126 msgid "E-mail subject" msgstr "" -#: includes/OptionsArray.php:807 -#: includes/OptionsArray.php:941 +#: includes/OptionsArray.php:890 +#: includes/OptionsArray.php:1046 msgid "Upcoming booking of {{item:post_title}} {{booking:formattedBookingDate}}" msgstr "" -#: includes/OptionsArray.php:810 -#: includes/OptionsArray.php:907 -#: includes/OptionsArray.php:944 -#: includes/OptionsArray.php:1013 +#: includes/OptionsArray.php:893 +#: includes/OptionsArray.php:1004 +#: includes/OptionsArray.php:1049 +#: includes/OptionsArray.php:1132 msgid "email body" msgstr "" -#: includes/OptionsArray.php:813 +#: includes/OptionsArray.php:897 msgid "" "

      Hi {{user:first_name}},

      \n" "

      Your booking period for the item {{item:post_title}} will start soon.
      \n" @@ -829,41 +825,41 @@ msgid "" "{{booking:getEmailSignature}}" msgstr "" -#: includes/OptionsArray.php:827 +#: includes/OptionsArray.php:915 msgid "Sent reminder x days before booking start" msgstr "" -#: includes/OptionsArray.php:829 +#: includes/OptionsArray.php:918 msgid "This reminder email will be sent to users x days before the start of the booking. If the booking is made less days before the specified days, no reminder email will be sent" msgstr "" -#: includes/OptionsArray.php:843 -#: includes/OptionsArray.php:956 -#: includes/OptionsArray.php:1026 +#: includes/OptionsArray.php:934 +#: includes/OptionsArray.php:1066 +#: includes/OptionsArray.php:1150 msgid "Time" msgstr "" -#: includes/OptionsArray.php:845 -#: includes/OptionsArray.php:958 -#: includes/OptionsArray.php:1028 +#: includes/OptionsArray.php:937 +#: includes/OptionsArray.php:1069 +#: includes/OptionsArray.php:1153 msgid "Define when the reminder should be sent. The actual sending may differ from the defined value by a few hours, depending on how your WordPress is configured." msgstr "" -#: includes/OptionsArray.php:886 +#: includes/OptionsArray.php:980 msgid "email after booking has ended" msgstr "" -#: includes/OptionsArray.php:888 +#: includes/OptionsArray.php:983 msgid "" "Here you can set whether users should receive an additional e-mail after completing a booking. This can be used, for example, to inquire about the users satisfaction or possible problems during the booking.\n" "\t\t\t\t\t
      The email will be sent around midnight after the booking day has ended." msgstr "" -#: includes/OptionsArray.php:904 +#: includes/OptionsArray.php:1001 msgid "Your booking of {{item:post_title}} {{booking:formattedBookingDate}} has ended" msgstr "" -#: includes/OptionsArray.php:910 +#: includes/OptionsArray.php:1008 msgid "" "

      Hi {{user:first_name}},

      \n" "

      Your booking of {{item:post_title}} at {{location:post_title}} has ended.
      \n" @@ -873,20 +869,20 @@ msgid "" "{{booking:getEmailSignature}}" msgstr "" -#: includes/OptionsArray.php:923 +#: includes/OptionsArray.php:1025 msgid "Reminder for locations before booking starts" msgstr "" -#: includes/OptionsArray.php:925 +#: includes/OptionsArray.php:1028 msgid "You can set here whether locations should receive a reminder email before the start of a booking.
      More Information in the documentation" msgstr "" -#: includes/OptionsArray.php:934 -#: includes/OptionsArray.php:1003 +#: includes/OptionsArray.php:1039 +#: includes/OptionsArray.php:1122 msgid "The reminders need to be enabled for all locations individually. This is only the main on/off switch." msgstr "" -#: includes/OptionsArray.php:947 +#: includes/OptionsArray.php:1053 msgid "" "

      Hi,

      \n" "

      The booking period for the item {{item:post_title}} at {{location:post_title}} will start soon.
      \n" @@ -896,38 +892,38 @@ msgid "" "{{booking:getEmailSignature}}" msgstr "" -#: includes/OptionsArray.php:973 -#: includes/OptionsArray.php:1044 +#: includes/OptionsArray.php:1086 +#: includes/OptionsArray.php:1171 msgid "Bookings of" msgstr "" -#: includes/OptionsArray.php:975 +#: includes/OptionsArray.php:1089 msgid "Define for which booking start day the notifications should be sent" msgstr "" -#: includes/OptionsArray.php:982 -#: includes/OptionsArray.php:1053 +#: includes/OptionsArray.php:1098 +#: includes/OptionsArray.php:1183 msgid "current day" msgstr "" -#: includes/OptionsArray.php:983 -#: includes/OptionsArray.php:1054 +#: includes/OptionsArray.php:1099 +#: includes/OptionsArray.php:1184 msgid "next day" msgstr "" -#: includes/OptionsArray.php:992 +#: includes/OptionsArray.php:1108 msgid "Reminder for locations before booking ends" msgstr "" -#: includes/OptionsArray.php:994 +#: includes/OptionsArray.php:1111 msgid "You can set here whether locations should receive a reminder email before the end of a booking.
      More Information in the documentation" msgstr "" -#: includes/OptionsArray.php:1010 +#: includes/OptionsArray.php:1129 msgid "Booking of {{item:post_title}} {{booking:formattedBookingDate}}" msgstr "" -#: includes/OptionsArray.php:1016 +#: includes/OptionsArray.php:1136 msgid "" "

      Hi,

      \n" "

      The booking period for the item {{item:post_title}} at {{location:post_title}} will end soon.
      \n" @@ -938,286 +934,286 @@ msgid "" "{{booking:getEmailSignature}}" msgstr "" -#: includes/OptionsArray.php:1046 +#: includes/OptionsArray.php:1174 msgid "Define for which booking end day the notifications should be sent" msgstr "" -#: includes/OptionsArray.php:1067 +#: includes/OptionsArray.php:1197 msgid "Migration" msgstr "" -#: includes/OptionsArray.php:1071 +#: includes/OptionsArray.php:1201 msgid "Finish upgrade to latest version" msgstr "" -#: includes/OptionsArray.php:1073 +#: includes/OptionsArray.php:1203 msgid "Click here to finish the upgrade to the latest version.
      This needs to be done after updating the plugin to a new version.
      If you do not do this, the plugin may not work correctly." msgstr "" -#: includes/OptionsArray.php:1076 +#: includes/OptionsArray.php:1206 msgid "Finish upgrade" msgstr "" -#: includes/OptionsArray.php:1085 +#: includes/OptionsArray.php:1215 msgid "Migrate from Commons Booking Version 0.X" msgstr "" -#: includes/OptionsArray.php:1087 +#: includes/OptionsArray.php:1217 msgid "Migrate data from CommonsBooking Version 0.X.
      The migration includes: locations, items, timeframes and bookings.
      If you have clicked \"Migrate\" before, starting the migration again will overwrite any changes you made to locations, items, timeframes and bookings.
      Please read the documentation How to migrate from version 0.9.x to 2.x.x before you start migration." msgstr "" -#: includes/OptionsArray.php:1090 -#: src/View/Migration.php:73 +#: includes/OptionsArray.php:1220 +#: src/View/Migration.php:77 msgid "Start Migration" msgstr "" -#: includes/OptionsArray.php:1101 +#: includes/OptionsArray.php:1231 msgid "CommonsBooking Version 0.X profile fields" msgstr "" -#: includes/OptionsArray.php:1103 +#: includes/OptionsArray.php:1233 msgid "Enable the following legacy CommonsBooking Version 0.X user profile fields:" msgstr "" -#: includes/OptionsArray.php:1106 +#: includes/OptionsArray.php:1236 msgid "Enable" msgstr "" -#: includes/OptionsArray.php:1111 +#: includes/OptionsArray.php:1241 msgid "Terms & Services Url" msgstr "" -#: includes/OptionsArray.php:1120 +#: includes/OptionsArray.php:1250 msgid "Migrate bookings to new version" msgstr "" -#: includes/OptionsArray.php:1122 +#: includes/OptionsArray.php:1252 msgid "Migrate bookings to new format so that they are listed at bookings menu item.
      This function is only for special cases during migration. Please use it only in case of problems with migration." msgstr "" -#: includes/OptionsArray.php:1125 +#: includes/OptionsArray.php:1255 #: src/View/MassOperations.php:109 -#: src/View/Migration.php:107 +#: src/View/Migration.php:112 msgid "Migrate bookings" msgstr "" -#: includes/OptionsArray.php:1138 -#: includes/OptionsArray.php:1192 +#: includes/OptionsArray.php:1268 +#: includes/OptionsArray.php:1326 msgid "Export" msgstr "" -#: includes/OptionsArray.php:1142 +#: includes/OptionsArray.php:1272 msgid "Download timeframes export" msgstr "" -#: includes/OptionsArray.php:1146 -#: src/Wordpress/CustomPostType/Map.php:559 +#: includes/OptionsArray.php:1276 +#: src/Wordpress/CustomPostType/Map.php:557 #: src/Wordpress/CustomPostType/Restriction.php:53 -#: src/Wordpress/CustomPostType/Restriction.php:417 -#: src/Wordpress/CustomPostType/Timeframe.php:100 -#: src/Wordpress/CustomPostType/Timeframe.php:486 +#: src/Wordpress/CustomPostType/Restriction.php:421 +#: src/Wordpress/CustomPostType/Timeframe.php:104 +#: src/Wordpress/CustomPostType/Timeframe.php:495 msgid "Type" msgstr "" -#: includes/OptionsArray.php:1147 +#: includes/OptionsArray.php:1277 msgid "Select Type of this timeframe (e.g. bookable, repair, holidays, booking). See Documentation for detailed information." msgstr "" -#: includes/OptionsArray.php:1153 +#: includes/OptionsArray.php:1283 msgid "Location-Fields" msgstr "" -#: includes/OptionsArray.php:1154 -#: includes/OptionsArray.php:1161 +#: includes/OptionsArray.php:1285 +#: includes/OptionsArray.php:1294 msgid "Just add field names, no matter if its a post- or a meta-field. Comma separated list. Beside the standard post fields and standard postmeta-fields, the following custom meta fields are available. Copy only the values in [] in the field without the brackets. %s" msgstr "" -#: includes/OptionsArray.php:1160 +#: includes/OptionsArray.php:1292 msgid "Item-Fields" msgstr "" -#: includes/OptionsArray.php:1167 +#: includes/OptionsArray.php:1301 msgid "User-Fields" msgstr "" -#: includes/OptionsArray.php:1168 +#: includes/OptionsArray.php:1302 msgid "Just add field names, no matter if its a userfield or a meta-field. Comma separated list." msgstr "" -#: includes/OptionsArray.php:1173 +#: includes/OptionsArray.php:1307 msgid "Export start date" msgstr "" -#: includes/OptionsArray.php:1183 +#: includes/OptionsArray.php:1317 msgid "Export end date" msgstr "" -#: includes/OptionsArray.php:1200 +#: includes/OptionsArray.php:1334 msgid "Cron settings for timeframes export" msgstr "" -#: includes/OptionsArray.php:1204 +#: includes/OptionsArray.php:1338 msgid "Run as cronjob" msgstr "" -#: includes/OptionsArray.php:1209 +#: includes/OptionsArray.php:1343 msgid "Export interval" msgstr "" -#: includes/OptionsArray.php:1213 -#: includes/OptionsArray.php:1214 +#: includes/OptionsArray.php:1347 +#: includes/OptionsArray.php:1348 msgid "minutes" msgstr "" -#: includes/OptionsArray.php:1215 +#: includes/OptionsArray.php:1349 msgid "daily" msgstr "" -#: includes/OptionsArray.php:1219 +#: includes/OptionsArray.php:1353 msgid "Export timerange" msgstr "" -#: includes/OptionsArray.php:1220 +#: includes/OptionsArray.php:1354 msgid "Export timerange in days." msgstr "" -#: includes/OptionsArray.php:1229 +#: includes/OptionsArray.php:1363 msgid "Filepath" msgstr "" -#: includes/OptionsArray.php:1230 +#: includes/OptionsArray.php:1364 msgid "Absolute path on your webserver (including trailing slash) where export file will be saved to." msgstr "" -#: includes/OptionsArray.php:1242 -#: includes/OptionsArray.php:1270 +#: includes/OptionsArray.php:1376 +#: includes/OptionsArray.php:1404 msgid "API" msgstr "" -#: includes/OptionsArray.php:1246 +#: includes/OptionsArray.php:1380 msgid "Configure API Access" msgstr "" -#: includes/OptionsArray.php:1250 +#: includes/OptionsArray.php:1384 msgid "Activate API" msgstr "" -#: includes/OptionsArray.php:1251 +#: includes/OptionsArray.php:1385 msgid "If selected, the API is enabled. See more information in the documentation: API documentation" msgstr "" -#: includes/OptionsArray.php:1256 +#: includes/OptionsArray.php:1390 msgid "Enable API Access without API-Key" msgstr "" -#: includes/OptionsArray.php:1257 +#: includes/OptionsArray.php:1391 msgid "If selected, the API is accessible without an API-Key. For details see: API documentation" msgstr "" -#: includes/OptionsArray.php:1264 +#: includes/OptionsArray.php:1398 msgid "API shares" msgstr "" -#: includes/OptionsArray.php:1265 +#: includes/OptionsArray.php:1399 msgid "You can define on or more API shares. Read the documentation for more information about API shares and configuration API documentation" msgstr "" -#: includes/OptionsArray.php:1271 +#: includes/OptionsArray.php:1405 msgid "Add Another API" msgstr "" -#: includes/OptionsArray.php:1272 +#: includes/OptionsArray.php:1406 msgid "Remove API" msgstr "" -#: includes/OptionsArray.php:1279 +#: includes/OptionsArray.php:1413 msgid "API name" msgstr "" -#: includes/OptionsArray.php:1280 +#: includes/OptionsArray.php:1414 msgid "Internal name for this API share" msgstr "" -#: includes/OptionsArray.php:1285 +#: includes/OptionsArray.php:1419 msgid "API enabled" msgstr "" -#: includes/OptionsArray.php:1286 +#: includes/OptionsArray.php:1420 msgid "If checked this API share is enabled" msgstr "" -#: includes/OptionsArray.php:1291 +#: includes/OptionsArray.php:1425 msgid "Push URL" msgstr "" -#: includes/OptionsArray.php:1292 +#: includes/OptionsArray.php:1426 msgid "URL that gets push information everytime there was a change on CommonsBooking data" msgstr "" -#: includes/OptionsArray.php:1297 +#: includes/OptionsArray.php:1431 msgid "API Key" msgstr "" -#: includes/OptionsArray.php:1300 +#: includes/OptionsArray.php:1434 msgid " You must set an API-Key. The API key should consist of alphanumeric characters and be at least 24 characters long." msgstr "" -#: includes/OptionsArray.php:1303 +#: includes/OptionsArray.php:1437 msgid "API Owner" msgstr "" -#: includes/OptionsArray.php:1304 +#: includes/OptionsArray.php:1438 msgid "The owner value is provided by the API. It is set to the blog name by default in this version. In future versions you may be able to change this information" msgstr "" -#: includes/OptionsArray.php:1324 +#: includes/OptionsArray.php:1458 msgid "Advanced Options" msgstr "" -#: includes/OptionsArray.php:1328 +#: includes/OptionsArray.php:1462 msgid "Set Custom metadata to locations and items" msgstr "" -#: includes/OptionsArray.php:1329 +#: includes/OptionsArray.php:1464 msgid "This is an advanced feature and should only be used if you are experienced or instructed how to set it up properly. In future versions we will add more detailed information and documentation." msgstr "" -#: includes/OptionsArray.php:1335 +#: includes/OptionsArray.php:1472 msgid "Meta Data" msgstr "" -#: includes/OptionsArray.php:1336 +#: includes/OptionsArray.php:1474 msgid "" "Use only this format, separated by semicolon and each entry in a new line:
      post_type(item/location);field-name;label(english),type(checkbox,number,text),description(in english)
      \n" " Example: item;waterproof;Waterproof material;checkbox;\"This item is waterproof and can be used in heavy rain\" " msgstr "" -#: includes/OptionsArray.php:1344 +#: includes/OptionsArray.php:1486 msgid "iCalendar Feed" msgstr "" -#: includes/OptionsArray.php:1345 +#: includes/OptionsArray.php:1488 msgid "Enables users to copy a url for a dynamic iCalendar feed into their own digital calendars. This feature is experimental." msgstr "" -#: includes/OptionsArray.php:1350 +#: includes/OptionsArray.php:1496 msgid "Enable iCalendar feed" msgstr "" -#: includes/OptionsArray.php:1355 +#: includes/OptionsArray.php:1501 msgid "Event title" msgstr "" -#: includes/OptionsArray.php:1356 -#: includes/OptionsArray.php:1364 +#: includes/OptionsArray.php:1502 +#: includes/OptionsArray.php:1514 msgid "You can use template tags here as well" msgstr "" -#: includes/OptionsArray.php:1363 +#: includes/OptionsArray.php:1513 msgid "Event description" msgstr "" -#: includes/OptionsArray.php:1365 +#: includes/OptionsArray.php:1516 msgid "" "\n" "Pick up: {{booking:pickupDatetime}}\n" @@ -1226,37 +1222,37 @@ msgid "" "{{booking:formattedBookingCode}} " msgstr "" -#: includes/OptionsArray.php:1377 +#: includes/OptionsArray.php:1531 msgid "Advanced caching settings" msgstr "" -#: includes/OptionsArray.php:1380 +#: includes/OptionsArray.php:1534 msgid "Allows you to change options regarding the caching system" msgstr "" -#: includes/OptionsArray.php:1383 -#: src/Service/Cache.php:370 +#: includes/OptionsArray.php:1537 +#: src/Service/Cache.php:368 msgid "Clear Cache" msgstr "" -#: includes/OptionsArray.php:1389 +#: includes/OptionsArray.php:1543 msgid "Filesystem cache path" msgstr "" -#: includes/OptionsArray.php:1390 +#: includes/OptionsArray.php:1544 msgid "Where the filesystem cache should be created. Only change when filesystem caching is not working." msgstr "" -#: includes/OptionsArray.php:1396 -#: includes/OptionsArray.php:1413 +#: includes/OptionsArray.php:1550 +#: includes/OptionsArray.php:1567 msgid "Current connection status" msgstr "" -#: includes/OptionsArray.php:1402 +#: includes/OptionsArray.php:1556 msgid "Enable REDIS Caching (experimental)" msgstr "" -#: includes/OptionsArray.php:1407 +#: includes/OptionsArray.php:1561 msgid "REDIS DSN (REDIS Server URL)" msgstr "" @@ -1285,8 +1281,8 @@ msgid "Please enter your phone number" msgstr "" #: src/CB/CB1UserFields.php:90 -#: src/CB/CB1UserFields.php:281 -#: src/Wordpress/CustomPostType/Location.php:219 +#: src/CB/CB1UserFields.php:280 +#: src/Wordpress/CustomPostType/Location.php:221 #: templates/booking-single.php:77 msgid "Address" msgstr "" @@ -1308,23 +1304,23 @@ msgid "Please accept the terms & conditions" msgstr "" #. translators: %s = terms and service url -#: src/CB/CB1UserFields.php:185 +#: src/CB/CB1UserFields.php:188 msgid "Read the terms and services" msgstr "" -#: src/CB/CB1UserFields.php:269 +#: src/CB/CB1UserFields.php:268 msgid "Extra Fields" msgstr "" -#: src/CB/CB1UserFields.php:273 +#: src/CB/CB1UserFields.php:272 msgid "Phone number" msgstr "" -#: src/CB/CB1UserFields.php:289 +#: src/CB/CB1UserFields.php:288 msgid "Terms and conditions" msgstr "" -#: src/CB/CB1UserFields.php:295 +#: src/CB/CB1UserFields.php:298 msgid "Accepted Terms & Conditions" msgstr "" @@ -1332,7 +1328,7 @@ msgstr "" msgid "Booking is saved as draft." msgstr "" -#: src/Exception/TimeframeInvalidException.php:15 +#: src/Exception/TimeframeInvalidException.php:14 msgid "Timeframe is saved as draft." msgstr "" @@ -1345,204 +1341,204 @@ msgstr "" msgid "map is not published" msgstr "" -#: src/Map/MapShortcode.php:49 +#: src/Map/MapShortcode.php:51 msgid "opening hours" msgstr "" -#: src/Map/MapShortcode.php:50 +#: src/Map/MapShortcode.php:52 msgid "contact" msgstr "" -#: src/Map/MapShortcode.php:51 +#: src/Map/MapShortcode.php:53 msgid "from" msgstr "" -#: src/Map/MapShortcode.php:52 +#: src/Map/MapShortcode.php:54 msgid "until" msgstr "" -#: src/Map/MapShortcode.php:53 +#: src/Map/MapShortcode.php:55 msgid "for at least" msgstr "" -#: src/Map/MapShortcode.php:54 +#: src/Map/MapShortcode.php:56 msgid "day(s)" msgstr "" -#: src/Map/MapShortcode.php:55 +#: src/Map/MapShortcode.php:57 msgid "Sorry, no locations found." msgstr "" -#: src/Map/MapShortcode.php:56 -#: src/Wordpress/CustomPostType/Map.php:535 +#: src/Map/MapShortcode.php:58 +#: src/Wordpress/CustomPostType/Map.php:533 msgid "filter" msgstr "" -#: src/Map/MapShortcode.php:57 -#: src/Wordpress/CustomPostType/Map.php:517 +#: src/Map/MapShortcode.php:59 +#: src/Wordpress/CustomPostType/Map.php:515 msgid "availability" msgstr "" -#: src/Map/MapShortcode.php:58 -#: src/Wordpress/CustomPostType/Map.php:526 +#: src/Map/MapShortcode.php:60 +#: src/Wordpress/CustomPostType/Map.php:524 msgid "categories" msgstr "" -#: src/Map/MapShortcode.php:59 -#: src/Wordpress/CustomPostType/Map.php:478 +#: src/Map/MapShortcode.php:61 +#: src/Wordpress/CustomPostType/Map.php:476 msgid "distance" msgstr "" -#: src/Map/MapShortcode.php:60 +#: src/Map/MapShortcode.php:62 msgid "address" msgstr "" -#: src/Map/MapShortcode.php:61 +#: src/Map/MapShortcode.php:63 msgid "Sorry, an error occured during your request. Please try again later." msgstr "" -#: src/Map/MapShortcode.php:62 +#: src/Map/MapShortcode.php:64 msgid "The service is currently not available. Please try again later." msgstr "" -#: src/Map/MapShortcode.php:63 +#: src/Map/MapShortcode.php:65 msgid "comming soon" msgstr "" -#: src/Messages/BookingCodesMessage.php:50 +#: src/Messages/BookingCodesMessage.php:51 msgid "Unable to send Emails. No location email(s) configured, check location" msgstr "" -#: src/Messages/BookingCodesMessage.php:53 +#: src/Messages/BookingCodesMessage.php:57 msgid "Could not find booking codes for this timeframe/period" msgstr "" -#: src/Messages/BookingCodesMessage.php:187 +#: src/Messages/BookingCodesMessage.php:208 msgid "booking code for item \"%1$s\": %2$s" msgstr "" -#: src/Messages/Message.php:133 +#: src/Messages/Message.php:141 msgid "Could not send email because mail-template was not available. Check options -> templates" msgstr "" #. translators: %s = Booking code -#: src/Model/Booking.php:145 +#: src/Model/Booking.php:142 msgid "Your booking code is: %s" msgstr "" #. translators: %s = date in WordPress defined format -#: src/Model/Booking.php:441 +#: src/Model/Booking.php:436 msgid " on %s " msgstr "" #. translators: %1 = startdate, %2 = enddate in WordPress defined format -#: src/Model/Booking.php:444 +#: src/Model/Booking.php:439 msgid " from %1$s until %2$s " msgstr "" -#: src/Model/Booking.php:576 +#: src/Model/Booking.php:570 msgid "Please check your booking and click confirm booking" msgstr "" -#: src/Model/Booking.php:582 +#: src/Model/Booking.php:576 msgid "Your booking has been canceled at %s." msgstr "" -#: src/Model/Booking.php:584 +#: src/Model/Booking.php:578 msgid "Your booking has been canceled" msgstr "" -#: src/Model/Booking.php:613 +#: src/Model/Booking.php:607 msgid "Item not found" msgstr "" -#: src/Model/Booking.php:622 +#: src/Model/Booking.php:616 msgid "Location not found" msgstr "" -#: src/Model/Booking.php:627 +#: src/Model/Booking.php:621 msgid "There is no timeframe for this booking. Please create a timeframe first." msgstr "" -#: src/Model/Booking.php:648 +#: src/Model/Booking.php:641 msgid "There are one ore more overlapping bookings within the chosen timerange" msgstr "" -#: src/Model/Booking.php:649 +#: src/Model/Booking.php:642 msgid "Please adjust the start- or end-date." msgstr "" -#: src/Model/Booking.php:650 +#: src/Model/Booking.php:643 msgid "Affected Bookings: %s" msgstr "" -#: src/Model/Booking.php:671 +#: src/Model/Booking.php:664 msgid "Link to your booking" msgstr "" -#: src/Model/Booking.php:1022 +#: src/Model/Booking.php:1016 msgid "Confirmed" msgstr "" -#: src/Model/Booking.php:1024 +#: src/Model/Booking.php:1018 msgid "Unconfirmed" msgstr "" -#: src/Model/Booking.php:1026 +#: src/Model/Booking.php:1020 msgid "Cancelled" msgstr "" -#: src/Model/Booking.php:1028 -#: src/Service/TimeframeExport.php:523 +#: src/Model/Booking.php:1022 #: src/Service/TimeframeExport.php:533 -#: src/Service/TimeframeExport.php:539 +#: src/Service/TimeframeExport.php:543 #: src/Service/TimeframeExport.php:549 -#: src/Service/TimeframeExport.php:559 +#: src/Service/TimeframeExport.php:561 +#: src/Service/TimeframeExport.php:574 msgid "Unknown" msgstr "" -#: src/Model/Location.php:124 +#: src/Model/Location.php:130 msgid "Please contact the contact persons at the location directly if you have any questions regarding collection or return:" msgstr "" -#: src/Model/Restriction.php:242 -#: src/Model/Restriction.php:266 +#: src/Model/Restriction.php:241 +#: src/Model/Restriction.php:265 msgid "Not set" msgstr "" -#: src/Model/Timeframe.php:253 +#: src/Model/Timeframe.php:252 msgid "Available here" msgstr "" #. translators: %s = date in WordPress defined format -#: src/Model/Timeframe.php:258 +#: src/Model/Timeframe.php:257 msgid "on %s" msgstr "" #. translators: %s = date in WordPress defined format -#: src/Model/Timeframe.php:263 +#: src/Model/Timeframe.php:262 msgid "from %s" msgstr "" -#: src/Model/Timeframe.php:267 +#: src/Model/Timeframe.php:266 msgid "permanently" msgstr "" #. translators: %1$s = startdate, second %2$s = enddate in WordPress defined format -#: src/Model/Timeframe.php:273 +#: src/Model/Timeframe.php:272 msgid "from %1$s until %2$s" msgstr "" #. translators: %s = enddate in WordPress defined format -#: src/Model/Timeframe.php:280 +#: src/Model/Timeframe.php:279 msgid "until %s" msgstr "" -#: src/Model/Timeframe.php:556 +#: src/Model/Timeframe.php:552 msgid "Could not get item or location. Please set a valid item and location." msgstr "" -#: src/Model/Timeframe.php:563 +#: src/Model/Timeframe.php:561 msgid "Item or location is missing. Please set item and location." msgstr "" @@ -1550,249 +1546,249 @@ msgstr "" msgid "No dates selected. Please select at least one date." msgstr "" -#: src/Model/Timeframe.php:582 +#: src/Model/Timeframe.php:584 msgid "The same date was selected multiple times. Please select each date only once." msgstr "" -#: src/Model/Timeframe.php:591 +#: src/Model/Timeframe.php:593 msgid "Startdate is missing. Please enter a start date to publish this timeframe." msgstr "" -#: src/Model/Timeframe.php:604 +#: src/Model/Timeframe.php:607 msgid "A pickup time but no return time has been set. Please set the return time." msgstr "" -#: src/Model/Timeframe.php:612 +#: src/Model/Timeframe.php:617 msgid "End date is before start date. Please set a valid end date." msgstr "" -#: src/Model/Timeframe.php:620 +#: src/Model/Timeframe.php:627 msgid "The start- and end-time of the timeframe can not be the same. Please check the full-day checkbox if you want users to be able to book the full day." msgstr "" -#: src/Model/Timeframe.php:645 +#: src/Model/Timeframe.php:652 msgid "Item is already bookable at another location within the same date range. See other timeframe ID: %1$s: %2$s" msgstr "" #. translators: first %s = timeframe-ID, second %s is timeframe post_title -#: src/Model/Timeframe.php:681 +#: src/Model/Timeframe.php:688 msgid "See overlapping timeframe ID: %1$s %2$s" msgstr "" -#: src/Model/Timeframe.php:778 +#: src/Model/Timeframe.php:787 msgid "Overlapping bookable timeframes are only allowed to have the same grid." msgstr "" -#: src/Model/Timeframe.php:794 +#: src/Model/Timeframe.php:803 msgid "Daily repeated time periods are not allowed to overlap." msgstr "" -#: src/Model/Timeframe.php:808 +#: src/Model/Timeframe.php:817 msgid "Overlapping bookable timeframes are not allowed to have the same weekdays." msgstr "" -#: src/Model/Timeframe.php:820 +#: src/Model/Timeframe.php:829 msgid "Overlapping bookable timeframes are not allowed to have the same dates." msgstr "" -#: src/Model/Timeframe.php:827 -#: src/Model/Timeframe.php:834 +#: src/Model/Timeframe.php:836 +#: src/Model/Timeframe.php:843 msgid "The other timeframe is overlapping with your weekly configuration." msgstr "" -#: src/Plugin.php:309 -#: src/Plugin.php:310 +#: src/Plugin.php:311 +#: src/Plugin.php:312 msgid "Item Categories" msgstr "" -#: src/Plugin.php:319 -#: src/Plugin.php:320 +#: src/Plugin.php:321 +#: src/Plugin.php:322 msgid "Location Categories" msgstr "" -#: src/Plugin.php:329 -#: src/Plugin.php:330 +#: src/Plugin.php:331 +#: src/Plugin.php:332 msgid "Mass Operations" msgstr "" -#: src/Plugin.php:435 -#: src/Plugin.php:467 +#: src/Plugin.php:437 +#: src/Plugin.php:470 msgid "Item Category" msgstr "" -#: src/Plugin.php:476 +#: src/Plugin.php:479 msgid "Add custom title for filter" msgstr "" -#: src/Plugin.php:479 +#: src/Plugin.php:482 msgid "Define name that should be used for the category if it is displayed in the map as a filter group. You can also use this to add custom HTML to the category name. When left empty, the defined name of the category will be used." msgstr "" -#: src/Plugin.php:497 +#: src/Plugin.php:500 msgid "Location Category" msgstr "" -#: src/Plugin.php:709 -#: src/Plugin.php:724 -#: src/Wordpress/CustomPostType/Booking.php:922 +#: src/Plugin.php:713 +#: src/Plugin.php:728 +#: src/Wordpress/CustomPostType/Booking.php:924 msgid "CommonsBooking Bookings" msgstr "" -#: src/Repository/BookingCodes.php:332 +#: src/Repository/BookingCodes.php:337 msgid "No booking codes could be created because there were no booking codes to choose from. Please set some booking codes in the CommonsBooking settings." msgstr "" -#: src/Repository/BookingCodes.php:339 +#: src/Repository/BookingCodes.php:344 msgid "No booking codes could be created because the location of the timeframe could not be found." msgstr "" -#: src/Repository/BookingCodes.php:345 +#: src/Repository/BookingCodes.php:350 msgid "No booking codes could be created because the item of the timeframe could not be found." msgstr "" -#: src/Service/BookingCodes.php:42 +#: src/Service/BookingCodes.php:45 msgid "Error sending booking codes by E-mail for Timeframe " msgstr "" -#: src/Service/BookingRule.php:212 +#: src/Service/BookingRule.php:226 msgid "Forbid simultaneous Bookings" msgstr "" -#: src/Service/BookingRule.php:213 +#: src/Service/BookingRule.php:227 msgid "Users can no longer book two items on the same day." msgstr "" -#: src/Service/BookingRule.php:214 +#: src/Service/BookingRule.php:228 msgid "You can not book more than one item at a time." msgstr "" -#: src/Service/BookingRule.php:219 +#: src/Service/BookingRule.php:233 msgid "Prohibit chain-bookings" msgstr "" -#: src/Service/BookingRule.php:220 +#: src/Service/BookingRule.php:234 msgid "Users can no longer work around the maximum booking limit by chaining two bookings directly after one another." msgstr "" -#: src/Service/BookingRule.php:221 -#: src/Service/BookingRule.php:228 -#: src/Service/BookingRule.php:246 -#: src/Service/BookingRule.php:283 -#: src/Service/BookingRule.php:301 +#: src/Service/BookingRule.php:235 +#: src/Service/BookingRule.php:242 +#: src/Service/BookingRule.php:260 +#: src/Service/BookingRule.php:297 +#: src/Service/BookingRule.php:315 msgid "You have reached your booking limit. Please leave some time in between bookings." msgstr "" -#: src/Service/BookingRule.php:226 -#: src/Service/BookingRule.php:232 +#: src/Service/BookingRule.php:240 +#: src/Service/BookingRule.php:246 msgid "Maximum booked days per week" msgstr "" -#: src/Service/BookingRule.php:227 +#: src/Service/BookingRule.php:241 msgid "Users are only allowed to book a limited amount of days per week." msgstr "" -#: src/Service/BookingRule.php:233 +#: src/Service/BookingRule.php:247 msgid "Number of days each user is allowed to book per week" msgstr "" -#: src/Service/BookingRule.php:237 -#: src/Service/BookingRule.php:292 +#: src/Service/BookingRule.php:251 +#: src/Service/BookingRule.php:306 msgid "At what day of the week should the counter be reset?" msgstr "" -#: src/Service/BookingRule.php:244 -#: src/Service/BookingRule.php:250 +#: src/Service/BookingRule.php:258 +#: src/Service/BookingRule.php:264 msgid "Maximum booked days per month" msgstr "" -#: src/Service/BookingRule.php:245 +#: src/Service/BookingRule.php:259 msgid "Users are only allowed to book a limited amount of days per month." msgstr "" -#: src/Service/BookingRule.php:251 +#: src/Service/BookingRule.php:265 msgid "Number of days each user is allowed to book per month" msgstr "" -#: src/Service/BookingRule.php:255 -#: src/Service/BookingRule.php:310 +#: src/Service/BookingRule.php:269 +#: src/Service/BookingRule.php:324 msgid "At what day of the month should the counter be reset?" msgstr "" -#: src/Service/BookingRule.php:262 +#: src/Service/BookingRule.php:276 msgid "Maximum of bookable days in time period" msgstr "" -#: src/Service/BookingRule.php:263 +#: src/Service/BookingRule.php:277 msgid "Allow x booked days over the period of y days for user." msgstr "" -#: src/Service/BookingRule.php:264 +#: src/Service/BookingRule.php:278 msgid "Booking limit exceeded. " msgstr "" -#: src/Service/BookingRule.php:268 +#: src/Service/BookingRule.php:282 msgid "Allow x booked days" msgstr "" -#: src/Service/BookingRule.php:269 +#: src/Service/BookingRule.php:283 msgid "How many days are free to book in the given period of days" msgstr "" -#: src/Service/BookingRule.php:272 +#: src/Service/BookingRule.php:286 msgid "In the period of y days" msgstr "" -#: src/Service/BookingRule.php:273 +#: src/Service/BookingRule.php:287 msgid "The length of the period for which the booking is limited. This period always lies in the middle, so if you define 30 days, the 15 days before and after will count towards the maximum quota." msgstr "" -#: src/Service/BookingRule.php:281 -#: src/Service/BookingRule.php:287 +#: src/Service/BookingRule.php:295 +#: src/Service/BookingRule.php:301 msgid "Maximum number of bookings per week" msgstr "" -#: src/Service/BookingRule.php:282 +#: src/Service/BookingRule.php:296 msgid "Users are only allowed to make that many bookings per week (Irrespective of their length)." msgstr "" -#: src/Service/BookingRule.php:288 +#: src/Service/BookingRule.php:302 msgid "Number of bookings each user is allowed to make per week" msgstr "" -#: src/Service/BookingRule.php:299 -#: src/Service/BookingRule.php:305 +#: src/Service/BookingRule.php:313 +#: src/Service/BookingRule.php:319 msgid "Maximum number of bookings per month" msgstr "" -#: src/Service/BookingRule.php:300 +#: src/Service/BookingRule.php:314 msgid "Users are only allowed to make that many bookings per month (Irrespective of their length)." msgstr "" -#: src/Service/BookingRule.php:306 +#: src/Service/BookingRule.php:320 msgid "Number of bookings each user is allowed to make per month" msgstr "" -#: src/Service/BookingRule.php:433 +#: src/Service/BookingRule.php:455 msgid "You can only book %1$s days out of %2$s days. Please wait a while in-between bookings." msgstr "" -#: src/Service/BookingRule.php:466 +#: src/Service/BookingRule.php:487 msgid "You can only book %1$s days per week, please try again after %2$s next week." msgstr "" -#: src/Service/BookingRule.php:484 +#: src/Service/BookingRule.php:505 msgid "You are only allowed to have %1$s booking(s) per week, please try again after %2$s next week." msgstr "" -#: src/Service/BookingRule.php:515 +#: src/Service/BookingRule.php:534 msgid "You can only book %1$s days per month, please try again after the %2$s. next month." msgstr "" -#: src/Service/BookingRule.php:530 +#: src/Service/BookingRule.php:549 msgid "You are only allowed %1$s booking(s) per month, please try again after the %2$s. next month." msgstr "" -#: src/Service/BookingRuleApplied.php:59 +#: src/Service/BookingRuleApplied.php:60 msgid "You need to specify a category, if the rule does not apply to all items" msgstr "" @@ -1808,19 +1804,19 @@ msgstr "" msgid "Booking rules: Select parameter has not been properly set." msgstr "" -#: src/Service/BookingRuleApplied.php:169 +#: src/Service/BookingRuleApplied.php:167 msgid "This affects the following bookings:" msgstr "" -#: src/Service/BookingRuleApplied.php:240 +#: src/Service/BookingRuleApplied.php:239 msgid "Booking rules: No rule type specified." msgstr "" -#: src/Service/Cache.php:303 +#: src/Service/Cache.php:305 msgid "Connection status:" msgstr "" -#: src/Service/Cache.php:310 +#: src/Service/Cache.php:312 msgid "Successfully connected to REDIS database!" msgstr "" @@ -1828,28 +1824,28 @@ msgstr "" msgid "REDIS database not enabled" msgstr "" -#: src/Service/Cache.php:347 +#: src/Service/Cache.php:346 msgid "Directory %s is writeable." msgstr "" -#: src/Service/Cache.php:352 +#: src/Service/Cache.php:350 msgid "Directory %s could not be written to." msgstr "" -#: src/Service/Cache.php:365 +#: src/Service/Cache.php:363 msgid "Clear all cache items" msgstr "" -#: src/Service/Holiday.php:30 +#: src/Service/Holiday.php:34 msgid "Year" msgstr "" -#: src/Service/Holiday.php:42 +#: src/Service/Holiday.php:50 msgctxt "territory" msgid "State" msgstr "" -#: src/Service/Holiday.php:56 +#: src/Service/Holiday.php:68 msgid "Load Holidays" msgstr "" @@ -1874,37 +1870,37 @@ msgstr "" msgid "There is already a booking on the new location during the timeframe of booking with ID %s." msgstr "" -#: src/Service/TimeframeExport.php:89 +#: src/Service/TimeframeExport.php:88 msgid "Invalid start date" msgstr "" -#: src/Service/TimeframeExport.php:93 +#: src/Service/TimeframeExport.php:92 msgid "Invalid end date" msgstr "" -#: src/Service/TimeframeExport.php:96 +#: src/Service/TimeframeExport.php:95 msgid "Start date must not be after the end date." msgstr "" -#: src/Service/TimeframeExport.php:164 +#: src/Service/TimeframeExport.php:168 #: src/View/TimeframeExport.php:39 msgid "Export finished" msgstr "" -#: src/Service/TimeframeExport.php:254 +#: src/Service/TimeframeExport.php:261 msgid "Export data is not complete. Please complete the process before trying to export." msgstr "" -#: src/Service/TimeframeExport.php:258 +#: src/Service/TimeframeExport.php:265 msgid "No data was found for the selected time period" msgstr "" -#: src/Service/TimeframeExport.php:263 +#: src/Service/TimeframeExport.php:270 msgid "You need to set an export path to execute the export" msgstr "" -#: src/Service/TimeframeExport.php:364 -msgid "Processed %d of %d bookings" +#: src/Service/TimeframeExport.php:374 +msgid "Processed %1$d of %2$d bookings" msgstr "" #: src/Service/Upgrade.php:138 @@ -1928,157 +1924,157 @@ msgid "" msgstr "" #: src/View/Admin/Filter.php:58 -#: src/Wordpress/CustomPostType/Booking.php:769 -#: src/Wordpress/CustomPostType/Restriction.php:446 -#: src/Wordpress/CustomPostType/Timeframe.php:700 +#: src/Wordpress/CustomPostType/Booking.php:771 +#: src/Wordpress/CustomPostType/Restriction.php:455 +#: src/Wordpress/CustomPostType/Timeframe.php:712 msgid "Start date" msgstr "" #: src/View/Admin/Filter.php:62 -#: src/Wordpress/CustomPostType/Booking.php:786 -#: src/Wordpress/CustomPostType/Restriction.php:456 -#: src/Wordpress/CustomPostType/Timeframe.php:724 +#: src/Wordpress/CustomPostType/Booking.php:788 +#: src/Wordpress/CustomPostType/Restriction.php:465 +#: src/Wordpress/CustomPostType/Timeframe.php:736 msgid "End date" msgstr "" -#: src/View/Booking.php:156 +#: src/View/Booking.php:154 msgid "Details" msgstr "" -#: src/View/Booking.php:162 +#: src/View/Booking.php:160 msgid "Use this link to import the data into your own calendar. Usually you just need to provide the URL as an external source and the calendar will figure it out. Do not try to download this file." msgstr "" -#: src/View/Booking.php:163 +#: src/View/Booking.php:161 msgid "iCalendar Link:" msgstr "" -#: src/View/Booking.php:170 -#: src/View/Booking.php:172 +#: src/View/Booking.php:167 +#: src/View/Booking.php:169 msgid "Not available" msgstr "" -#: src/View/Booking.php:193 +#: src/View/Booking.php:190 #: src/View/MassOperations.php:38 -#: src/Wordpress/CustomPostType/Booking.php:441 -#: src/Wordpress/CustomPostType/Timeframe.php:99 +#: src/Wordpress/CustomPostType/Booking.php:443 +#: src/Wordpress/CustomPostType/Timeframe.php:103 #: templates/shortcode-bookings.php:73 msgid "User" msgstr "" -#: src/View/Booking.php:197 +#: src/View/Booking.php:194 #: src/View/MassOperations.php:42 -#: src/Wordpress/CustomPostType/Booking.php:959 -#: src/Wordpress/CustomPostType/Restriction.php:472 +#: src/Wordpress/CustomPostType/Booking.php:961 +#: src/Wordpress/CustomPostType/Restriction.php:481 msgid "Status" msgstr "" -#: src/View/Booking.php:206 +#: src/View/Booking.php:203 msgid "Code" msgstr "" -#: src/View/Booking.php:538 -#: src/Wordpress/CustomPostType/Booking.php:854 +#: src/View/Booking.php:537 +#: src/Wordpress/CustomPostType/Booking.php:856 msgid "Submit booking" msgstr "" -#: src/View/BookingCodes.php:175 -#: src/View/BookingCodes.php:276 +#: src/View/BookingCodes.php:178 +#: src/View/BookingCodes.php:287 msgid "No location configured for this timeframe" msgstr "" -#: src/View/BookingCodes.php:177 +#: src/View/BookingCodes.php:181 msgid "Unable to send emails. No location email configured, check location" msgstr "" -#: src/View/BookingCodes.php:180 -#: src/View/BookingCodes.php:283 -#: src/View/BookingCodes.php:361 -#: src/View/BookingCodes.php:388 +#: src/View/BookingCodes.php:185 +#: src/View/BookingCodes.php:294 +#: src/View/BookingCodes.php:394 +#: src/View/BookingCodes.php:424 msgid "This timeframe has no booking codes. To generate booking codes you need to save the timeframe." msgstr "" -#: src/View/BookingCodes.php:270 +#: src/View/BookingCodes.php:281 msgid "Send booking codes by email" msgstr "" -#: src/View/BookingCodes.php:279 +#: src/View/BookingCodes.php:290 msgid "Unable to send Emails. No location email configured, check location" msgstr "" -#: src/View/BookingCodes.php:291 +#: src/View/BookingCodes.php:307 msgid "Email booking codes for the entire timeframe" msgstr "" -#: src/View/BookingCodes.php:294 +#: src/View/BookingCodes.php:310 msgid "All codes for the entire timeframe will be emailed to the location email(s), given in bold below." msgstr "" -#: src/View/BookingCodes.php:303 +#: src/View/BookingCodes.php:328 msgid "Email booking codes of current month" msgstr "" -#: src/View/BookingCodes.php:305 +#: src/View/BookingCodes.php:330 msgid "The codes of the current month will be sent to all the location email(s), given in bold below" msgstr "" -#: src/View/BookingCodes.php:314 +#: src/View/BookingCodes.php:348 msgid "Email booking codes of next month" msgstr "" -#: src/View/BookingCodes.php:316 +#: src/View/BookingCodes.php:350 msgid "The codes of the next month will be sent to all the location email(s), given in bold below." msgstr "" -#: src/View/BookingCodes.php:318 +#: src/View/BookingCodes.php:352 msgid "Currently configured location email(s): " msgstr "" -#: src/View/BookingCodes.php:327 +#: src/View/BookingCodes.php:360 msgid "Last booking codes email sent:" msgstr "" -#: src/View/BookingCodes.php:354 +#: src/View/BookingCodes.php:387 msgid "Download booking codes" msgstr "" -#: src/View/BookingCodes.php:359 +#: src/View/BookingCodes.php:392 msgid "Will download all available booking codes for this timeframe. If the timeframe has no end-date, the booking codes for the next %s days will be retrieved." msgstr "" -#: src/View/BookingCodes.php:360 +#: src/View/BookingCodes.php:393 msgid "The file will be exported as tab delimited .txt file so you can choose wether you want to print it, open it in a separate application (like Word, Excel etc.)" msgstr "" -#: src/View/BookingCodes.php:374 +#: src/View/BookingCodes.php:407 msgid "Booking codes list" msgstr "" -#: src/View/BookingCodes.php:382 +#: src/View/BookingCodes.php:419 msgid "Only showing booking codes for the next %s days." msgstr "" -#: src/View/BookingCodes.php:384 +#: src/View/BookingCodes.php:421 msgid "The amount of booking codes shown in the overview can be changed in the settings." msgstr "" -#: src/View/BookingCodes.php:473 +#: src/View/BookingCodes.php:510 msgid "Unable to retrieve booking codes" msgstr "" -#: src/View/BookingCodes.php:474 +#: src/View/BookingCodes.php:511 msgid "Missing ID of timeframe post" msgstr "" -#: src/View/BookingCodes.php:496 +#: src/View/BookingCodes.php:537 msgid "Error sending booking codes" msgstr "" -#: src/View/BookingCodes.php:515 +#: src/View/BookingCodes.php:555 msgid "An unknown error occured" msgstr "" -#: src/View/BookingCodes.php:516 +#: src/View/BookingCodes.php:556 msgid "Email booking codes" msgstr "" @@ -2087,40 +2083,40 @@ msgid "No items found." msgstr "" #: src/View/Calendar.php:225 -#: src/Wordpress/CustomPostType/Booking.php:442 -#: src/Wordpress/CustomPostType/Booking.php:751 -#: src/Wordpress/CustomPostType/Booking.php:975 -#: src/Wordpress/CustomPostType/Item.php:115 +#: src/Wordpress/CustomPostType/Booking.php:444 +#: src/Wordpress/CustomPostType/Booking.php:753 +#: src/Wordpress/CustomPostType/Booking.php:977 +#: src/Wordpress/CustomPostType/Item.php:117 #: src/Wordpress/CustomPostType/Restriction.php:54 -#: src/Wordpress/CustomPostType/Restriction.php:434 -#: src/Wordpress/CustomPostType/Timeframe.php:101 +#: src/Wordpress/CustomPostType/Restriction.php:443 +#: src/Wordpress/CustomPostType/Timeframe.php:105 #: templates/shortcode-bookings.php:72 msgid "Item" msgstr "" #: src/View/Calendar.php:226 -#: src/Wordpress/CustomPostType/Booking.php:443 -#: src/Wordpress/CustomPostType/Booking.php:757 -#: src/Wordpress/CustomPostType/Booking.php:971 -#: src/Wordpress/CustomPostType/Location.php:122 +#: src/Wordpress/CustomPostType/Booking.php:445 +#: src/Wordpress/CustomPostType/Booking.php:759 +#: src/Wordpress/CustomPostType/Booking.php:973 +#: src/Wordpress/CustomPostType/Location.php:123 #: src/Wordpress/CustomPostType/Restriction.php:55 -#: src/Wordpress/CustomPostType/Restriction.php:428 -#: src/Wordpress/CustomPostType/Timeframe.php:102 -#: src/Wordpress/CustomPostType/Timeframe.php:494 +#: src/Wordpress/CustomPostType/Restriction.php:437 +#: src/Wordpress/CustomPostType/Timeframe.php:106 +#: src/Wordpress/CustomPostType/Timeframe.php:503 #: templates/shortcode-bookings.php:74 msgid "Location" msgstr "" -#: src/View/Dashboard.php:41 -#: src/View/Dashboard.php:80 +#: src/View/Dashboard.php:48 +#: src/View/Dashboard.php:94 msgid "at" msgstr "" -#: src/View/Item.php:124 +#: src/View/Item.php:123 msgid "No bookable items found." msgstr "" -#: src/View/Location.php:127 +#: src/View/Location.php:128 msgid "No locations found." msgstr "" @@ -2165,18 +2161,18 @@ msgid "New location name" msgstr "" #: src/View/MassOperations.php:94 -#: src/View/Migration.php:93 +#: src/View/Migration.php:98 msgid "migration in process .. please wait ..." msgstr "" #: src/View/MassOperations.php:99 -#: src/View/Migration.php:53 -#: src/View/Migration.php:98 +#: src/View/Migration.php:57 +#: src/View/Migration.php:103 msgid "Migration finished" msgstr "" #: src/View/MassOperations.php:104 -#: src/View/Migration.php:103 +#: src/View/Migration.php:108 msgid "Migration failed" msgstr "" @@ -2184,71 +2180,71 @@ msgstr "" msgid "We could not detect a version of an older CommonsBooking Installation (Version 0.X)." msgstr "" -#: src/View/Migration.php:31 +#: src/View/Migration.php:33 msgid "Found a version of an older CommonsBooking Installation (Version 0.X). You can migrate." msgstr "" -#: src/View/Migration.php:37 +#: src/View/Migration.php:41 msgid " Locations updated/saved" msgstr "" -#: src/View/Migration.php:38 +#: src/View/Migration.php:42 msgid " Items updated/saved" msgstr "" -#: src/View/Migration.php:39 +#: src/View/Migration.php:43 msgid " Timeframes updated/saved" msgstr "" -#: src/View/Migration.php:40 +#: src/View/Migration.php:44 msgid " Bookings updated/saved" msgstr "" -#: src/View/Migration.php:41 +#: src/View/Migration.php:45 msgid " Booking Codes updated/saved" msgstr "" -#: src/View/Migration.php:42 +#: src/View/Migration.php:46 msgid " Terms & Urls updated/saved" msgstr "" -#: src/View/Migration.php:43 +#: src/View/Migration.php:47 msgid " Taxonomies updated/saved" msgstr "" -#: src/View/Migration.php:44 +#: src/View/Migration.php:48 msgid " Options updated/saved" msgstr "" -#: src/View/Migration.php:48 +#: src/View/Migration.php:52 msgid "migration in process .. please wait ...
      This could take several minutes. Do not close this browser tab" msgstr "" -#: src/View/Migration.php:65 +#: src/View/Migration.php:69 msgid "Retrieve location geo coordinates." msgstr "" -#: src/View/Migration.php:67 +#: src/View/Migration.php:71 msgid "If this option is enabled, CommonsBooking will try to derive the matching geo-coordinates from the address data of the locations during import. We use an interface to a GeoCoder service (Nominatim) for this task. This service allows only one query per second, so the runtime of the migration is increased by 1 second per location. The geo-coordinates are needed to use the location map integrated in CommonsBooking." msgstr "" -#: src/View/Migration.php:120 +#: src/View/Migration.php:127 msgid "upgrade in process .. please wait ..." msgstr "" -#: src/View/Migration.php:125 +#: src/View/Migration.php:132 msgid "Upgrade finished" msgstr "" -#: src/View/Migration.php:129 +#: src/View/Migration.php:136 msgid "Start Upgrade" msgstr "" -#: src/View/Restriction.php:35 +#: src/View/Restriction.php:34 msgid "Send" msgstr "" -#: src/View/Restriction.php:43 +#: src/View/Restriction.php:42 msgid "Sent" msgstr "" @@ -2268,176 +2264,176 @@ msgstr "" msgid "Download Export" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:107 +#: src/Wordpress/CustomPostType/Booking.php:106 msgid "Admin-Booking" msgstr "" #. translators: $s = id of the item -#: src/Wordpress/CustomPostType/Booking.php:256 +#: src/Wordpress/CustomPostType/Booking.php:258 msgid "Item does not exist. (%s)" msgstr "" #. translators: $s = id of the location -#: src/Wordpress/CustomPostType/Booking.php:260 +#: src/Wordpress/CustomPostType/Booking.php:262 msgid "Location does not exist. (%s)" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:264 +#: src/Wordpress/CustomPostType/Booking.php:266 msgid "Start- and/or end-date is missing." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:269 +#: src/Wordpress/CustomPostType/Booking.php:271 msgid "Your reservation has expired, please try to book again" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:295 +#: src/Wordpress/CustomPostType/Booking.php:297 msgid "Booking canceled." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:311 +#: src/Wordpress/CustomPostType/Booking.php:313 msgid "There is already a booking in this time-range. This notice may also appear if there is an unconfirmed booking in the requested period. Unconfirmed bookings are deleted after about 10 minutes. Please try again in a few minutes." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:319 +#: src/Wordpress/CustomPostType/Booking.php:321 msgid "status changed by admin user via frontend. New status: " msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:326 -#: src/Wordpress/CustomPostType/Booking.php:518 -#: src/Wordpress/CustomPostType/Booking.php:702 -#: src/Wordpress/CustomPostType/Timeframe.php:135 +#: src/Wordpress/CustomPostType/Booking.php:328 +#: src/Wordpress/CustomPostType/Booking.php:520 +#: src/Wordpress/CustomPostType/Booking.php:704 +#: src/Wordpress/CustomPostType/Timeframe.php:138 msgid "Booking" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:370 +#: src/Wordpress/CustomPostType/Booking.php:372 msgid "There was an error while saving the booking. Please try again. Thrown error:" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:387 +#: src/Wordpress/CustomPostType/Booking.php:389 msgid "There was an error while saving the booking. Please try again. Resulting WP_ERROR: " msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:444 +#: src/Wordpress/CustomPostType/Booking.php:446 msgid "Bookingdate" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:445 +#: src/Wordpress/CustomPostType/Booking.php:447 #: src/Wordpress/CustomPostType/Restriction.php:56 -#: src/Wordpress/CustomPostType/Timeframe.php:103 -#: src/Wordpress/CustomPostType/Timeframe.php:766 +#: src/Wordpress/CustomPostType/Timeframe.php:107 +#: src/Wordpress/CustomPostType/Timeframe.php:788 msgid "Start Date" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:446 +#: src/Wordpress/CustomPostType/Booking.php:448 #: src/Wordpress/CustomPostType/Restriction.php:57 -#: src/Wordpress/CustomPostType/Timeframe.php:104 +#: src/Wordpress/CustomPostType/Timeframe.php:108 msgid "End Date" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:447 +#: src/Wordpress/CustomPostType/Booking.php:449 msgid "Booking Status" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:448 -#: src/Wordpress/CustomPostType/Booking.php:967 -#: src/Wordpress/CustomPostType/Timeframe.php:479 +#: src/Wordpress/CustomPostType/Booking.php:450 +#: src/Wordpress/CustomPostType/Booking.php:969 +#: src/Wordpress/CustomPostType/Timeframe.php:488 msgid "Comment" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:517 +#: src/Wordpress/CustomPostType/Booking.php:519 #: templates/dashboard-index.php:45 msgid "Bookings" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:519 -#: src/Wordpress/CustomPostType/Item.php:116 -#: src/Wordpress/CustomPostType/Location.php:123 -#: src/Wordpress/CustomPostType/Restriction.php:310 -#: src/Wordpress/CustomPostType/Timeframe.php:1146 +#: src/Wordpress/CustomPostType/Booking.php:521 +#: src/Wordpress/CustomPostType/Item.php:118 +#: src/Wordpress/CustomPostType/Location.php:124 +#: src/Wordpress/CustomPostType/Restriction.php:313 +#: src/Wordpress/CustomPostType/Timeframe.php:1180 msgid "Add new" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:520 #: src/Wordpress/CustomPostType/Booking.php:522 +#: src/Wordpress/CustomPostType/Booking.php:524 msgid "Add new booking" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:521 -#: src/Wordpress/CustomPostType/Booking.php:733 +#: src/Wordpress/CustomPostType/Booking.php:523 +#: src/Wordpress/CustomPostType/Booking.php:735 msgid "Edit booking" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:523 +#: src/Wordpress/CustomPostType/Booking.php:525 msgid "Show booking" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:524 +#: src/Wordpress/CustomPostType/Booking.php:526 msgid "Show bookings" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:525 +#: src/Wordpress/CustomPostType/Booking.php:527 msgid "Search bookings" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:526 +#: src/Wordpress/CustomPostType/Booking.php:528 msgid "Bookings not found" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:527 +#: src/Wordpress/CustomPostType/Booking.php:529 msgid "No bookings found in trash" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:528 +#: src/Wordpress/CustomPostType/Booking.php:530 msgid "Parent bookings:" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:529 +#: src/Wordpress/CustomPostType/Booking.php:531 msgid "All bookings" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:530 -#: src/Wordpress/CustomPostType/Timeframe.php:1157 +#: src/Wordpress/CustomPostType/Booking.php:532 +#: src/Wordpress/CustomPostType/Timeframe.php:1191 msgid "Timeframe archive" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:531 -#: src/Wordpress/CustomPostType/Timeframe.php:1158 +#: src/Wordpress/CustomPostType/Booking.php:533 +#: src/Wordpress/CustomPostType/Timeframe.php:1192 msgid "Timeframe attributes" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:532 +#: src/Wordpress/CustomPostType/Booking.php:534 msgid "Add to booking" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:533 +#: src/Wordpress/CustomPostType/Booking.php:535 msgid "Added to booking" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:534 -#: src/Wordpress/CustomPostType/Timeframe.php:1161 +#: src/Wordpress/CustomPostType/Booking.php:536 +#: src/Wordpress/CustomPostType/Timeframe.php:1195 msgid "Timeframe image" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:535 +#: src/Wordpress/CustomPostType/Booking.php:537 msgid "set booking image" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:536 +#: src/Wordpress/CustomPostType/Booking.php:538 msgid "remove booking image" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:537 +#: src/Wordpress/CustomPostType/Booking.php:539 msgid "use as booking image" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:538 -#: src/Wordpress/CustomPostType/Timeframe.php:1144 -#: src/Wordpress/CustomPostType/Timeframe.php:1165 +#: src/Wordpress/CustomPostType/Booking.php:540 +#: src/Wordpress/CustomPostType/Timeframe.php:1178 +#: src/Wordpress/CustomPostType/Timeframe.php:1199 #: templates/dashboard-index.php:37 msgid "Timeframes" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:735 +#: src/Wordpress/CustomPostType/Booking.php:737 msgid "" "

      Notice

      In this view, you as an admin can create or modify existing bookings. Please use it with caution.
      \n" "\t\t\t\t

        \n" @@ -2449,72 +2445,72 @@ msgid "" "\t\t\t\t" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:763 +#: src/Wordpress/CustomPostType/Booking.php:765 msgid "Book full day" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:766 +#: src/Wordpress/CustomPostType/Booking.php:768 msgid "The booking should apply to the entire day(s)" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:770 +#: src/Wordpress/CustomPostType/Booking.php:772 msgid "Set the start date. You must set the time to 00:00 if you want to book the full day " msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:787 +#: src/Wordpress/CustomPostType/Booking.php:789 msgid "Set the end date. You must set time to 23:59 if you want to book the full day" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:803 +#: src/Wordpress/CustomPostType/Booking.php:805 #: templates/booking-single.php:59 msgid "Booking Code" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:806 +#: src/Wordpress/CustomPostType/Booking.php:808 msgid "Valid booking code will be automatically retrieved for bookings that apply to the full day." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:809 +#: src/Wordpress/CustomPostType/Booking.php:811 msgid "Booking User" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:815 +#: src/Wordpress/CustomPostType/Booking.php:817 msgid "" "Here you must select the user for whom the booking is made.
        \n" " If the booking was made by a user via frontend booking process, the user will be shown in this field.\n" "
        Notice:The user will receive a booking confirmation as soon as the booking is submitted." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:824 +#: src/Wordpress/CustomPostType/Booking.php:826 msgid "Admin Booking User" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:835 +#: src/Wordpress/CustomPostType/Booking.php:837 msgid "This is the admin user who created or modified this booking." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:842 +#: src/Wordpress/CustomPostType/Booking.php:844 msgid "External comment" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:843 +#: src/Wordpress/CustomPostType/Booking.php:845 msgid "This comment can be seen by users in booking details. It can be set by users during the booking confirmation process if comments are enabled in settings." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:848 -#: templates/booking-single.php:130 +#: src/Wordpress/CustomPostType/Booking.php:850 +#: templates/booking-single.php:131 msgid "Internal comment" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:849 +#: src/Wordpress/CustomPostType/Booking.php:851 msgid "This internal comment can only be seen in the backend by privileged users like admins or cb-managers" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:855 +#: src/Wordpress/CustomPostType/Booking.php:857 msgid "This will create the specified booking and send out the booking confirmation email." msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:877 +#: src/Wordpress/CustomPostType/Booking.php:879 msgid "" "Bookings should be created via frontend booking calendar.
        \n" "\t\tAs an admin you can create bookings via this admin interface. Please be aware that admin bookings are not validated\n" @@ -2524,838 +2520,838 @@ msgid "" "\t\tSee here How to display the booking list" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:947 +#: src/Wordpress/CustomPostType/Booking.php:949 msgid "Booking start" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:951 +#: src/Wordpress/CustomPostType/Booking.php:953 msgid "Booking end" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:955 +#: src/Wordpress/CustomPostType/Booking.php:957 msgid "Time of booking" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:963 +#: src/Wordpress/CustomPostType/Booking.php:965 msgid "Booking code" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:979 +#: src/Wordpress/CustomPostType/Booking.php:981 msgid "Time of cancellation" msgstr "" -#: src/Wordpress/CustomPostType/Booking.php:983 +#: src/Wordpress/CustomPostType/Booking.php:985 msgid "Admin booking by" msgstr "" -#: src/Wordpress/CustomPostType/CustomPostType.php:317 +#: src/Wordpress/CustomPostType/CustomPostType.php:331 msgid "Filter By Category " msgstr "" -#: src/Wordpress/CustomPostType/Item.php:114 -#: src/Wordpress/CustomPostType/Item.php:135 +#: src/Wordpress/CustomPostType/Item.php:116 +#: src/Wordpress/CustomPostType/Item.php:137 #: templates/dashboard-index.php:33 msgid "Items" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:117 #: src/Wordpress/CustomPostType/Item.php:119 +#: src/Wordpress/CustomPostType/Item.php:121 msgid "Add new item" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:118 +#: src/Wordpress/CustomPostType/Item.php:120 msgid "Edit item" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:120 +#: src/Wordpress/CustomPostType/Item.php:122 msgid "Show item" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:121 +#: src/Wordpress/CustomPostType/Item.php:123 msgid "Show items" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:122 +#: src/Wordpress/CustomPostType/Item.php:124 msgid "Search items" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:123 +#: src/Wordpress/CustomPostType/Item.php:125 msgid "items not found" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:124 +#: src/Wordpress/CustomPostType/Item.php:126 msgid "No items found in trash" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:125 +#: src/Wordpress/CustomPostType/Item.php:127 msgid "Parent items:" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:126 +#: src/Wordpress/CustomPostType/Item.php:128 msgid "All items" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:127 +#: src/Wordpress/CustomPostType/Item.php:129 msgid "Item archive" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:128 +#: src/Wordpress/CustomPostType/Item.php:130 msgid "Item attributes" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:129 +#: src/Wordpress/CustomPostType/Item.php:131 msgid "Add to item" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:130 +#: src/Wordpress/CustomPostType/Item.php:132 msgid "Added to item" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:131 +#: src/Wordpress/CustomPostType/Item.php:133 msgid "Item image" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:132 +#: src/Wordpress/CustomPostType/Item.php:134 msgid "set item image" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:133 +#: src/Wordpress/CustomPostType/Item.php:135 msgid "remove item image" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:134 +#: src/Wordpress/CustomPostType/Item.php:136 msgid "use as item image" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:231 +#: src/Wordpress/CustomPostType/Item.php:233 msgid "Item Info" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:249 +#: src/Wordpress/CustomPostType/Item.php:252 msgid "Item Admin(s)" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:250 +#: src/Wordpress/CustomPostType/Item.php:253 msgid "choose one or more users to give them the permisssion to edit and manage this specific item. Only users with the role cb_manager can be selected here" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:255 +#: src/Wordpress/CustomPostType/Item.php:258 msgid "Select item admins." msgstr "" -#: src/Wordpress/CustomPostType/Item.php:261 +#: src/Wordpress/CustomPostType/Item.php:266 msgid "Item maintainer email" msgstr "" -#: src/Wordpress/CustomPostType/Item.php:262 +#: src/Wordpress/CustomPostType/Item.php:267 msgid "Email addresses to which notifications about a change of item status (restriction, breakdown) shall be sent. You can enter multiple addresses separated by commas." msgstr "" -#: src/Wordpress/CustomPostType/Item.php:277 +#: src/Wordpress/CustomPostType/Item.php:286 msgid "Item Meta-Data" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:121 -#: src/Wordpress/CustomPostType/Location.php:142 +#: src/Wordpress/CustomPostType/Location.php:122 +#: src/Wordpress/CustomPostType/Location.php:143 #: templates/dashboard-index.php:35 msgid "Locations" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:124 -#: src/Wordpress/CustomPostType/Location.php:126 +#: src/Wordpress/CustomPostType/Location.php:125 +#: src/Wordpress/CustomPostType/Location.php:127 msgid "Add new location" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:125 +#: src/Wordpress/CustomPostType/Location.php:126 msgid "Edit location" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:127 +#: src/Wordpress/CustomPostType/Location.php:128 msgid "Show location" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:128 +#: src/Wordpress/CustomPostType/Location.php:129 msgid "Show locations" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:129 +#: src/Wordpress/CustomPostType/Location.php:130 msgid "Search locations" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:130 +#: src/Wordpress/CustomPostType/Location.php:131 msgid "location not found" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:131 +#: src/Wordpress/CustomPostType/Location.php:132 msgid "No locations found in trash" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:132 +#: src/Wordpress/CustomPostType/Location.php:133 msgid "Parent location:" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:133 +#: src/Wordpress/CustomPostType/Location.php:134 msgid "All locations" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:134 +#: src/Wordpress/CustomPostType/Location.php:135 msgid "Location archive" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:135 +#: src/Wordpress/CustomPostType/Location.php:136 msgid "Location attributes" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:136 +#: src/Wordpress/CustomPostType/Location.php:137 msgid "Add to location" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:137 +#: src/Wordpress/CustomPostType/Location.php:138 msgid "Added to location" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:138 +#: src/Wordpress/CustomPostType/Location.php:139 msgid "Location image" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:139 +#: src/Wordpress/CustomPostType/Location.php:140 msgid "set location image" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:140 +#: src/Wordpress/CustomPostType/Location.php:141 msgid "remove location image" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:141 +#: src/Wordpress/CustomPostType/Location.php:142 msgid "use as location image" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:228 +#: src/Wordpress/CustomPostType/Location.php:232 msgid "Street / No." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:239 +#: src/Wordpress/CustomPostType/Location.php:245 msgid "Postcode" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:250 +#: src/Wordpress/CustomPostType/Location.php:258 msgid "City" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:261 +#: src/Wordpress/CustomPostType/Location.php:271 msgid "Country" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:270 +#: src/Wordpress/CustomPostType/Location.php:282 msgid "Set / Update GPS and map" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:281 +#: src/Wordpress/CustomPostType/Location.php:294 msgid "Latitude" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:282 +#: src/Wordpress/CustomPostType/Location.php:295 msgid "The latitude is calculated automatically when you click the \"set / update GPS\" button after entering the street, postal code and city." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:290 +#: src/Wordpress/CustomPostType/Location.php:305 msgid "Longitude" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:291 +#: src/Wordpress/CustomPostType/Location.php:306 msgid "The longitude is calculated automatically when you click the \"set / update GPS\" button after entering the street, postal code and city." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:299 +#: src/Wordpress/CustomPostType/Location.php:316 msgid "Position" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:308 +#: src/Wordpress/CustomPostType/Location.php:327 msgid "Show location map on item view" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:309 +#: src/Wordpress/CustomPostType/Location.php:328 msgid "If enabled, a map showing the location will be displayed on the location details page." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:318 +#: src/Wordpress/CustomPostType/Location.php:339 msgid "General Location information" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:327 +#: src/Wordpress/CustomPostType/Location.php:350 msgid "Location email" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:328 +#: src/Wordpress/CustomPostType/Location.php:351 msgid "Email addresses of the owner of the station. Can be reminded about bookings / cancellations and will receive the booking codes (when configured in the timeframe). You can enter multiple addresses separated by commas." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:341 +#: src/Wordpress/CustomPostType/Location.php:368 msgid "Send copy of bookings / cancellations to location email" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:342 +#: src/Wordpress/CustomPostType/Location.php:369 msgid "If enabled, the location email will receive a copy of all booking and cancellation notifications." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:350 +#: src/Wordpress/CustomPostType/Location.php:379 #: templates/booking-single.php:86 #: templates/location-single-meta.php:53 msgid "Pickup instructions" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:351 +#: src/Wordpress/CustomPostType/Location.php:380 msgid "Type in information about the pickup process (e.g. detailed route description, opening hours, etc.). This will be shown to user in booking process and booking confirmation mail" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:361 +#: src/Wordpress/CustomPostType/Location.php:394 msgid "Location contact information" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:362 +#: src/Wordpress/CustomPostType/Location.php:395 msgid "information about how to contact the location (e.g. contact person, phone number, e-mail etc.). This will be shown to user in booking process and booking confirmation mail" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:378 +#: src/Wordpress/CustomPostType/Location.php:415 msgid "Location Admin(s)" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:379 +#: src/Wordpress/CustomPostType/Location.php:416 msgid "choose one or more users to give them the permisssion to edit and manage this specific location. Only users with the role CommonsBooking Manager can be selected here." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:385 +#: src/Wordpress/CustomPostType/Location.php:424 msgid "Select location admins." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:391 +#: src/Wordpress/CustomPostType/Location.php:432 msgid "Use global location settings" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:392 +#: src/Wordpress/CustomPostType/Location.php:433 msgid "If selected, the global location settings (under the \"General\" tab) will be used for this location. If not selected, the settings below will be used." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:403 +#: src/Wordpress/CustomPostType/Location.php:446 msgid "Receive booking start reminder" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:404 +#: src/Wordpress/CustomPostType/Location.php:447 msgid "If selected, this location receives reminder emails of bookings starting soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:410 +#: src/Wordpress/CustomPostType/Location.php:455 msgid "Receive booking end reminder" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:411 +#: src/Wordpress/CustomPostType/Location.php:456 msgid "If selected, this location receives reminder emails of bookings ending soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:423 +#: src/Wordpress/CustomPostType/Location.php:470 msgid "Location Meta-Data" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:454 +#: src/Wordpress/CustomPostType/Location.php:501 msgid "Allow locked day overbooking" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:455 +#: src/Wordpress/CustomPostType/Location.php:502 msgid "If selected, all not selected days in any bookable timeframe that is connected to this location can be overbooked. Read the documentation Create Locations for more information." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:460 +#: src/Wordpress/CustomPostType/Location.php:507 msgid "Count locked days when overbooking" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:461 +#: src/Wordpress/CustomPostType/Location.php:508 msgid "If selected, days that are overbooked will be counted towards the maximum number of bookable days. If this option is disabled, locked days that are overbooked will allow for bookings that are longer than the maximum number of bookable days configured for the timeframe." msgstr "" -#: src/Wordpress/CustomPostType/Location.php:466 +#: src/Wordpress/CustomPostType/Location.php:513 msgid "Count connected locked days as one" msgstr "" -#: src/Wordpress/CustomPostType/Location.php:467 +#: src/Wordpress/CustomPostType/Location.php:514 msgid "Here you can specify, if a connected span of locked days should be counted individually or just use up x amount of the maximum quota the user is allowed to book. If you set this field to 0, every day will be counted individually. If you set this field to 1, all overbooked days, no matter how many, will always count for 1 day. If you set this to 2, they will count a maximum of two days and so on." msgstr "" -#: src/Wordpress/CustomPostType/Map.php:45 +#: src/Wordpress/CustomPostType/Map.php:44 msgid "Map settings" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:59 +#: src/Wordpress/CustomPostType/Map.php:57 msgid "These settings help you to configure the usage and appearance of Commons Booking Map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:70 +#: src/Wordpress/CustomPostType/Map.php:68 msgid "Presentation" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:76 +#: src/Wordpress/CustomPostType/Map.php:74 msgid "base map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:77 +#: src/Wordpress/CustomPostType/Map.php:75 msgid "the base map defines the rendering style of the map tiles" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:81 +#: src/Wordpress/CustomPostType/Map.php:79 msgid "OSM - mapnik" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:82 +#: src/Wordpress/CustomPostType/Map.php:80 msgid "OSM - german style" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:92 +#: src/Wordpress/CustomPostType/Map.php:90 msgid "show scale" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:93 +#: src/Wordpress/CustomPostType/Map.php:91 msgid "show the current scale in the bottom left corner of the map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:98 +#: src/Wordpress/CustomPostType/Map.php:96 msgid "map height" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:99 +#: src/Wordpress/CustomPostType/Map.php:97 msgid "the height the map is rendered with - the width is the same as of the parent element" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:109 +#: src/Wordpress/CustomPostType/Map.php:107 msgid "no locations message" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:110 +#: src/Wordpress/CustomPostType/Map.php:108 msgid "in case a user filters locations and gets no result, a message is shown - here the text can be customized" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:113 +#: src/Wordpress/CustomPostType/Map.php:111 msgid "No locations found" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:116 +#: src/Wordpress/CustomPostType/Map.php:114 msgid "enable data export" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:117 +#: src/Wordpress/CustomPostType/Map.php:115 msgid "activate to enable a button that allows the export of map data (geojson format)" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:123 +#: src/Wordpress/CustomPostType/Map.php:121 msgid "Zoom" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:129 +#: src/Wordpress/CustomPostType/Map.php:127 msgid "min. zoom level" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:130 +#: src/Wordpress/CustomPostType/Map.php:128 msgid "the minimal zoom level a user can choose" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:142 +#: src/Wordpress/CustomPostType/Map.php:140 msgid "max. zoom level" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:143 +#: src/Wordpress/CustomPostType/Map.php:141 msgid "the maximal zoom level a user can choose" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:155 +#: src/Wordpress/CustomPostType/Map.php:153 msgid "start zoom level" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:156 +#: src/Wordpress/CustomPostType/Map.php:154 msgid "the zoom level that will be set when the map is loaded" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:168 +#: src/Wordpress/CustomPostType/Map.php:166 msgid "enable scroll wheel zoom" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:169 +#: src/Wordpress/CustomPostType/Map.php:167 msgid "when activated users can zoom the map using the scroll wheel" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:177 +#: src/Wordpress/CustomPostType/Map.php:175 msgid "Positioning" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:183 +#: src/Wordpress/CustomPostType/Map.php:181 msgid "start latitude" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:184 +#: src/Wordpress/CustomPostType/Map.php:182 msgid "the latitude of the map center when the map is loaded" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:190 +#: src/Wordpress/CustomPostType/Map.php:188 msgid "start longitude" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:191 +#: src/Wordpress/CustomPostType/Map.php:189 msgid "the longitude of the map center when the map is loaded" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:197 +#: src/Wordpress/CustomPostType/Map.php:195 msgid "initial adjustment to marker bounds" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:198 +#: src/Wordpress/CustomPostType/Map.php:196 msgid "adjust map section to bounds of shown markers automatically when map is loaded" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:204 +#: src/Wordpress/CustomPostType/Map.php:202 msgid "adjustment to marker bounds on filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:205 +#: src/Wordpress/CustomPostType/Map.php:203 msgid "adjust map section to bounds of shown markers automatically when filtered by users" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:213 +#: src/Wordpress/CustomPostType/Map.php:211 msgid "Marker Tooltip" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:219 +#: src/Wordpress/CustomPostType/Map.php:217 msgid "Show marker tooltip permanently" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:220 +#: src/Wordpress/CustomPostType/Map.php:218 msgid "activate to show the marker tooltips permanently" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:227 +#: src/Wordpress/CustomPostType/Map.php:225 msgid "Marker Popup" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:233 +#: src/Wordpress/CustomPostType/Map.php:231 msgid "show item availability" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:234 +#: src/Wordpress/CustomPostType/Map.php:232 msgid "activate to show the item availability in the marker popup" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:239 +#: src/Wordpress/CustomPostType/Map.php:237 msgid "Max. available days in popup" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:240 +#: src/Wordpress/CustomPostType/Map.php:238 msgid "Set how many days are displayed on the popup (starting from today)" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:251 +#: src/Wordpress/CustomPostType/Map.php:249 msgid "Maximum days to choose in map availabilty filter " msgstr "" -#: src/Wordpress/CustomPostType/Map.php:252 +#: src/Wordpress/CustomPostType/Map.php:250 msgid "Notice: Defines the maximun days a user can choose in the availabilty filter in frontend map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:264 +#: src/Wordpress/CustomPostType/Map.php:262 msgid "Custom Marker" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:270 +#: src/Wordpress/CustomPostType/Map.php:268 msgid "image file" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:271 -#: src/Wordpress/CustomPostType/Map.php:348 -#: src/Wordpress/CustomPostType/Map.php:404 +#: src/Wordpress/CustomPostType/Map.php:269 +#: src/Wordpress/CustomPostType/Map.php:346 +#: src/Wordpress/CustomPostType/Map.php:402 msgid "the default marker icon can be replaced by a custom image" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:284 -#: src/Wordpress/CustomPostType/Map.php:361 -#: src/Wordpress/CustomPostType/Map.php:417 +#: src/Wordpress/CustomPostType/Map.php:282 +#: src/Wordpress/CustomPostType/Map.php:359 +#: src/Wordpress/CustomPostType/Map.php:415 msgid "icon width" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:285 -#: src/Wordpress/CustomPostType/Map.php:296 -#: src/Wordpress/CustomPostType/Map.php:362 -#: src/Wordpress/CustomPostType/Map.php:373 -#: src/Wordpress/CustomPostType/Map.php:418 -#: src/Wordpress/CustomPostType/Map.php:429 +#: src/Wordpress/CustomPostType/Map.php:283 +#: src/Wordpress/CustomPostType/Map.php:294 +#: src/Wordpress/CustomPostType/Map.php:360 +#: src/Wordpress/CustomPostType/Map.php:371 +#: src/Wordpress/CustomPostType/Map.php:416 +#: src/Wordpress/CustomPostType/Map.php:427 msgid "the size of the custom marker icon image as it is shown on the map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:295 -#: src/Wordpress/CustomPostType/Map.php:372 -#: src/Wordpress/CustomPostType/Map.php:428 +#: src/Wordpress/CustomPostType/Map.php:293 +#: src/Wordpress/CustomPostType/Map.php:370 +#: src/Wordpress/CustomPostType/Map.php:426 msgid "icon height" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:306 -#: src/Wordpress/CustomPostType/Map.php:316 -#: src/Wordpress/CustomPostType/Map.php:439 -#: src/Wordpress/CustomPostType/Map.php:449 +#: src/Wordpress/CustomPostType/Map.php:304 +#: src/Wordpress/CustomPostType/Map.php:314 +#: src/Wordpress/CustomPostType/Map.php:437 +#: src/Wordpress/CustomPostType/Map.php:447 msgid "anchor point" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:307 -#: src/Wordpress/CustomPostType/Map.php:317 -#: src/Wordpress/CustomPostType/Map.php:440 -#: src/Wordpress/CustomPostType/Map.php:450 +#: src/Wordpress/CustomPostType/Map.php:305 +#: src/Wordpress/CustomPostType/Map.php:315 +#: src/Wordpress/CustomPostType/Map.php:438 +#: src/Wordpress/CustomPostType/Map.php:448 msgid "the position of the anchor point of the icon image, seen from the left top corner of the icon, often it is half of the width and full height of the icon size - this point is used to place the marker on the geo coordinates" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:328 +#: src/Wordpress/CustomPostType/Map.php:326 msgid "Cluster" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:334 +#: src/Wordpress/CustomPostType/Map.php:332 msgid "max. cluster radius" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:335 +#: src/Wordpress/CustomPostType/Map.php:333 msgid "combine markers to a cluster within given radius - 0 for deactivation" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:347 +#: src/Wordpress/CustomPostType/Map.php:345 msgid "Custom Cluster Marker" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:385 +#: src/Wordpress/CustomPostType/Map.php:383 msgid "Appearance by Item Status" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:391 +#: src/Wordpress/CustomPostType/Map.php:389 msgid "appearance" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:392 +#: src/Wordpress/CustomPostType/Map.php:390 msgid "how locations with items that are in draft status should be handled" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:396 +#: src/Wordpress/CustomPostType/Map.php:394 msgid "don't show drafts" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:397 +#: src/Wordpress/CustomPostType/Map.php:395 msgid "show only drafts" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:398 +#: src/Wordpress/CustomPostType/Map.php:396 msgid "show all together" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:403 +#: src/Wordpress/CustomPostType/Map.php:401 msgid "Custom Item Draft Marker" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:461 +#: src/Wordpress/CustomPostType/Map.php:459 msgid "Filter for Users" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:467 +#: src/Wordpress/CustomPostType/Map.php:465 msgid "show location distance filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:468 +#: src/Wordpress/CustomPostType/Map.php:466 msgid "activate to show the location distance filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:473 +#: src/Wordpress/CustomPostType/Map.php:471 msgid "label for location distance filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:474 +#: src/Wordpress/CustomPostType/Map.php:472 msgid "alternative label for the location distance filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:482 -#: src/Wordpress/CustomPostType/Map.php:488 +#: src/Wordpress/CustomPostType/Map.php:480 +#: src/Wordpress/CustomPostType/Map.php:486 msgid "address search bounds - left bottom" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:482 -#: src/Wordpress/CustomPostType/Map.php:494 +#: src/Wordpress/CustomPostType/Map.php:480 +#: src/Wordpress/CustomPostType/Map.php:492 msgid "longitude" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:483 +#: src/Wordpress/CustomPostType/Map.php:481 msgid "defines the bounds of the address search - set the longitude of the left bottom corner of the bounding box" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:488 -#: src/Wordpress/CustomPostType/Map.php:500 +#: src/Wordpress/CustomPostType/Map.php:486 +#: src/Wordpress/CustomPostType/Map.php:498 msgid "latitude" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:489 +#: src/Wordpress/CustomPostType/Map.php:487 msgid "defines the bounds of the address search - set the bottom left corner of the bounding box" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:494 -#: src/Wordpress/CustomPostType/Map.php:500 +#: src/Wordpress/CustomPostType/Map.php:492 +#: src/Wordpress/CustomPostType/Map.php:498 msgid "address search bounds - right top" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:495 +#: src/Wordpress/CustomPostType/Map.php:493 msgid "defines the bounds of the address search - set the longitude of the right top corner of the bounding box" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:501 +#: src/Wordpress/CustomPostType/Map.php:499 msgid "defines the bounds of the address search - set the latitude of the right top corner of the bounding box" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:506 +#: src/Wordpress/CustomPostType/Map.php:504 msgid "show item availability filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:507 +#: src/Wordpress/CustomPostType/Map.php:505 msgid "activate to show the item availability filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:512 +#: src/Wordpress/CustomPostType/Map.php:510 msgid "label for item availability filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:513 +#: src/Wordpress/CustomPostType/Map.php:511 msgid "alternative label for the item availability filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:521 +#: src/Wordpress/CustomPostType/Map.php:519 msgid "label for item category filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:522 +#: src/Wordpress/CustomPostType/Map.php:520 msgid "alternative label for the item category filter" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:530 +#: src/Wordpress/CustomPostType/Map.php:528 msgid "custom text for filter button" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:531 +#: src/Wordpress/CustomPostType/Map.php:529 msgid "the text for the button used for filtering" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:539 +#: src/Wordpress/CustomPostType/Map.php:537 msgid "Filter groups" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:540 +#: src/Wordpress/CustomPostType/Map.php:538 msgid "Filter groups can group item or location categories together to allow for filtering in the map." msgstr "" -#: src/Wordpress/CustomPostType/Map.php:545 +#: src/Wordpress/CustomPostType/Map.php:543 msgid "Filter group {#}" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:546 +#: src/Wordpress/CustomPostType/Map.php:544 msgid "Add another filter group" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:547 +#: src/Wordpress/CustomPostType/Map.php:545 msgid "Remove filter group" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:552 +#: src/Wordpress/CustomPostType/Map.php:550 msgid "Name" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:555 +#: src/Wordpress/CustomPostType/Map.php:553 msgid "The name of the filter group" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:562 +#: src/Wordpress/CustomPostType/Map.php:560 msgid "This is not available yet. Which data source should be used for the filter group. Taxonomy stands for the assigned categories, post-meta can be individually configured custom fields for item posts. When this item field contains data, it will be included. If it does not contain data or does not exist, the item will be excluded." msgstr "" -#: src/Wordpress/CustomPostType/Map.php:564 +#: src/Wordpress/CustomPostType/Map.php:562 msgid "Taxonomy" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:565 +#: src/Wordpress/CustomPostType/Map.php:563 msgid "Post-meta" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:574 +#: src/Wordpress/CustomPostType/Map.php:572 msgid "Exclusive selection" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:577 +#: src/Wordpress/CustomPostType/Map.php:575 msgid "WARNING: This feature is only available for the cb_search shortcode, not for cb_map. If checked, only one category can be selected in this filter group. If unchecked, multiple categories can be selected." msgstr "" -#: src/Wordpress/CustomPostType/Map.php:580 +#: src/Wordpress/CustomPostType/Map.php:578 msgid "Categories" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:583 +#: src/Wordpress/CustomPostType/Map.php:581 msgid "The categories to be included in the filter group" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:593 +#: src/Wordpress/CustomPostType/Map.php:591 msgid "Filter Item Presets" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:594 +#: src/Wordpress/CustomPostType/Map.php:592 msgid "select the categories that are used to prefilter the items that are shown on the map - none for all items" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:601 +#: src/Wordpress/CustomPostType/Map.php:599 msgid "Filter Location Presets" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:602 +#: src/Wordpress/CustomPostType/Map.php:600 msgid "select the categories that are used to prefilter the locations that are shown on the map - none for all locations" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:618 +#: src/Wordpress/CustomPostType/Map.php:616 #: templates/dashboard-index.php:55 msgid "Maps" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:619 +#: src/Wordpress/CustomPostType/Map.php:617 msgid "Map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:620 -#: src/Wordpress/CustomPostType/Map.php:623 +#: src/Wordpress/CustomPostType/Map.php:618 +#: src/Wordpress/CustomPostType/Map.php:621 msgid "create CB map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:621 +#: src/Wordpress/CustomPostType/Map.php:619 msgid "create Commons Booking map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:622 +#: src/Wordpress/CustomPostType/Map.php:620 msgid "edit Commons Booking map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:624 +#: src/Wordpress/CustomPostType/Map.php:622 msgid "view CB map" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:625 +#: src/Wordpress/CustomPostType/Map.php:623 msgid "search CB maps" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:626 +#: src/Wordpress/CustomPostType/Map.php:624 msgid "no Commons Booking map found" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:627 +#: src/Wordpress/CustomPostType/Map.php:625 msgid "no Commons Booking map found in the trash" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:628 +#: src/Wordpress/CustomPostType/Map.php:626 msgid "parent CB maps" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:657 +#: src/Wordpress/CustomPostType/Map.php:655 msgid "Maps to show Commons Booking Locations and their Items" msgstr "" -#: src/Wordpress/CustomPostType/Map.php:680 +#: src/Wordpress/CustomPostType/Map.php:677 msgid "Copy to clipboard" msgstr "" @@ -3363,101 +3359,101 @@ msgstr "" msgid "Restriction Status" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:75 -#: src/Wordpress/CustomPostType/Timeframe.php:245 +#: src/Wordpress/CustomPostType/Restriction.php:73 +#: src/Wordpress/CustomPostType/Timeframe.php:249 msgid "Filter By Type " msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:101 -#: src/Wordpress/CustomPostType/Timeframe.php:271 +#: src/Wordpress/CustomPostType/Restriction.php:99 +#: src/Wordpress/CustomPostType/Timeframe.php:275 msgid "Filter By Item " msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:128 -#: src/Wordpress/CustomPostType/Timeframe.php:298 +#: src/Wordpress/CustomPostType/Restriction.php:126 +#: src/Wordpress/CustomPostType/Timeframe.php:302 msgid "Filter By Location " msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:141 -#: src/Wordpress/CustomPostType/Timeframe.php:316 +#: src/Wordpress/CustomPostType/Restriction.php:139 +#: src/Wordpress/CustomPostType/Timeframe.php:319 msgid "Filter By Status " msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:309 -#: src/Wordpress/CustomPostType/Restriction.php:390 +#: src/Wordpress/CustomPostType/Restriction.php:312 +#: src/Wordpress/CustomPostType/Restriction.php:393 msgid "Restriction" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:311 -#: src/Wordpress/CustomPostType/Restriction.php:313 +#: src/Wordpress/CustomPostType/Restriction.php:314 +#: src/Wordpress/CustomPostType/Restriction.php:316 msgid "Add new Restriction" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:312 +#: src/Wordpress/CustomPostType/Restriction.php:315 msgid "Edit Restriction" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:314 +#: src/Wordpress/CustomPostType/Restriction.php:317 msgid "Show Restriction" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:315 +#: src/Wordpress/CustomPostType/Restriction.php:318 msgid "Show Restrictions" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:316 +#: src/Wordpress/CustomPostType/Restriction.php:319 msgid "Search Restrictions" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:317 +#: src/Wordpress/CustomPostType/Restriction.php:320 msgid "Restrictions not found" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:318 +#: src/Wordpress/CustomPostType/Restriction.php:321 msgid "No Restrictions found in trash" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:319 +#: src/Wordpress/CustomPostType/Restriction.php:322 msgid "Parent Restrictions:" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:320 +#: src/Wordpress/CustomPostType/Restriction.php:323 msgid "All Restrictions" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:321 +#: src/Wordpress/CustomPostType/Restriction.php:324 msgid "Restriction archive" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:322 +#: src/Wordpress/CustomPostType/Restriction.php:325 msgid "Restriction attributes" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:323 +#: src/Wordpress/CustomPostType/Restriction.php:326 msgid "Add to Restriction" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:324 +#: src/Wordpress/CustomPostType/Restriction.php:327 msgid "Added to Restriction" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:325 +#: src/Wordpress/CustomPostType/Restriction.php:328 msgid "Restriction image" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:326 +#: src/Wordpress/CustomPostType/Restriction.php:329 msgid "set Restriction image" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:327 +#: src/Wordpress/CustomPostType/Restriction.php:330 msgid "remove Restriction image" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:328 +#: src/Wordpress/CustomPostType/Restriction.php:331 msgid "use as Restriction image" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:418 +#: src/Wordpress/CustomPostType/Restriction.php:423 msgid "" "Select the type of restriction.
        \n" "\t\t\t\tSelect Notice, the item can still be used and if e.g. only one part is missing or defective.
        \n" @@ -3466,23 +3462,23 @@ msgid "" "\t\t\t\t" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:440 +#: src/Wordpress/CustomPostType/Restriction.php:449 msgid "Hint" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:442 +#: src/Wordpress/CustomPostType/Restriction.php:451 msgid "Please enter here a short information about the reason and possible effects of the usage restriction.
        The explanation will be displayed on the article page and in the notification e-mail." msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:447 +#: src/Wordpress/CustomPostType/Restriction.php:456 msgid "Set the start date and time" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:457 +#: src/Wordpress/CustomPostType/Restriction.php:466 msgid "Set the estimated end date and time" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:474 +#: src/Wordpress/CustomPostType/Restriction.php:484 msgid "" "Choose status of this restriction.
        \n" "\t\t\t\tSet to None if you want to deactivate the restriction.
        \n" @@ -3492,253 +3488,253 @@ msgid "" "Select the desired status and then click the \"Send\" button to send the e-mail.
        " msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:485 +#: src/Wordpress/CustomPostType/Restriction.php:499 msgid "Send notification emails to users" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:486 +#: src/Wordpress/CustomPostType/Restriction.php:500 msgid "Important: Please save this restriction before clicking the send-button. Dependent of the status of the restriction, the appropriate notifications are sent to all affected users and location admins. You can configure the e-mail templates via Options -> Commonsbooking -> Tab Restrictions" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:504 +#: src/Wordpress/CustomPostType/Restriction.php:518 msgid "Total breakdown" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:505 +#: src/Wordpress/CustomPostType/Restriction.php:519 msgid "Notice" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:515 +#: src/Wordpress/CustomPostType/Restriction.php:529 msgid "Not active" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:516 +#: src/Wordpress/CustomPostType/Restriction.php:530 msgid "Active" msgstr "" -#: src/Wordpress/CustomPostType/Restriction.php:517 +#: src/Wordpress/CustomPostType/Restriction.php:531 msgid "Problem solved" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:105 +#: src/Wordpress/CustomPostType/Timeframe.php:109 msgid "Max. Booking Duration" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:124 +#: src/Wordpress/CustomPostType/Timeframe.php:127 msgid "All timeframe types" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:130 +#: src/Wordpress/CustomPostType/Timeframe.php:133 msgid "Bookable" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:131 +#: src/Wordpress/CustomPostType/Timeframe.php:134 msgid "Holidays or location closed" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:134 +#: src/Wordpress/CustomPostType/Timeframe.php:137 msgid "Blocked (not overbookable)" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:161 +#: src/Wordpress/CustomPostType/Timeframe.php:164 msgid "Select Dates:" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:451 -#: src/Wordpress/CustomPostType/Timeframe.php:1145 +#: src/Wordpress/CustomPostType/Timeframe.php:460 +#: src/Wordpress/CustomPostType/Timeframe.php:1179 msgid "Timeframe" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:480 +#: src/Wordpress/CustomPostType/Timeframe.php:489 msgid "This comment is internal for timeframes like bookable, repair, holiday. If timeframe is a booking this comment can be set by users during the booking confirmation process." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:487 +#: src/Wordpress/CustomPostType/Timeframe.php:496 msgid "Select Type of this timeframe: Bookable or Location Closed. See Documentation for detailed information." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:502 +#: src/Wordpress/CustomPostType/Timeframe.php:511 msgid "Location Category Selection" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:510 +#: src/Wordpress/CustomPostType/Timeframe.php:519 msgid "Location Selection" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:513 -#: src/Wordpress/CustomPostType/Timeframe.php:551 +#: src/Wordpress/CustomPostType/Timeframe.php:522 +#: src/Wordpress/CustomPostType/Timeframe.php:560 msgid "Please select" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:518 +#: src/Wordpress/CustomPostType/Timeframe.php:527 msgid "Select one or more locations" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:525 +#: src/Wordpress/CustomPostType/Timeframe.php:534 msgid "Item Selection" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:533 +#: src/Wordpress/CustomPostType/Timeframe.php:542 msgid "Select one or more items" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:540 +#: src/Wordpress/CustomPostType/Timeframe.php:549 msgid "Item Category Selection" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:548 +#: src/Wordpress/CustomPostType/Timeframe.php:557 msgid "Item selection" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:556 +#: src/Wordpress/CustomPostType/Timeframe.php:565 msgid "Configure bookings" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:561 +#: src/Wordpress/CustomPostType/Timeframe.php:570 msgid "Maximum" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:562 +#: src/Wordpress/CustomPostType/Timeframe.php:571 msgid "days in a row" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:574 +#: src/Wordpress/CustomPostType/Timeframe.php:583 msgid "Lead time:" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:575 +#: src/Wordpress/CustomPostType/Timeframe.php:584 msgid "Enter the number of days that should be blocked for bookings as a booking lead time (calculated from the current day)." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:587 +#: src/Wordpress/CustomPostType/Timeframe.php:596 msgid "Calendar shows as bookable" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:588 +#: src/Wordpress/CustomPostType/Timeframe.php:597 msgid "Select for how many days in advance the calendar should display bookable days. Calculated from the current date." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:600 +#: src/Wordpress/CustomPostType/Timeframe.php:609 msgid "Allowed for" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:602 +#: src/Wordpress/CustomPostType/Timeframe.php:611 msgid "
        Select one or more user roles that will be allowed to book the item exclusively.
        Leave this blank to allow all users to book the item. " msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:606 +#: src/Wordpress/CustomPostType/Timeframe.php:615 msgid "User roles" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:611 +#: src/Wordpress/CustomPostType/Timeframe.php:620 msgid "Configure timeframe" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:616 +#: src/Wordpress/CustomPostType/Timeframe.php:625 msgid "Full day" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:617 +#: src/Wordpress/CustomPostType/Timeframe.php:626 msgid "If this option is selected, users can choose only whole days for pickup and return. No specific time slots for pickup or return are offered. Select this option if the pickup/return should be arranged personally between the location and the user. " msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:626 +#: src/Wordpress/CustomPostType/Timeframe.php:636 msgid "Grid" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:627 +#: src/Wordpress/CustomPostType/Timeframe.php:637 msgid "Choose whether users can only select the entire from/to time period when booking (full slot) or book within the time period in an hourly grid. See the documentation: Manage Booking Timeframes" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:634 +#: src/Wordpress/CustomPostType/Timeframe.php:644 msgid "Start time" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:651 +#: src/Wordpress/CustomPostType/Timeframe.php:661 msgid "End time" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:668 +#: src/Wordpress/CustomPostType/Timeframe.php:678 msgid "Timeframe Repetition" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:669 +#: src/Wordpress/CustomPostType/Timeframe.php:679 msgid "Choose whether the time frame should repeat at specific intervals. The repetitions refer to the unit of a day. With the start and end date you define when the repetition interval starts and ends. If you choose \"weekly\", you can select specific days of the week below. Read the documentation for more information and examples." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:679 +#: src/Wordpress/CustomPostType/Timeframe.php:690 msgid "Import holidays" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:680 +#: src/Wordpress/CustomPostType/Timeframe.php:691 msgid "Select the year and state to import holidays for (as of now only German holidays are supported)" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:687 +#: src/Wordpress/CustomPostType/Timeframe.php:699 msgid "Configure repetition" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:688 +#: src/Wordpress/CustomPostType/Timeframe.php:700 msgid "Below you can make settings regarding the time frame repetition. " msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:693 +#: src/Wordpress/CustomPostType/Timeframe.php:705 msgid "Selected manual dates" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:694 +#: src/Wordpress/CustomPostType/Timeframe.php:706 msgid "Enter the dates in the YYYY-MM-DD format here, the dates are separated by a comma.
        Example: 2023-05-24,2023-06-24
        You can also use the datepicker above to pick dates for this field." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:701 +#: src/Wordpress/CustomPostType/Timeframe.php:713 msgid "Set the start date. If you have selected repetition, this is the start date of the interval. " msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:709 +#: src/Wordpress/CustomPostType/Timeframe.php:721 msgid "Weekdays" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:713 +#: src/Wordpress/CustomPostType/Timeframe.php:725 msgid "Monday" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:714 +#: src/Wordpress/CustomPostType/Timeframe.php:726 msgid "Tuesday" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:715 +#: src/Wordpress/CustomPostType/Timeframe.php:727 msgid "Wednesday" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:716 +#: src/Wordpress/CustomPostType/Timeframe.php:728 msgid "Thursday" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:717 +#: src/Wordpress/CustomPostType/Timeframe.php:729 msgid "Friday" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:718 +#: src/Wordpress/CustomPostType/Timeframe.php:730 msgid "Saturday" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:719 +#: src/Wordpress/CustomPostType/Timeframe.php:731 msgid "Sunday" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:725 +#: src/Wordpress/CustomPostType/Timeframe.php:738 msgid "" "Set the end date. If you have selected repetition, this is the end date of the interval. Leave blank if you do not want to set an end date.\n" "
        Notice: If you want to select only one day (e.g. for holidays or blocked days) set the start and the end date to same day." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:734 -#: src/Wordpress/CustomPostType/Timeframe.php:758 -#: src/Wordpress/CustomPostType/Timeframe.php:781 +#: src/Wordpress/CustomPostType/Timeframe.php:751 +#: src/Wordpress/CustomPostType/Timeframe.php:780 +#: src/Wordpress/CustomPostType/Timeframe.php:803 msgid "Booking Codes" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:735 +#: src/Wordpress/CustomPostType/Timeframe.php:753 msgid "" "You can automatically generate booking codes. Codes can be generated only with the following settings:
        \n" "\t\t\t\t- Whole day is enabled
        \n" @@ -3747,173 +3743,173 @@ msgid "" "\t\t\t\t" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:744 +#: src/Wordpress/CustomPostType/Timeframe.php:766 msgid "Create Booking Codes" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:745 +#: src/Wordpress/CustomPostType/Timeframe.php:767 msgid "Select to generate booking codes for each day within the start/end date. The booking codes will be generated after clicking \"Save / Update\"." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:751 +#: src/Wordpress/CustomPostType/Timeframe.php:773 msgid "Show Booking Codes" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:752 +#: src/Wordpress/CustomPostType/Timeframe.php:774 msgid "Select whether users should be shown a booking code when booking." msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:764 +#: src/Wordpress/CustomPostType/Timeframe.php:786 msgid "Send booking codes automated by email" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:765 +#: src/Wordpress/CustomPostType/Timeframe.php:787 msgid "Enable automated sending of booking codes by email" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:767 +#: src/Wordpress/CustomPostType/Timeframe.php:789 msgid "First day to send Codes (List starts at next month)
        (Same day will be used for subsequent messages) " msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:770 +#: src/Wordpress/CustomPostType/Timeframe.php:792 msgid "Months to send" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:771 +#: src/Wordpress/CustomPostType/Timeframe.php:793 msgid "Send booking codes for this amount of month's in one email" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:773 +#: src/Wordpress/CustomPostType/Timeframe.php:795 msgid "Next email planned for: " msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:774 +#: src/Wordpress/CustomPostType/Timeframe.php:796 msgid "(not planned)" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:820 +#: src/Wordpress/CustomPostType/Timeframe.php:843 msgid "Manual selection" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:821 +#: src/Wordpress/CustomPostType/Timeframe.php:844 msgid "Select by category" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:822 +#: src/Wordpress/CustomPostType/Timeframe.php:845 #: templates/shortcode-bookings.php:54 msgid "All" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:832 +#: src/Wordpress/CustomPostType/Timeframe.php:856 msgid "Full slot" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:833 +#: src/Wordpress/CustomPostType/Timeframe.php:857 msgid "Hourly" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:843 +#: src/Wordpress/CustomPostType/Timeframe.php:868 msgid "No repetition" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:844 +#: src/Wordpress/CustomPostType/Timeframe.php:869 msgid "Manual repetition" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:845 +#: src/Wordpress/CustomPostType/Timeframe.php:870 msgid "Daily" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:846 +#: src/Wordpress/CustomPostType/Timeframe.php:871 msgid "Weekly" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:847 +#: src/Wordpress/CustomPostType/Timeframe.php:872 msgid "Monthly" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:848 +#: src/Wordpress/CustomPostType/Timeframe.php:873 msgid "Yearly" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:932 +#: src/Wordpress/CustomPostType/Timeframe.php:955 msgid "Orphaned bookings found, can migrate. Click here to migrate " msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1147 -#: src/Wordpress/CustomPostType/Timeframe.php:1149 +#: src/Wordpress/CustomPostType/Timeframe.php:1181 +#: src/Wordpress/CustomPostType/Timeframe.php:1183 msgid "Add new timeframe" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1148 +#: src/Wordpress/CustomPostType/Timeframe.php:1182 msgid "Edit timeframe" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1150 +#: src/Wordpress/CustomPostType/Timeframe.php:1184 msgid "Show timeframe" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1151 +#: src/Wordpress/CustomPostType/Timeframe.php:1185 msgid "Show timeframes" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1152 +#: src/Wordpress/CustomPostType/Timeframe.php:1186 msgid "Search timeframes" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1153 +#: src/Wordpress/CustomPostType/Timeframe.php:1187 msgid "Timeframes not found" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1154 +#: src/Wordpress/CustomPostType/Timeframe.php:1188 msgid "No timeframes found in trash" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1155 +#: src/Wordpress/CustomPostType/Timeframe.php:1189 msgid "Parent timeframes:" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1156 +#: src/Wordpress/CustomPostType/Timeframe.php:1190 msgid "All timeframes" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1159 +#: src/Wordpress/CustomPostType/Timeframe.php:1193 msgid "Add to timeframe" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1160 +#: src/Wordpress/CustomPostType/Timeframe.php:1194 msgid "Added to timeframe" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1162 +#: src/Wordpress/CustomPostType/Timeframe.php:1196 msgid "set timeframe image" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1163 +#: src/Wordpress/CustomPostType/Timeframe.php:1197 msgid "remove timeframe image" msgstr "" -#: src/Wordpress/CustomPostType/Timeframe.php:1164 +#: src/Wordpress/CustomPostType/Timeframe.php:1198 msgid "use as timeframe image" msgstr "" -#: src/Wordpress/Options/AdminOptions.php:54 +#: src/Wordpress/Options/AdminOptions.php:53 msgid "Default values for following fields automatically set or restored, because they were empty:
        " msgstr "" -#: src/Wordpress/Options/OptionsTab.php:56 +#: src/Wordpress/Options/OptionsTab.php:55 msgid "CommonsBooking" msgstr "" -#: src/Wordpress/Options/OptionsTab.php:148 +#: src/Wordpress/Options/OptionsTab.php:146 msgid "The export path does not exist or is not readable." msgstr "" -#: src/Wordpress/Options/OptionsTab.php:156 +#: src/Wordpress/Options/OptionsTab.php:154 msgid "The export path is not writeable." msgstr "" -#: src/Wordpress/Options/OptionsTab.php:167 +#: src/Wordpress/Options/OptionsTab.php:166 msgid "Cache cleared." msgstr "" @@ -3945,25 +3941,25 @@ msgstr "" msgid "
      • Log out
      • " msgstr "" -#: src/Wordpress/Widget/UserWidget.php:85 +#: src/Wordpress/Widget/UserWidget.php:83 msgid "You are not logged in." msgstr "" #. translators: $s = wp login url -#: src/Wordpress/Widget/UserWidget.php:88 +#: src/Wordpress/Widget/UserWidget.php:86 msgid "
      • Login
      • " msgstr "" #. translators: $s = wp registration url -#: src/Wordpress/Widget/UserWidget.php:90 +#: src/Wordpress/Widget/UserWidget.php:88 msgid "
      • Register
      • " msgstr "" -#: src/Wordpress/Widget/UserWidget.php:109 +#: src/Wordpress/Widget/UserWidget.php:106 msgid "Title:" msgstr "" -#: src/Wordpress/Widget/UserWidget.php:115 +#: src/Wordpress/Widget/UserWidget.php:112 msgid "Text:" msgstr "" @@ -3987,8 +3983,8 @@ msgstr "" msgid "You are not allowed to access this booking." msgstr "" -#: templates/booking-single-notallowed.php:14 -#: templates/timeframe-notallowed.php:14 +#: templates/booking-single-notallowed.php:15 +#: templates/timeframe-notallowed.php:15 msgid "Login to your account" msgstr "" @@ -4019,31 +4015,31 @@ msgstr "" msgid "Admin Booking by" msgstr "" -#: templates/booking-single.php:140 +#: templates/booking-single.php:142 msgid "Your E-Mail" msgstr "" -#: templates/booking-single.php:144 +#: templates/booking-single.php:146 msgid "Your data" msgstr "" -#: templates/calendar-key.php:12 +#: templates/calendar-key.php:11 msgid "Color legend" msgstr "" -#: templates/calendar-key.php:13 +#: templates/calendar-key.php:12 msgid "bookable" msgstr "" -#: templates/calendar-key.php:14 +#: templates/calendar-key.php:13 msgid "booked/blocked" msgstr "" -#: templates/calendar-key.php:15 +#: templates/calendar-key.php:14 msgid "station closed" msgstr "" -#: templates/calendar-key.php:16 +#: templates/calendar-key.php:15 msgid "not bookable" msgstr "" @@ -4100,24 +4096,24 @@ msgid "No returns today" msgstr "" #. translators: %1$s: wp_login_url, 1$s: wp_registration_url -#: templates/item-single.php:42 -#: templates/location-single.php:42 +#: templates/item-single.php:44 +#: templates/location-single.php:43 msgid "To be able to book, you must first login or register." msgstr "" -#: templates/location-calendar-header.php:31 +#: templates/location-calendar-header.php:33 msgid "Pickup instructions:" msgstr "" -#: templates/location-single-meta.php:23 +#: templates/location-single-meta.php:22 msgid "Adress" msgstr "" -#: templates/location-single-meta.php:34 +#: templates/location-single-meta.php:33 msgid "Location contact" msgstr "" -#: templates/massoperations-index.php:7 +#: templates/massoperations-index.php:8 msgid "Migrate orphaned bookings" msgstr "" diff --git a/package-lock.json b/package-lock.json index 492bd5b09..53aca9537 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,10 +20,10 @@ "vue": "^3.5.13" }, "devDependencies": { - "@babel/preset-env": "^7.26.0", - "@wordpress/env": "^10.15.0", + "@babel/preset-env": "^7.26.7", + "@wordpress/env": "^10.17.0", "commons-api": "git+https://github.com/wielebenwir/commons-api.git", - "cypress": "^13.17.0", + "cypress": "^14.0.1", "editorconfig": "^2.0.0", "grunt": "^1.6.1", "grunt-babel": "^8.0.0", @@ -36,7 +36,7 @@ "grunt-contrib-watch": "^1.1.0", "grunt-dart-sass": "^2.0.1", "matchdep": "^2.0.0", - "sass": "^1.83.1" + "sass": "^1.83.4" } }, "node_modules/@ampproject/remapping": { @@ -67,10 +67,11 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", - "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", + "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -139,26 +140,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz", - "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", + "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.25.9", + "@babel/compat-data": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -278,10 +267,11 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -320,19 +310,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz", - "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", @@ -600,12 +577,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", - "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -775,12 +753,12 @@ } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz", - "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { @@ -915,14 +893,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz", - "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==", + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-simple-access": "^7.25.9" + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -997,12 +975,13 @@ } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", - "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1262,12 +1241,13 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", - "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz", + "integrity": "sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1340,14 +1320,15 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", - "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.7.tgz", + "integrity": "sha512-Ycg2tnXwixaXOVb29rana8HNPgLVBof8qqtNQ9LE22IoyZboQbGSxI6ZySMdW3K5nAe6gu35IaJefUJflhUFTQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/compat-data": "^7.26.5", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", @@ -1361,7 +1342,7 @@ "@babel/plugin-transform-arrow-functions": "^7.25.9", "@babel/plugin-transform-async-generator-functions": "^7.25.9", "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", "@babel/plugin-transform-block-scoping": "^7.25.9", "@babel/plugin-transform-class-properties": "^7.25.9", "@babel/plugin-transform-class-static-block": "^7.26.0", @@ -1372,7 +1353,7 @@ "@babel/plugin-transform-duplicate-keys": "^7.25.9", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-for-of": "^7.25.9", "@babel/plugin-transform-function-name": "^7.25.9", @@ -1381,12 +1362,12 @@ "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", "@babel/plugin-transform-member-expression-literals": "^7.25.9", "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", "@babel/plugin-transform-modules-systemjs": "^7.25.9", "@babel/plugin-transform-modules-umd": "^7.25.9", "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", "@babel/plugin-transform-numeric-separator": "^7.25.9", "@babel/plugin-transform-object-rest-spread": "^7.25.9", "@babel/plugin-transform-object-super": "^7.25.9", @@ -1403,7 +1384,7 @@ "@babel/plugin-transform-spread": "^7.25.9", "@babel/plugin-transform-sticky-regex": "^7.25.9", "@babel/plugin-transform-template-literals": "^7.25.9", - "@babel/plugin-transform-typeof-symbol": "^7.25.9", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", "@babel/plugin-transform-unicode-escapes": "^7.25.9", "@babel/plugin-transform-unicode-property-regex": "^7.25.9", "@babel/plugin-transform-unicode-regex": "^7.25.9", @@ -2698,10 +2679,11 @@ } }, "node_modules/@wordpress/env": { - "version": "10.15.0", - "resolved": "https://registry.npmjs.org/@wordpress/env/-/env-10.15.0.tgz", - "integrity": "sha512-UMd7taPznebwMnW7tHlr+PzRMrCFzPL/rtJZdufxGCCr4MNaAYecb4OjJsuy2w1Bm9erDjTa7BjUEw2V+jWB/Q==", + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@wordpress/env/-/env-10.17.0.tgz", + "integrity": "sha512-Wy0DpOwOy2gtmtad9inkEydAfBm5+TMulCfh22oi5hFVy6BaPpS+Dm9yjgzd9YtO13CR1Y/WjcqYJxEMOFVEJA==", "dev": true, + "license": "GPL-2.0-or-later", "dependencies": { "@inquirer/prompts": "^7.2.0", "chalk": "^4.0.0", @@ -4005,11 +3987,12 @@ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/cypress": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.17.0.tgz", - "integrity": "sha512-5xWkaPurwkIljojFidhw8lFScyxhtiFHl/i/3zov+1Z5CmY4t9tjIdvSXfu82Y3w7wt0uR9KkucbhkVvJZLQSA==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-14.0.1.tgz", + "integrity": "sha512-gBAvKZE3f6eBaW1v8OtrwAFP90rjNZjjOO40M2KvOvmwVXk96Ps5Yjyck1EzGkXmNCaC/8kXFOY/1KD/wsaWpQ==", "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { "@cypress/request": "^3.0.6", "@cypress/xvfb": "^1.2.4", @@ -4059,7 +4042,7 @@ "cypress": "bin/cypress" }, "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" } }, "node_modules/cypress/node_modules/ansi-styles": { @@ -9593,10 +9576,11 @@ "dev": true }, "node_modules/sass": { - "version": "1.83.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.1.tgz", - "integrity": "sha512-EVJbDaEs4Rr3F0glJzFSOvtg2/oy2V/YrGFPqPY24UqcLDWcI9ZY5sN+qyO3c/QCZwzgfirvhXvINiJCE/OLcA==", + "version": "1.83.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.4.tgz", + "integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==", "dev": true, + "license": "MIT", "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", diff --git a/package.json b/package.json index cc34e30ea..2ba12b39a 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,10 @@ "url": "https://github.com/wielebenwir/cb" }, "devDependencies": { - "@babel/preset-env": "^7.26.0", - "@wordpress/env": "^10.15.0", + "@babel/preset-env": "^7.26.7", + "@wordpress/env": "^10.17.0", "commons-api": "git+https://github.com/wielebenwir/commons-api.git", - "cypress": "^13.17.0", + "cypress": "^14.0.1", "editorconfig": "^2.0.0", "grunt": "^1.6.1", "grunt-babel": "^8.0.0", @@ -25,7 +25,7 @@ "grunt-contrib-watch": "^1.1.0", "grunt-dart-sass": "^2.0.1", "matchdep": "^2.0.0", - "sass": "^1.83.1" + "sass": "^1.83.4" }, "scripts": { "start": "composer install --ignore-platform-reqs && npm install && npm run dist", diff --git a/src/API/AvailabilityRoute.php b/src/API/AvailabilityRoute.php index 7c25b8fab..4aec3f3ae 100644 --- a/src/API/AvailabilityRoute.php +++ b/src/API/AvailabilityRoute.php @@ -62,13 +62,13 @@ public function getItemData( $id = false ): array { * @return WP_REST_Response|WP_Error */ public function get_item( $request ) { - //get parameters from request - $params = $request->get_params(); - $data = new stdClass(); + // get parameters from request + $params = $request->get_params(); + $data = new stdClass(); try { $data->availability = $this->getItemData( $params['id'] ); - //return a response or error based on some conditional + // return a response or error based on some conditional if ( count( $data->availability ) ) { return new WP_REST_Response( $data, 200 ); } else { @@ -76,10 +76,9 @@ public function get_item( $request ) { // TODO this part and the enclosing if-clause can be removed in future version, if no problems arose ... return new WP_REST_Response( $data, 200 ); } - } catch (Exception $e) { + } catch ( Exception $e ) { return new WP_Error( 'code', $e->getMessage() ); } - } /** @@ -94,16 +93,15 @@ public function get_items( $request ) { $data->availability = []; // Get all items - $items = Item::get([], true); + $items = Item::get( [], true ); // Collect availabilies for each item - foreach ($items as $item) { + foreach ( $items as $item ) { $data->availability = array_merge( $data->availability, - $this->getItemData($item->ID) + $this->getItemData( $item->ID ) ); } return new WP_REST_Response( $data, 200 ); } - } diff --git a/src/API/BaseRoute.php b/src/API/BaseRoute.php index 6d70a6fff..da41658cd 100644 --- a/src/API/BaseRoute.php +++ b/src/API/BaseRoute.php @@ -186,7 +186,7 @@ public function escapeJsonString( $string ) { * * @return bool */ - public static function hasPermission() : bool { + public static function hasPermission(): bool { $isApiActive = Settings::getOption( 'commonsbooking_options_api', 'api-activated' ); $anonymousAccessAllowed = Settings::getOption( 'commonsbooking_options_api', 'apikey_not_required' ); $apiKey = array_key_exists( self::API_KEY_PARAM, $_REQUEST ) ? sanitize_text_field( $_REQUEST[ self::API_KEY_PARAM ] ) : false; @@ -207,5 +207,4 @@ public static function hasPermission() : bool { return false; } - } diff --git a/src/API/GBFS/BaseRoute.php b/src/API/GBFS/BaseRoute.php index 777e78f18..1b8c056ca 100644 --- a/src/API/GBFS/BaseRoute.php +++ b/src/API/GBFS/BaseRoute.php @@ -3,7 +3,6 @@ namespace CommonsBooking\API\GBFS; - use CommonsBooking\Repository\Location; use Exception; use stdClass; @@ -30,9 +29,9 @@ public function get_items( $request ): WP_REST_Response { $data = new stdClass(); $data->data = new stdClass(); $data->data->stations = $this->getItemData( $request ); - $data->last_updated = current_time('timestamp', true); + $data->last_updated = time(); $data->ttl = 60; - $data->version = "2.3"; + $data->version = '2.3'; if ( WP_DEBUG ) { $this->validateData( $data ); @@ -65,5 +64,4 @@ public function getItemData( $request ): array { return $data; } - -} \ No newline at end of file +} diff --git a/src/API/GBFS/Discovery.php b/src/API/GBFS/Discovery.php index 846f24939..d6dc3d47b 100644 --- a/src/API/GBFS/Discovery.php +++ b/src/API/GBFS/Discovery.php @@ -35,19 +35,18 @@ class Discovery extends \CommonsBooking\API\BaseRoute { public function get_items( $request ): WP_REST_Response { $feeds = array(); - $feeds[] = $this->get_feed('system_information'); - $feeds[] = $this->get_feed('station_information'); - $feeds[] = $this->get_feed('station_status'); - - $lang = get_bloginfo('language'); + $feeds[] = $this->get_feed( 'system_information' ); + $feeds[] = $this->get_feed( 'station_information' ); + $feeds[] = $this->get_feed( 'station_status' ); + + $lang = get_bloginfo( 'language' ); $data = new stdClass(); $data->data = new stdClass(); $data->data->$lang = new stdClass(); $data->data->$lang->feeds = $feeds; - $data->last_updated = current_time('timestamp'); + $data->last_updated = current_time( 'timestamp' ); $data->ttl = 86400; - $data->version = "2.3"; - + $data->version = '2.3'; if ( WP_DEBUG ) { $this->validateData( $data ); @@ -59,7 +58,7 @@ public function get_items( $request ): WP_REST_Response { private function get_feed( $name ): stdClass { $feed = new stdClass(); $feed->name = $name; - $feed->url = get_rest_url() . 'commonsbooking/v1/' . $name . '.json'; + $feed->url = get_rest_url() . 'commonsbooking/v1/' . $name . '.json'; return $feed; } } diff --git a/src/API/GBFS/StationInformation.php b/src/API/GBFS/StationInformation.php index 40ecf27b7..463cb3d99 100644 --- a/src/API/GBFS/StationInformation.php +++ b/src/API/GBFS/StationInformation.php @@ -3,7 +3,6 @@ namespace CommonsBooking\API\GBFS; - use CommonsBooking\Helper\GeoHelper; use CommonsBooking\Model\Location; use Exception; @@ -35,24 +34,24 @@ class StationInformation extends BaseRoute { */ public function prepare_item_for_response( $item, $request ): stdClass { $preparedItem = new stdClass(); - $preparedItem->station_id = $item->ID . ""; + $preparedItem->station_id = $item->ID . ''; $preparedItem->name = $item->post_title; $preparedItem->address = $item->formattedAddressOneLine(); $preparedItem->rental_uris = new stdClass(); $preparedItem->rental_uris->web = get_permalink( $item->ID ); // Additional possible fields (but we don't have the information): -// $preparedItem->short_name = ""; -// $preparedItem->cross_street = ""; -// $preparedItem->region_id = ""; -// $preparedItem->post_code = ""; -// $preparedItem->rental_methods = []; -// $preparedItem->is_virtual_station = false; -// $preparedItem->station_area = ""; -// $preparedItem->capacity = ""; -// $preparedItem->vehicle_capacity = ""; -// $preparedItem->is_valet_station = ""; -// $preparedItem->vehicle_type_capacity = ""; + // $preparedItem->short_name = ""; + // $preparedItem->cross_street = ""; + // $preparedItem->region_id = ""; + // $preparedItem->post_code = ""; + // $preparedItem->rental_methods = []; + // $preparedItem->is_virtual_station = false; + // $preparedItem->station_area = ""; + // $preparedItem->capacity = ""; + // $preparedItem->vehicle_capacity = ""; + // $preparedItem->is_valet_station = ""; + // $preparedItem->vehicle_type_capacity = ""; $latitude = get_post_meta( $item->ID, 'geo_latitude', true ); // TODO this can be part of model $item Location $longitude = get_post_meta( $item->ID, 'geo_longitude', true ); @@ -85,5 +84,4 @@ public function prepare_item_for_response( $item, $request ): stdClass { return $preparedItem; } - -} \ No newline at end of file +} diff --git a/src/API/GBFS/StationStatus.php b/src/API/GBFS/StationStatus.php index f357ccab9..c17530d22 100644 --- a/src/API/GBFS/StationStatus.php +++ b/src/API/GBFS/StationStatus.php @@ -3,7 +3,6 @@ namespace CommonsBooking\API\GBFS; - use CommonsBooking\Model\Calendar; use CommonsBooking\Model\Day; use CommonsBooking\Model\Location; @@ -21,9 +20,10 @@ class StationStatus extends BaseRoute { /** * Commons-API schema definition. + * * @var string */ - protected $schemaUrl = COMMONSBOOKING_PLUGIN_DIR . 'includes/gbfs-json-schema/station_status.json'; + protected $schemaUrl = COMMONSBOOKING_PLUGIN_DIR . 'includes/gbfs-json-schema/station_status.json'; /** * @param Location $item @@ -34,12 +34,12 @@ class StationStatus extends BaseRoute { */ public function prepare_item_for_response( $item, $request ): stdClass { $preparedItem = new stdClass(); - $preparedItem->station_id = $item->ID . ""; - $preparedItem->num_bikes_available = $this->getItemCountAtLocation($item->ID); + $preparedItem->station_id = $item->ID . ''; + $preparedItem->num_bikes_available = $this->getItemCountAtLocation( $item->ID ); $preparedItem->is_installed = true; $preparedItem->is_renting = true; $preparedItem->is_returning = true; - $preparedItem->last_reported = current_time('timestamp', true); + $preparedItem->last_reported = time(); return $preparedItem; } @@ -56,31 +56,31 @@ public function prepare_item_for_response( $item, $request ): stdClass { * @return int|null * @throws \Exception */ - private function getItemCountAtLocation($locationId){ - $items = Item::getByLocation($locationId,true); - $nowDT = new \DateTime(); + private function getItemCountAtLocation( $locationId ) { + $items = Item::getByLocation( $locationId, true ); + $nowDT = new \DateTime(); $availableCounter = 0; - foreach ($items as $item){ - //we have to make our calendar span at least one day, otherwise we get no results - $itemCalendar = new Calendar( + foreach ( $items as $item ) { + // we have to make our calendar span at least one day, otherwise we get no results + $itemCalendar = new Calendar( new Day( date( 'Y-m-d', time() ) ), - new Day( date( 'Y-m-d', strtotime('+1 day') ) ), - [$locationId], - [$item->ID] + new Day( date( 'Y-m-d', strtotime( '+1 day' ) ) ), + [ $locationId ], + [ $item->ID ] ); $availabilitySlots = $itemCalendar->getAvailabilitySlots(); - //we have to iterate over multiple slots because the calendar will give us more than we asked for - foreach ($availabilitySlots as $availabilitySlot){ - //match our exact current time to the slot - $startDT = new \DateTime($availabilitySlot->start); - $endDT = new \DateTime($availabilitySlot->end); - if ($nowDT >= $startDT && $nowDT <= $endDT){ - $availableCounter++; - //break out of the loop, we only need one match of availability per item + // we have to iterate over multiple slots because the calendar will give us more than we asked for + foreach ( $availabilitySlots as $availabilitySlot ) { + // match our exact current time to the slot + $startDT = new \DateTime( $availabilitySlot->start ); + $endDT = new \DateTime( $availabilitySlot->end ); + if ( $nowDT >= $startDT && $nowDT <= $endDT ) { + ++$availableCounter; + // break out of the loop, we only need one match of availability per item break; } } } return $availableCounter; } -} \ No newline at end of file +} diff --git a/src/API/GBFS/SystemInformation.php b/src/API/GBFS/SystemInformation.php index 0ede99fe4..f9c2aba24 100644 --- a/src/API/GBFS/SystemInformation.php +++ b/src/API/GBFS/SystemInformation.php @@ -18,25 +18,26 @@ class SystemInformation extends \CommonsBooking\API\BaseRoute { /** * Commons-API schema definition. + * * @var string */ - protected $schemaUrl = COMMONSBOOKING_PLUGIN_DIR . 'includes/gbfs-json-schema/system_information.json'; + protected $schemaUrl = COMMONSBOOKING_PLUGIN_DIR . 'includes/gbfs-json-schema/system_information.json'; - public function get_items( $request ): WP_REST_Response { - $tz = timezone_name_get(wp_timezone()); - if (preg_match('/^(\+|\-)0?(\d+)/', $tz, $matches)) { - $tz = "Etc/GMT" . $matches[1] . $matches[2]; + public function get_items( $request ): WP_REST_Response { + $tz = timezone_name_get( wp_timezone() ); + if ( preg_match( '/^(\+|\-)0?(\d+)/', $tz, $matches ) ) { + $tz = 'Etc/GMT' . $matches[1] . $matches[2]; } - $data = new stdClass(); - $data->data = new stdClass(); - $data->data->name = get_bloginfo('name'); - $data->data->system_id = sha1(site_url()); - $data->data->language = get_bloginfo('language'); - $data->data->timezone = $tz; - $data->last_updated = current_time('timestamp'); - $data->ttl = 86400; - $data->version = "2.3"; + $data = new stdClass(); + $data->data = new stdClass(); + $data->data->name = get_bloginfo( 'name' ); + $data->data->system_id = sha1( site_url() ); + $data->data->language = get_bloginfo( 'language' ); + $data->data->timezone = $tz; + $data->last_updated = current_time( 'timestamp' ); + $data->ttl = 86400; + $data->version = '2.3'; if ( WP_DEBUG ) { $this->validateData( $data ); diff --git a/src/API/ItemsRoute.php b/src/API/ItemsRoute.php index 3073b55b6..d46d5ed8f 100644 --- a/src/API/ItemsRoute.php +++ b/src/API/ItemsRoute.php @@ -3,7 +3,6 @@ namespace CommonsBooking\API; - use CommonsBooking\Repository\Item; use stdClass; use WP_Error; @@ -22,13 +21,14 @@ class ItemsRoute extends BaseRoute { * * @var string */ - protected $rest_base = "items"; + protected $rest_base = 'items'; /** * Commons-API schema definition. + * * @var string */ - protected $schemaUrl = COMMONSBOOKING_PLUGIN_DIR . "includes/commons-api-json-schema/commons-api.items.schema.json"; + protected $schemaUrl = COMMONSBOOKING_PLUGIN_DIR . 'includes/commons-api-json-schema/commons-api.items.schema.json'; /** * Returns raw data collection. @@ -45,7 +45,7 @@ public function getItemData( $request ): stdClass { $args = []; if ( array_key_exists( 'id', $params ) ) { $args = [ - 'p' => $params['id'] + 'p' => $params['id'], ]; } @@ -66,37 +66,36 @@ public function getItemData( $request ): stdClass { * @return WP_Error|WP_REST_Response */ public function get_items( $request ) { - //get parameters from request + // get parameters from request $params = $request->get_params(); $data = $this->getItemData( $request ); // Add owners data -// if(!array_key_exists('owners', $params) || $params['owners'] != "false") { -// $ownersRoute = new OwnersRoute(); -// $data->owners = $ownersRoute->getItemData($request); -// } + // if(!array_key_exists('owners', $params) || $params['owners'] != "false") { + // $ownersRoute = new OwnersRoute(); + // $data->owners = $ownersRoute->getItemData($request); + // } // Add projects data - if ( ! array_key_exists( 'projects', $params ) || $params['projects'] != "false" ) { + if ( ! array_key_exists( 'projects', $params ) || $params['projects'] != 'false' ) { $projectsRoute = new ProjectsRoute(); $data->projects = $projectsRoute->getItemData(); } // Add locations data - if ( ! array_key_exists( 'locations', $params ) || $params['locations'] != "false" ) { + if ( ! array_key_exists( 'locations', $params ) || $params['locations'] != 'false' ) { $locationsRoute = new LocationsRoute(); $data->locations = $locationsRoute->getItemData( $request ); } // Add availability data - if ( ! array_key_exists( 'availability', $params ) || $params['availability'] != "false" ) { + if ( ! array_key_exists( 'availability', $params ) || $params['availability'] != 'false' ) { $data->availability = []; foreach ( $data->items as $item ) { $availabilityRoute = new AvailabilityRoute(); $data->availability = array_merge( $data->availability, $availabilityRoute->getItemData( $item->id ) ); } - } if ( WP_DEBUG ) { @@ -119,7 +118,7 @@ public function get_item( $request ): WP_REST_Response { } /** - * @param mixed $item + * @param mixed $item * @param WP_REST_Request $request * * @return stdClass @@ -130,12 +129,12 @@ public function prepare_item_for_response( $item, $request ): stdClass { $preparedItem->name = $item->post_title; $preparedItem->url = get_permalink( $item->ID ); $preparedItem->description = $this->escapeJsonString( $item->post_content ); - $preparedItem->projectId = "1"; + $preparedItem->projectId = '1'; $thumbnailId = get_post_thumbnail_id( $item->ID ); if ( $thumbnailId ) { - $preparedItem->image = wp_get_attachment_image_url( $thumbnailId, 'full' ); - $preparedItem-> images = [ + $preparedItem->image = wp_get_attachment_image_url( $thumbnailId, 'full' ); + $preparedItem->images = [ 'thumbnail' => wp_get_attachment_image_src( $thumbnailId, 'thumbnail' ), 'medium' => wp_get_attachment_image_src( $thumbnailId, 'medium' ), 'large' => wp_get_attachment_image_src( $thumbnailId, 'large' ), @@ -145,5 +144,4 @@ public function prepare_item_for_response( $item, $request ): stdClass { return $preparedItem; } - } diff --git a/src/API/LocationsRoute.php b/src/API/LocationsRoute.php index b76c460ab..4db130519 100644 --- a/src/API/LocationsRoute.php +++ b/src/API/LocationsRoute.php @@ -3,7 +3,6 @@ namespace CommonsBooking\API; - use CommonsBooking\Helper\GeoHelper; use CommonsBooking\Model\Location; use Exception; @@ -76,7 +75,7 @@ public function get_items( $request ) { public function getItemData( $request ) { $data = new stdClass(); - $data->type = "FeatureCollection"; + $data->type = 'FeatureCollection'; $params = $request->get_params(); $args = []; @@ -117,7 +116,7 @@ public function prepare_item_for_response( $item, $request ) { $preparedItem->type = 'Feature'; $preparedItem->properties = new stdClass(); - $preparedItem->properties->id = $item->ID . ""; + $preparedItem->properties->id = $item->ID . ''; $preparedItem->properties->name = $item->post_title; $preparedItem->properties->description = $this->escapeJsonString( $item->post_content ); $preparedItem->properties->url = get_permalink( $item->ID ); @@ -130,7 +129,7 @@ public function prepare_item_for_response( $item, $request ) { // If we have latitude and longitude definec, we use them. if ( $latitude && $longitude ) { $preparedItem->geometry = new stdClass(); - $preparedItem->geometry->type = "Point"; + $preparedItem->geometry->type = 'Point'; $preparedItem->geometry->coordinates = [ floatval( $longitude ), floatval( $latitude ), @@ -139,7 +138,7 @@ public function prepare_item_for_response( $item, $request ) { $address = GeoHelper::getAddressData( $item->formattedAddressOneLine() ); if ( $address !== null ) { $preparedItem->geometry = new stdClass(); - $preparedItem->geometry->type = "Point"; + $preparedItem->geometry->type = 'Point'; $preparedItem->geometry->coordinates = $address->getCoordinates()->toArray(); // Save data to items @@ -160,5 +159,4 @@ public function prepare_item_for_response( $item, $request ) { return $preparedItem; } - } diff --git a/src/API/OwnersRoute.php b/src/API/OwnersRoute.php index f53f3e509..3c5be70c5 100644 --- a/src/API/OwnersRoute.php +++ b/src/API/OwnersRoute.php @@ -3,7 +3,6 @@ namespace CommonsBooking\API; - use CommonsBooking\Repository\UserRepository; use stdClass; use WP_Error; @@ -54,25 +53,25 @@ public function getItemData( $request ): array { public function prepare_item_for_response( $owner, $request ): stdClass { $ownerObject = new stdClass(); - $ownerObject->id = "" . $owner->ID; + $ownerObject->id = '' . $owner->ID; $ownerObject->name = get_user_meta( $owner->ID, 'first_name', true ) . ' ' . get_user_meta( $owner->ID, 'last_name', true ); $ownerObject->url = $owner->user_url; -// if($items = \CommonsBooking\Repository\Item::getByUserId($owner->ID, true)) { -// $ownerObject->items = []; -// $itemsRoute = new ItemsRoute(); -// foreach($items as $item) { -// $ownerObject->items[] = $itemsRoute->prepare_item_for_response($item, new \WP_REST_Request()); -// } -// } -// -// if($locations = \CommonsBooking\Repository\Location::getByUserId($owner->ID, true)) { -// $ownerObject->locations = []; -// $locationsRoute = new LocationsRoute(); -// foreach($locations as $location) { -// $ownerObject->locations[] = $locationsRoute->prepare_item_for_response($location, new \WP_REST_Request()); -// } -// } + // if($items = \CommonsBooking\Repository\Item::getByUserId($owner->ID, true)) { + // $ownerObject->items = []; + // $itemsRoute = new ItemsRoute(); + // foreach($items as $item) { + // $ownerObject->items[] = $itemsRoute->prepare_item_for_response($item, new \WP_REST_Request()); + // } + // } + // + // if($locations = \CommonsBooking\Repository\Location::getByUserId($owner->ID, true)) { + // $ownerObject->locations = []; + // $locationsRoute = new LocationsRoute(); + // foreach($locations as $location) { + // $ownerObject->locations[] = $locationsRoute->prepare_item_for_response($location, new \WP_REST_Request()); + // } + // } return $ownerObject; } @@ -81,7 +80,7 @@ public function prepare_item_for_response( $owner, $request ): stdClass { * Get a single item */ public function get_item( $request ): WP_REST_Response { - //get parameters from request + // get parameters from request $params = $request->get_params(); $owner = get_user_by( 'id', $params['id'] ); $data = new stdClass(); @@ -107,5 +106,4 @@ public function get_items( $request ) { public function prepare_response_for_collection( $itemdata ) { return $itemdata; } - } diff --git a/src/API/ProjectsRoute.php b/src/API/ProjectsRoute.php index 788dc2c77..6bcf364cb 100644 --- a/src/API/ProjectsRoute.php +++ b/src/API/ProjectsRoute.php @@ -3,14 +3,13 @@ namespace CommonsBooking\API; - use stdClass; use WP_REST_Response; /** * Endpoint for information about the lending organisation. - * Infos like site name, description etc. is retrieved from general Wordpress settings @see https://wordpress.com/support/general-settings/ - * + * Infos like site name, description etc. is retrieved from general WordPress settings @see https://wordpress.com/support/general-settings/ + * * Full schema see, @see https://github.com/wielebenwir/commons-api/blob/master/commons-api.projects.schema.json */ class ProjectsRoute extends BaseRoute { @@ -52,18 +51,18 @@ public function get_items( $request ): WP_REST_Response { /** * Returns raw data collection. + * * @return object[] */ public function getItemData(): array { return [ (object) [ - "id" => "1", - "name" => get_bloginfo( 'name' ), - "url" => get_bloginfo( 'url' ), - "description" => get_bloginfo( 'description' ), - "language" => get_bloginfo( 'language' ), - ] + 'id' => '1', + 'name' => get_bloginfo( 'name' ), + 'url' => get_bloginfo( 'url' ), + 'description' => get_bloginfo( 'description' ), + 'language' => get_bloginfo( 'language' ), + ], ]; } - } diff --git a/src/API/Share.php b/src/API/Share.php index f030cb0a5..4ce6b250a 100644 --- a/src/API/Share.php +++ b/src/API/Share.php @@ -73,5 +73,4 @@ public function getKey() { public function getOwner() { return $this->owner; } - } diff --git a/src/CB/CB.php b/src/CB/CB.php index 20fd4ff40..179826da6 100644 --- a/src/CB/CB.php +++ b/src/CB/CB.php @@ -21,22 +21,22 @@ public static function getInternalDateFormat(): string { /** * Returns property of (custom) post by class key and property. * - * @param mixed $key - * @param mixed $property + * @param mixed $key + * @param mixed $property * @param \WP_Post|WP_User $wpObject - * @param mixed $args - * @param callable $sanitizeFunction The callable used to remove unwanted tags/characters (use default 'commonsbooking_sanitizeHTML' or 'sanitize_text_field') + * @param mixed $args + * @param callable $sanitizeFunction The callable used to remove unwanted tags/characters (use default 'commonsbooking_sanitizeHTML' or 'sanitize_text_field') * * @return Property of (custom) post (sanitized) or null if not found * @throws Exception */ - public static function get( $key, $property, $wpObject = null, $args = null, $sanitizeFunction = "commonsbooking_sanitizeHTML" ) { + public static function get( $key, $property, $wpObject = null, $args = null, $sanitizeFunction = 'commonsbooking_sanitizeHTML' ) { // Only CustomPost, WP_User or WP_Post ist allowed. if ( $wpObject && ! ( ( $wpObject instanceof WP_Post ) || ( $wpObject instanceof WP_User ) || - ($wpObject instanceof CustomPost) + ( $wpObject instanceof CustomPost ) ) ) { throw new Exception( 'invalid object type.' ); } @@ -44,11 +44,11 @@ public static function get( $key, $property, $wpObject = null, $args = null, $sa // first we need to check if we are dealing with a post and set the post object properly if ( ! $wpObject ) { $postId = self::getPostId( $key ); - $wpObject = get_post($postId); + $wpObject = get_post( $postId ); } // If possible cast to CB Custom Post Type Model to get additional functions - $wpObject = Helper::castToCBCustomType($wpObject, $key); + $wpObject = Helper::castToCBCustomType( $wpObject, $key ); $result = self::lookUp( $key, $property, $wpObject, $args, $sanitizeFunction ); // Find matching methods, properties or metadata $filterName = sprintf( 'commonsbooking_tag_%s_%s', $key, $property ); @@ -83,8 +83,8 @@ private static function getPostId( string $key ): ?int { // If we are dealing with a timeframe and key ist not booking, we may need to look up the CHILDs post meta, not the parents' if ( $initialPostType == 'cb_timeframe' && - $key != Booking::$postType && - $key != 'user' + $key != Booking::$postType && + $key != 'user' ) { $subPostID = get_post_meta( $initialPost->ID, $key . '-id', true ); // item-id, location-id if ( get_post_status( $subPostID ) ) { // Post with that ID exists @@ -99,8 +99,8 @@ private static function getPostId( string $key ): ?int { } /** - * @param string $key - * @param string $property + * @param string $key + * @param string $property * @param $post * @param $args * @param callable $sanitizeFunction The callable used to remove unwanted tags/characters @@ -130,6 +130,7 @@ public static function lookUp( string $key, string $property, $post, $args, $san /** * Tries to get a property of a post with different approaches. + * * @param $post * @param $property * @param $args @@ -139,7 +140,7 @@ public static function lookUp( string $key, string $property, $post, $args, $san private static function getPostProperty( $post, $property, $args ) { $result = null; - $postId = is_int($post) ? $post : $post->ID; + $postId = is_int( $post ) ? $post : $post->ID; if ( get_post_meta( $postId, $property, true ) ) { // Post has meta fields $result = get_post_meta( $postId, $property, true ); @@ -165,7 +166,7 @@ private static function getPostProperty( $post, $property, $args ) { * Tries to get a property of a user with different approaches. * * @param WP_Post|WP_User $post - * @param string $property + * @param string $property * @param $args * * @return int|mixed|null @@ -174,7 +175,7 @@ private static function getPostProperty( $post, $property, $args ) { private static function getUserProperty( $post, string $property, $args ) { $result = null; - $cb_user = self::getUserFromObject($post); + $cb_user = self::getUserFromObject( $post ); if ( method_exists( $cb_user, $property ) ) { $result = $cb_user->$property( $args ); @@ -197,20 +198,19 @@ private static function getUserProperty( $post, string $property, $args ) { * @return false|WP_User * @throws Exception */ - private static function getUserFromObject($object) { + private static function getUserFromObject( $object ) { // Check if $post is of type WP_Post, then we're using Author as User - if( $object instanceof WP_Post) { - $userID = intval( $object->post_author ); + if ( $object instanceof WP_Post ) { + $userID = intval( $object->post_author ); return get_userdata( $userID ); - // Check if $post is of Type WP_User, than we can use it directly. - } else if ( $object instanceof WP_User) { + // Check if $post is of Type WP_User, than we can use it directly. + } elseif ( $object instanceof WP_User ) { return $object; - // Other types than WP_Post or WP_User are not allowed + // Other types than WP_Post or WP_User are not allowed } else { - throw new Exception('invalid $post type.'); + throw new Exception( 'invalid $post type.' ); } } - } diff --git a/src/CB/CB1UserFields.php b/src/CB/CB1UserFields.php index 3b701f952..41b098ed0 100644 --- a/src/CB/CB1UserFields.php +++ b/src/CB/CB1UserFields.php @@ -101,15 +101,13 @@ public function __construct() { ), ); - $this->registration_fields_required = $this->registration_fields; $this->user_fields = $this->get_extra_profile_fields(); - } /* - * Adds the user fields to the wordpress registration + * Adds the user fields to the WordPress registration * * @since 0.6 * @@ -120,7 +118,6 @@ public function __construct() { * * @return array * @since 0.6. - * */ public function get_extra_profile_fields(): array { return $this->extra_profile_fields; @@ -137,29 +134,36 @@ public function get_extra_profile_fields(): array { public function registration_add_fields() { foreach ( $this->user_fields as $field ) { - - $row = ( ! empty( $_POST[ $field['field_name'] ] ) ) ? sanitize_text_field( trim( $_POST[ $field['field_name'] ] ) ): ''; + $row = ( ! empty( $_POST[ $field['field_name'] ] ) ) ? sanitize_text_field( trim( $_POST[ $field['field_name'] ] ) ) : ''; ?> -

        +

        - - get_termsservices_string()); ?> + + get_termsservices_string() ); ?> - + -

        +

        termsservices_url ) ) { + if ( ! empty( $this->termsservices_url ) ) { // translators: %s = terms and service url $string = sprintf( commonsbooking_sanitizeHTML( __( 'Read the terms and services', 'commonsbooking' ) ), commonsbooking_sanitizeHTML( $this->termsservices_url ) ); } else { - $string = ""; + $string = ''; } return $string; @@ -195,18 +198,15 @@ public function get_termsservices_string(): string { public function registration_set_errors( $errors, $username, $email ) { foreach ( $this->user_fields as $field ) { - if ( $field['type'] == 'checkbox' ) { if ( ! isset( $_POST[ $field['field_name'] ] ) ) { $errors->add( $field['field_name'] . '_error', $field['errormessage'] ); } - } else { - if ( + } elseif ( empty( $_POST[ $field['field_name'] ] ) || ! empty( $_POST[ $field['field_name'] ] ) && - sanitize_text_field( trim( $_POST[ $field['field_name'] ] ) == '' ) ){ + sanitize_text_field( trim( $_POST[ $field['field_name'] ] ) == '' ) ) { $errors->add( $field['field_name'] . '_error', $field['errormessage'] ); - } } } @@ -229,7 +229,6 @@ public function registration_add_meta( $user_id ) { * * @since 2.10 deprecated (cb_object_to_array is unspecified) * @since 0.6 - * */ public function set_basic_user_vars( $user_id ) { $user_basic = get_user_by( 'id', $user_id ); @@ -251,7 +250,6 @@ public function set_basic_user_vars( $user_id ) { * Add addiotinal key/value pairs to the user_vars array * * @since 0.5.3 - * */ public function add_user_vars( $key, $value ) { @@ -262,47 +260,52 @@ public function add_user_vars( $key, $value ) { * Backend: Show the extra profile fields * * @since 0.2 - * */ - public function show_extra_profile_fields( $user ) { ?> - -

        - - - - - - - - - - - - - - -
        -
        -
        -
        -
        - - ID ) ) == "yes" ) { - echo "checked"; - } ?> />
        -
        - + +

        + + + + + + + + + + + + + + +
        +
        +
        +
        +
        + + ID ) ) == 'yes' ) { + echo 'checked'; + } + ?> + />
        +
        + redirectUrl = $redirectUrl; } /** * Will get the URL to redirect the user to after a booking is denied. * It is the referrer by default + * * @return string */ public function getRedirectUrl(): string { - if ($this->redirectUrl) { + if ( $this->redirectUrl ) { return $this->redirectUrl; - } - else { + } else { return sanitize_url( wp_get_referer() ); } } - -} \ No newline at end of file +} diff --git a/src/Exception/BookingRuleException.php b/src/Exception/BookingRuleException.php index 8d7f8ed19..63dac2421 100644 --- a/src/Exception/BookingRuleException.php +++ b/src/Exception/BookingRuleException.php @@ -4,4 +4,4 @@ class BookingRuleException extends \Exception { -} \ No newline at end of file +} diff --git a/src/Exception/ExportException.php b/src/Exception/ExportException.php index 70b41f942..75eccdc79 100644 --- a/src/Exception/ExportException.php +++ b/src/Exception/ExportException.php @@ -9,4 +9,4 @@ */ class ExportException extends \Exception { -} \ No newline at end of file +} diff --git a/src/Exception/OverlappingException.php b/src/Exception/OverlappingException.php index bcc089e5b..a1d1a5285 100644 --- a/src/Exception/OverlappingException.php +++ b/src/Exception/OverlappingException.php @@ -2,7 +2,7 @@ namespace CommonsBooking\Exception; -class OverlappingException extends \Exception -{ +class OverlappingException extends \Exception { -} \ No newline at end of file + +} diff --git a/src/Exception/PostException.php b/src/Exception/PostException.php index 79bcdc281..285826fca 100644 --- a/src/Exception/PostException.php +++ b/src/Exception/PostException.php @@ -5,7 +5,7 @@ /** * This exception is thrown when a post is not found or not of the expected type. */ -class PostException extends \Exception -{ +class PostException extends \Exception { -} \ No newline at end of file + +} diff --git a/src/Exception/TimeframeInvalidException.php b/src/Exception/TimeframeInvalidException.php index fdddbb73f..9930d133e 100644 --- a/src/Exception/TimeframeInvalidException.php +++ b/src/Exception/TimeframeInvalidException.php @@ -6,15 +6,13 @@ class TimeframeInvalidException extends \Exception { - public function __construct( $message = "", $code = 0, \Throwable $previous = null ) { - //get immediate caller + public function __construct( $message = '', $code = 0, \Throwable $previous = null ) { + // get immediate caller if ( debug_backtrace()[1]['class'] == Booking::class ) { - $message .= " " . __( "Booking is saved as draft.", 'commonsbooking' ); - } - else { - $message .= " " . __( "Timeframe is saved as draft.", 'commonsbooking' ); + $message .= ' ' . __( 'Booking is saved as draft.', 'commonsbooking' ); + } else { + $message .= ' ' . __( 'Timeframe is saved as draft.', 'commonsbooking' ); } parent::__construct( $message, $code, $previous ); } - -} \ No newline at end of file +} diff --git a/src/Helper/API.php b/src/Helper/API.php index b1e5e900c..e678fb476 100644 --- a/src/Helper/API.php +++ b/src/Helper/API.php @@ -3,38 +3,35 @@ namespace CommonsBooking\Helper; - use CommonsBooking\API\Share; use CommonsBooking\Repository\ApiShares; -class API -{ - - /** - * Triggers requests to all shares with push url. - */ - public static function triggerPushUrls() - { - $apiShares = ApiShares::getAll(); - - foreach ($apiShares as $apiShare) { - if ($apiShare->getPushUrl()) { - self::triggerPushUrl($apiShare); - } - } - } - - /** - * Makes a post request with api-key and owner to the configured push url. - * @param Share $share - */ - public static function triggerPushUrl(Share $share) - { - $requestData = [ - 'API_KEY' => $share->getKey(), - 'OWNER' => $share->getOwner() - ]; - wp_remote_post($share->getPushUrl(), $requestData); - } - -} \ No newline at end of file +class API { + + + /** + * Triggers requests to all shares with push url. + */ + public static function triggerPushUrls() { + $apiShares = ApiShares::getAll(); + + foreach ( $apiShares as $apiShare ) { + if ( $apiShare->getPushUrl() ) { + self::triggerPushUrl( $apiShare ); + } + } + } + + /** + * Makes a post request with api-key and owner to the configured push url. + * + * @param Share $share + */ + public static function triggerPushUrl( Share $share ) { + $requestData = [ + 'API_KEY' => $share->getKey(), + 'OWNER' => $share->getOwner(), + ]; + wp_remote_post( $share->getPushUrl(), $requestData ); + } +} diff --git a/src/Helper/GeoCodeService.php b/src/Helper/GeoCodeService.php index af41f82a9..70d49f2ba 100644 --- a/src/Helper/GeoCodeService.php +++ b/src/Helper/GeoCodeService.php @@ -14,4 +14,4 @@ interface GeoCodeService { * @return Location|null */ public function getAddressData( string $addressString ): ?Location; -} \ No newline at end of file +} diff --git a/src/Helper/GeoHelper.php b/src/Helper/GeoHelper.php index 9dd3b3e0b..e1da017d4 100644 --- a/src/Helper/GeoHelper.php +++ b/src/Helper/GeoHelper.php @@ -34,11 +34,11 @@ public static function getAddressData( $addressString ): ?Location { * * @return void */ - public static function setGeoCodeServiceInstance( GeoCodeService $instance ) : void { + public static function setGeoCodeServiceInstance( GeoCodeService $instance ): void { self::$geoCodeService = $instance; } - public static function resetGeoCoder() : void { - GeoHelper::setGeoCodeServiceInstance( new NominatimGeoCodeService() ); + public static function resetGeoCoder(): void { + self::setGeoCodeServiceInstance( new NominatimGeoCodeService() ); } } diff --git a/src/Helper/Helper.php b/src/Helper/Helper.php index 44ba61940..d8f57cb72 100644 --- a/src/Helper/Helper.php +++ b/src/Helper/Helper.php @@ -19,7 +19,7 @@ public static function generateRandomString( $length = '24' ): string { $characters = '0123456789abcdefghijklmnopqrstuvwxyz'; $charactersLength = strlen( $characters ); $randomString = ''; - for ( $i = 0; $i < $length; $i ++ ) { + for ( $i = 0; $i < $length; $i++ ) { $randomString .= $characters[ rand( 0, $charactersLength - 1 ) ]; } @@ -38,7 +38,6 @@ public static function FormattedDate( $timestamp ) { $date_format = commonsbooking_sanitizeHTML( get_option( 'date_format' ) ); return date_i18n( $date_format, $timestamp ); - } /** @@ -53,7 +52,6 @@ public static function FormattedTime( $timestamp ) { $time_format = commonsbooking_sanitizeHTML( get_option( 'time_format' ) ); return date_i18n( $time_format, $timestamp ); - } /** @@ -65,33 +63,38 @@ public static function FormattedTime( $timestamp ) { */ public static function FormattedDateTime( $timestamp ) { - return Helper::FormattedDate( $timestamp ) . ' ' . Helper::FormattedTime( $timestamp ); + return self::FormattedDate( $timestamp ) . ' ' . self::FormattedTime( $timestamp ); } /** * Returns timestamp of last full hour, needed to get more cache hits. * Also used to determine if a post is still bookable because it is in the past or not. + * * @return int */ public static function getLastFullHourTimestamp() { - $now = current_time('timestamp'); + $now = current_time( 'timestamp' ); return $now - ( $now % 3600 ); } /** * Returns timestamp of last full day, needed to get more cache hits. + * * @param $timestamp * * @return int|mixed|null */ - public static function getLastFullDayTimestamp($timestamp = null) { - if($timestamp === null) $timestamp = current_time('timestamp'); + public static function getLastFullDayTimestamp( $timestamp = null ) { + if ( $timestamp === null ) { + $timestamp = current_time( 'timestamp' ); + } - return $timestamp - ( $timestamp % (3600 * 24) ); + return $timestamp - ( $timestamp % ( 3600 * 24 ) ); } /** * Returns CB custom post type if possible. + * * @param $post * @param $type * @@ -102,10 +105,10 @@ public static function castToCBCustomType( $post, $type ) { if ( $type == \CommonsBooking\Wordpress\CustomPostType\Booking::$postType ) { $post = new Booking( $post->ID ); } - if ( $type == \CommonsBooking\Wordpress\CustomPostType\Item::$postType) { + if ( $type == \CommonsBooking\Wordpress\CustomPostType\Item::$postType ) { $post = new Item( $post->ID ); } - if ( $type == \CommonsBooking\Wordpress\CustomPostType\Location::$postType) { + if ( $type == \CommonsBooking\Wordpress\CustomPostType\Location::$postType ) { $post = new Location( $post->ID ); } @@ -136,7 +139,7 @@ public static function mergeRangesToBookableDates( array $array_of_ranges ): arr // Sort by start date. usort( $array_of_ranges, - function( $a, $b ) { + function ( $a, $b ) { return $a['start_date'] <=> $b['start_date']; } ); @@ -170,12 +173,10 @@ function( $a, $b ) { } else { // => No overlap, add new interval to result. Use as new last interval $result[] = $next_interval; - $last ++; + ++$last; } } return $result; } - - } diff --git a/src/Helper/NominatimGeoCodeService.php b/src/Helper/NominatimGeoCodeService.php index 6657ac103..e0606251e 100644 --- a/src/Helper/NominatimGeoCodeService.php +++ b/src/Helper/NominatimGeoCodeService.php @@ -22,13 +22,13 @@ class NominatimGeoCodeService implements GeoCodeService { * @throws \Exception */ public function getAddressData( $addressString ): ?Location { - + // The Nomination service requires the curl extension to be installed - if (! function_exists('curl_version')) { - throw new \Exception("Could not get address data because of missing curl extension."); + if ( ! function_exists( 'curl_version' ) ) { + throw new \Exception( 'Could not get address data because of missing curl extension.' ); } - $defaultUserAgent = 'CommonsBooking v.' . COMMONSBOOKING_VERSION . " Contact: mail@commonsbooking.org"; + $defaultUserAgent = 'CommonsBooking v.' . COMMONSBOOKING_VERSION . ' Contact: mail@commonsbooking.org'; $client = new Client( null, @@ -56,4 +56,4 @@ public function getAddressData( $addressString ): ?Location { return null; } -} \ No newline at end of file +} diff --git a/src/Helper/Wordpress.php b/src/Helper/Wordpress.php index 883b53c77..22ec0ccaa 100644 --- a/src/Helper/Wordpress.php +++ b/src/Helper/Wordpress.php @@ -36,9 +36,12 @@ public static function getPageListTitle(): array { * @return array|array[]|null[]|WP_Post[] */ public static function flattenWpdbResult( $posts ): array { - return array_map( function ( $post ) { - return get_post( $post->ID ); - }, $posts ); + return array_map( + function ( $post ) { + return get_post( $post->ID ); + }, + $posts + ); } /** @@ -46,20 +49,24 @@ public static function flattenWpdbResult( $posts ): array { * * @return bool|false */ - public static function isValidDateString($dateString): bool { - return preg_match('/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/i',$dateString) === 1; + public static function isValidDateString( $dateString ): bool { + return preg_match( '/^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/i', $dateString ) === 1; } /** * Returns array with IDs. + * * @param $posts * * @return array */ - public static function getPostIdArray($posts): array { - return array_map( function ( $post ) { - return intval($post->ID); - }, $posts); + public static function getPostIdArray( $posts ): array { + return array_map( + function ( $post ) { + return intval( $post->ID ); + }, + $posts + ); } /** @@ -70,100 +77,104 @@ public static function getPostIdArray($posts): array { * * @return array|string[] */ - public static function getRelatedPostIds($postId): array { + public static function getRelatedPostIds( $postId ): array { $postIds = []; - $post = get_post($postId); + $post = get_post( $postId ); - switch ($post->post_type) { + switch ( $post->post_type ) { case Booking::$postType: - $postIds = self::getRelatedPostsIdsForBooking($postId); + $postIds = self::getRelatedPostsIdsForBooking( $postId ); break; case Item::$postType: - $postIds = self::getRelatedPostsIdsForItem($postId); + $postIds = self::getRelatedPostsIdsForItem( $postId ); break; case Location::$postType: - $postIds = self::getRelatedPostsIdsForLocation($postId); + $postIds = self::getRelatedPostsIdsForLocation( $postId ); break; case Restriction::$postType: - $postIds = self::getRelatedPostsIdsForRestriction($postId); + $postIds = self::getRelatedPostsIdsForRestriction( $postId ); break; case \CommonsBooking\Wordpress\CustomPostType\Timeframe::$postType: - $postIds = self::getRelatedPostsIdsForTimeframe($postId); + $postIds = self::getRelatedPostsIdsForTimeframe( $postId ); break; } // Remove empty tags - $postIds = array_filter($postIds); + $postIds = array_filter( $postIds ); return array_map( 'strval', $postIds ); } /** * Returns all post ids in relation to $postId. + * * @param $postId * * @return mixed * @throws \Psr\Cache\InvalidArgumentException */ - public static function getRelatedPostsIdsForLocation($postId) { - $timeframes = \CommonsBooking\Repository\Timeframe::get([$postId]); - $restrictions = \CommonsBooking\Repository\Restriction::get([$postId]); + public static function getRelatedPostsIdsForLocation( $postId ) { + $timeframes = \CommonsBooking\Repository\Timeframe::get( [ $postId ] ); + $restrictions = \CommonsBooking\Repository\Restriction::get( [ $postId ] ); return array_merge( - [$postId], - Wordpress::getPostIdArray($timeframes), - Wordpress::getPostIdArray($restrictions) + [ $postId ], + self::getPostIdArray( $timeframes ), + self::getPostIdArray( $restrictions ) ); } /** * Returns all post ids in relation to $postId. * CAREFUL: This will not get the location that the item is in relation to. + * * @param $postId * * @return array * @throws \Psr\Cache\InvalidArgumentException */ - public static function getRelatedPostsIdsForItem($postId): array { - $timeframes = \CommonsBooking\Repository\Timeframe::get([], [$postId]); - $restrictions = \CommonsBooking\Repository\Restriction::get([], [$postId]); + public static function getRelatedPostsIdsForItem( $postId ): array { + $timeframes = \CommonsBooking\Repository\Timeframe::get( [], [ $postId ] ); + $restrictions = \CommonsBooking\Repository\Restriction::get( [], [ $postId ] ); return array_merge( - [$postId], - Wordpress::getPostIdArray($timeframes), - Wordpress::getPostIdArray($restrictions) + [ $postId ], + self::getPostIdArray( $timeframes ), + self::getPostIdArray( $restrictions ) ); } /** * Returns all post ids in relation to $postId. + * * @param $postId * * @return array * @throws \Exception */ - public static function getRelatedPostsIdsForTimeframe($postId): array { - $timeframe = new Timeframe($postId); - $ids = [$postId]; - return array_merge($ids, $timeframe->getItemIDs(), $timeframe->getLocationIDs() ); + public static function getRelatedPostsIdsForTimeframe( $postId ): array { + $timeframe = new Timeframe( $postId ); + $ids = [ $postId ]; + return array_merge( $ids, $timeframe->getItemIDs(), $timeframe->getLocationIDs() ); } /** * Returns all post ids in relation to $postId. + * * @param $postId * * @return array * @throws \Exception */ - public static function getRelatedPostsIdsForBooking($postId): array { - $booking = new \CommonsBooking\Model\Booking($postId); - $ids = [$postId]; + public static function getRelatedPostsIdsForBooking( $postId ): array { + $booking = new \CommonsBooking\Model\Booking( $postId ); + $ids = [ $postId ]; - if($booking->getItem()) { + if ( $booking->getItem() ) { $ids[] = $booking->getItemID(); } - if($booking->getLocation()) { + if ( $booking->getLocation() ) { $ids[] = $booking->getLocationID(); } - if($booking->getBookableTimeFrame()) { + if ( $booking->getBookableTimeFrame() ) { $ids[] = $booking->getBookableTimeFrame()->ID; } @@ -178,28 +189,28 @@ public static function getRelatedPostsIdsForBooking($postId): array { * @return array * @throws \Psr\Cache\InvalidArgumentException */ - public static function getRelatedPostsIdsForRestriction($postId): array { - $restriction = new \CommonsBooking\Model\Restriction($postId); + public static function getRelatedPostsIdsForRestriction( $postId ): array { + $restriction = new \CommonsBooking\Model\Restriction( $postId ); // Restriction itself $relatedPostIds = [ $postId ]; // Item and related timeframes - if($itemId = $restriction->getItemId()) { - $timeframes = \CommonsBooking\Repository\Timeframe::get([], [$itemId]); + if ( $itemId = $restriction->getItemId() ) { + $timeframes = \CommonsBooking\Repository\Timeframe::get( [], [ $itemId ] ); $relatedPostIds[] = $itemId; - $relatedPostIds = array_merge($relatedPostIds, Wordpress::getPostIdArray($timeframes)); + $relatedPostIds = array_merge( $relatedPostIds, self::getPostIdArray( $timeframes ) ); } // Location and related timeframes - if($locationId = $restriction->getLocationId()) { - $timeframes = \CommonsBooking\Repository\Timeframe::get([$locationId]); + if ( $locationId = $restriction->getLocationId() ) { + $timeframes = \CommonsBooking\Repository\Timeframe::get( [ $locationId ] ); $relatedPostIds[] = $locationId; - $relatedPostIds = array_merge($relatedPostIds, Wordpress::getPostIdArray($timeframes)); + $relatedPostIds = array_merge( $relatedPostIds, self::getPostIdArray( $timeframes ) ); } return array_unique( - array_map( 'intval', $relatedPostIds) + array_map( 'intval', $relatedPostIds ) ); } @@ -212,20 +223,22 @@ public static function getRelatedPostsIdsForRestriction($postId): array { * * @return array */ - public static function getTags($posts, array $items = [], array $locations = []): array { - $itemsAndLocations = Wordpress::getLocationAndItemIdsFromPosts($posts); + public static function getTags( $posts, array $items = [], array $locations = [] ): array { + $itemsAndLocations = self::getLocationAndItemIdsFromPosts( $posts ); - if(!count($items) && !count($locations)) { + if ( ! count( $items ) && ! count( $locations ) ) { $items[] = 'misc'; } - return array_values(array_unique( + return array_values( + array_unique( array_merge( - Wordpress::getPostIdArray($posts), + self::getPostIdArray( $posts ), $itemsAndLocations, $items, $locations - )) + ) + ) ); } @@ -233,32 +246,35 @@ public static function getTags($posts, array $items = [], array $locations = []) * Returns an array of post ids of locations and items from posts. * The only posts that have items / locations assinged are timeframes and bookings. * Any other posts are skipped. + * * @param $posts * * @return array */ - public static function getLocationAndItemIdsFromPosts(array $posts): array { + public static function getLocationAndItemIdsFromPosts( array $posts ): array { $itemsAndLocations = []; - array_walk($posts, function ($timeframe) use (&$itemsAndLocations) { - //only run for timeframe or booking - if ( ! in_array( $timeframe->post_type, [ \CommonsBooking\Wordpress\CustomPostType\Timeframe::$postType, Booking::$postType ] ) ) { - return; - } - if (! $timeframe instanceof Timeframe) { - if ( $timeframe->post_type == Booking::$postType ) { - $timeframe = new \CommonsBooking\Model\Booking( $timeframe ); + array_walk( + $posts, + function ( $timeframe ) use ( &$itemsAndLocations ) { + // only run for timeframe or booking + if ( ! in_array( $timeframe->post_type, [ \CommonsBooking\Wordpress\CustomPostType\Timeframe::$postType, Booking::$postType ] ) ) { + return; } - elseif ( $timeframe->post_type == \CommonsBooking\Wordpress\CustomPostType\Timeframe::$postType ) { - $timeframe = new Timeframe( $timeframe ); + if ( ! $timeframe instanceof Timeframe ) { + if ( $timeframe->post_type == Booking::$postType ) { + $timeframe = new \CommonsBooking\Model\Booking( $timeframe ); + } elseif ( $timeframe->post_type == \CommonsBooking\Wordpress\CustomPostType\Timeframe::$postType ) { + $timeframe = new Timeframe( $timeframe ); + } } + $itemsAndLocations = array_merge( + $itemsAndLocations, + $timeframe->getItemIDs(), + $timeframe->getLocationIDs() + ); } - $itemsAndLocations = array_merge( - $itemsAndLocations, - $timeframe->getItemIDs(), - $timeframe->getLocationIDs() - ); - }); - return array_map('intval', $itemsAndLocations); + ); + return array_map( 'intval', $itemsAndLocations ); } /** @@ -271,12 +287,12 @@ public static function getLocationAndItemIdsFromPosts(array $posts): array { * @return DateTime * @throws \Exception */ - public static function getUTCDateTimeByTimestamp($timestamp): DateTime { + public static function getUTCDateTimeByTimestamp( $timestamp ): DateTime { $dto = new DateTime(); $dto->setTimestamp( intval( $timestamp ) ); - $dto->setTimezone(new \DateTimeZone('UTC')); + $dto->setTimezone( new \DateTimeZone( 'UTC' ) ); return $dto; } @@ -297,19 +313,19 @@ public static function convertTimestampToUTCDatetime( $timestamp ) { return $dto; } - public static function getUTCDateTime($datetime = 'now'): DateTime { - $dto = new DateTime($datetime); - $dto->setTimezone(new \DateTimeZone('UTC')); + public static function getUTCDateTime( $datetime = 'now' ): DateTime { + $dto = new DateTime( $datetime ); + $dto->setTimezone( new \DateTimeZone( 'UTC' ) ); return $dto; } - public static function getLocalDateTime($timestamp): DateTime { + public static function getLocalDateTime( $timestamp ): DateTime { $dto = new DateTime(); $dto->setTimestamp( $timestamp ); - $dto->setTimezone(new \DateTimeZone(wp_timezone_string())); + $dto->setTimezone( new \DateTimeZone( wp_timezone_string() ) ); return $dto; } diff --git a/src/Map/BaseShortcode.php b/src/Map/BaseShortcode.php index 8c06d1690..91d152ade 100644 --- a/src/Map/BaseShortcode.php +++ b/src/Map/BaseShortcode.php @@ -19,28 +19,28 @@ final public function __construct() { } **/ public static function execute( array $atts, string $content = "" ): string { $instance = new static(); - $attrs = $instance->parse_attributes($atts); - $options = array_filter($atts, "is_int", ARRAY_FILTER_USE_KEY); + $attrs = $instance->parse_attributes( $atts ); + $options = array_filter( $atts, 'is_int', ARRAY_FILTER_USE_KEY ); - if (! (int) $attrs['id']) { - return '
        ' . esc_html__('no valid map id provided', 'commonsbooking') . '
        '; + if ( ! (int) $attrs['id'] ) { + return '
        ' . esc_html__( 'no valid map id provided', 'commonsbooking' ) . '
        '; } - $post = get_post($attrs['id']); + $post = get_post( $attrs['id'] ); - if (!($post && $post->post_type == 'cb_map')) { - return '
        ' . esc_html__('no valid map id provided', 'commonsbooking') . '
        '; + if ( ! ( $post && $post->post_type == 'cb_map' ) ) { + return '
        ' . esc_html__( 'no valid map id provided', 'commonsbooking' ) . '
        '; } - if ($post->post_status != 'publish') { - return '
        ' . esc_html__('map is not published', 'commonsbooking') . '
        '; + if ( $post->post_status != 'publish' ) { + return '
        ' . esc_html__( 'map is not published', 'commonsbooking' ) . '
        '; } $cb_map_id = $post->ID; - $instance->inject_script($cb_map_id); - return $instance->create_container($cb_map_id, $attrs, $options, $content); + $instance->inject_script( $cb_map_id ); + return $instance->create_container( $cb_map_id, $attrs, $options, $content ); } - abstract protected function parse_attributes($atts); - abstract protected function inject_script($cb_map_id); - abstract protected function create_container($cb_map_id, $attrs, $options, $content); -} \ No newline at end of file + abstract protected function parse_attributes( $atts ); + abstract protected function inject_script( $cb_map_id ); + abstract protected function create_container( $cb_map_id, $attrs, $options, $content ); +} diff --git a/src/Map/LocationMapAdmin.php b/src/Map/LocationMapAdmin.php index 827b516a5..366acb298 100644 --- a/src/Map/LocationMapAdmin.php +++ b/src/Map/LocationMapAdmin.php @@ -15,5 +15,4 @@ public function load_location_map_admin() { add_action( 'cmb2_render_cb_map', array( Map::class, 'render_cb_map' ), 10, 5 ); } } - } diff --git a/src/Map/MapData.php b/src/Map/MapData.php index 96404c1a0..bc5761ceb 100644 --- a/src/Map/MapData.php +++ b/src/Map/MapData.php @@ -8,23 +8,20 @@ class MapData { public static function geo_search() { if ( isset( $_POST['query'] ) && $_POST['cb_map_id'] ) { - $map = new Map( $_POST['cb_map_id'] ); - $check_capacity = true; $attempts = 0; - //because requests to nominatim are limited (max 1/s), we have to check for timestamp of last one and loop for a while, if needed + // because requests to nominatim are limited (max 1/s), we have to check for timestamp of last one and loop for a while, if needed while ( $check_capacity ) { - if ( $attempts > 10 ) { wp_send_json_error( [ 'error' => 5 ], 408 ); wp_die(); } - $attempts ++; + ++$attempts; $last_call_timestamp = commonsbooking_sanitizeHTML( get_option( 'cb_map_last_nominatim_call', 0 ) ); $current_timestamp = time(); @@ -45,9 +42,8 @@ public static function geo_search() { ]; if ( $map->getMeta( 'address_search_bounds_left_bottom_lat' ) && $map->getMeta( 'address_search_bounds_left_bottom_lon' ) && $map->getMeta( 'address_search_bounds_right_top_lat' ) && $map->getMeta( 'address_search_bounds_right_top_lon' ) ) { - $params['bounded'] = 1; - //viewbox - lon1, lat1, lon2, lat2: 12.856779316446545, 52.379790828551016, 13.948545673868422, 52.79694936237738 + // viewbox - lon1, lat1, lon2, lat2: 12.856779316446545, 52.379790828551016, 13.948545673868422, 52.79694936237738 $params['viewbox'] = $map->getMeta( 'address_search_bounds_left_bottom_lon' ) . ',' . $map->getMeta( 'address_search_bounds_left_bottom_lat' ) . ',' . $map->getMeta( 'address_search_bounds_right_top_lon' ) . ',' . $map->getMeta( 'address_search_bounds_right_top_lat' ); } @@ -61,19 +57,16 @@ public static function geo_search() { if ( is_wp_error( $data ) ) { wp_send_json_error( [ 'error' => 2 ], 404 ); - } else { - if ( $data['response']['code'] == 200 ) { - + } elseif ( $data['response']['code'] == 200 ) { json_decode( $data['body'] ); // Check if the json is valid - if ( json_last_error() == JSON_ERROR_NONE ) { - wp_send_json( $data['body'] ); - } else { - wp_send_json_error( [ 'error' => 4 ], 403 ); - } + if ( json_last_error() == JSON_ERROR_NONE ) { + wp_send_json( $data['body'] ); } else { - wp_send_json_error( [ 'error' => 3 ], 404 ); + wp_send_json_error( [ 'error' => 4 ], 403 ); } + } else { + wp_send_json_error( [ 'error' => 3 ], 404 ); } } else { wp_send_json_error( [ 'error' => 1 ], 400 ); @@ -86,7 +79,7 @@ public static function geo_search() { * the ajax request handler for locations **/ public static function get_locations() { - //handle local/import map + // handle local/import map if ( isset( $_POST['cb_map_id'] ) ) { check_ajax_referer( 'cb_map_locations', 'nonce' ); @@ -106,7 +99,6 @@ public static function get_locations() { wp_die(); } - if ( $post->post_status == 'publish' ) { $map = new Map( $cb_map_id ); $settings = self::get_settings( $cb_map_id ); @@ -115,7 +107,7 @@ public static function get_locations() { $itemTerms = self::getItemCategoryTerms( $settings ); $locations = $map->get_locations( $itemTerms ); - //create availabilities + // create availabilities $show_item_availability = $map->getMeta( 'show_item_availability' ); $show_item_availability_filter = $map->getMeta( 'show_item_availability_filter' ); @@ -123,10 +115,11 @@ public static function get_locations() { $locations = MapItemAvailable::create_items_availabilities( $locations, $default_date_start, - $default_date_end ); + $default_date_end + ); } - $locations = array_values( $locations ); //locations to indexed array + $locations = array_values( $locations ); // locations to indexed array $locations = Map::cleanup_location_data( $locations, '
        ' ); header( 'Content-Type: application/json' ); @@ -140,6 +133,7 @@ public static function get_locations() { /** * Returns configured item terms + * * @return array */ public static function getItemCategoryTerms( $settings ): array { @@ -233,11 +227,11 @@ public static function get_settings( $cb_map_id ): array { 'iconUrl' => wp_get_attachment_url( $map->getMeta( 'custom_marker_media_id' ) ), 'iconSize' => [ intval( $map->getMeta( 'marker_icon_width' ) ), - intval( $map->getMeta( 'marker_icon_height' ) ) + intval( $map->getMeta( 'marker_icon_height' ) ), ], 'iconAnchor' => [ intval( $map->getMeta( 'marker_icon_anchor_x' ) ), - intval( $map->getMeta( 'marker_icon_anchor_y' ) ) + intval( $map->getMeta( 'marker_icon_anchor_y' ) ), ], ]; } @@ -247,11 +241,11 @@ public static function get_settings( $cb_map_id ): array { 'iconUrl' => wp_get_attachment_url( $map->getMeta( 'marker_item_draft_media_id' ) ), 'iconSize' => [ intval( $map->getMeta( 'marker_item_draft_icon_width' ) ), - intval( $map->getMeta( 'marker_item_draft_icon_height' ) ) + intval( $map->getMeta( 'marker_item_draft_icon_height' ) ), ], 'iconAnchor' => [ intval( $map->getMeta( 'marker_item_draft_icon_anchor_x' ) ), - intval( $map->getMeta( 'marker_item_draft_icon_anchor_y' ) ) + intval( $map->getMeta( 'marker_item_draft_icon_anchor_y' ) ), ], ]; } @@ -266,8 +260,8 @@ public static function get_settings( $cb_map_id ): array { ]; } - //categories are only meant to be shown on local maps - //TODO: Evaluate if it makes sense to only show them when categories are imported + // categories are only meant to be shown on local maps + // TODO: Evaluate if it makes sense to only show them when categories are imported if ( $map->getMeta( 'cb_items_available_categories' ) ) { $settings['filter_cb_item_categories'] = []; @@ -283,9 +277,9 @@ public static function get_settings( $cb_map_id ): array { 'markup' => $termName, ]; } - $isExclusive = $group['isExclusive'] ?? 'off'; + $isExclusive = $group['isExclusive'] ?? 'off'; $settings['filter_cb_item_categories'][ $groupID ] = [ - 'name' => $group['name'] ?? "", + 'name' => $group['name'] ?? '', 'elements' => $elements, 'isExclusive' => $isExclusive == 'on', ]; @@ -293,4 +287,4 @@ public static function get_settings( $cb_map_id ): array { } return $settings; } -} \ No newline at end of file +} diff --git a/src/Map/MapFilter.php b/src/Map/MapFilter.php index 4d7fdc1f0..247de24c2 100644 --- a/src/Map/MapFilter.php +++ b/src/Map/MapFilter.php @@ -12,7 +12,7 @@ protected static function check_item_terms_against_categories( $item_terms, $cat foreach ( $category_groups as $group ) { foreach ( $item_terms as $term ) { if ( in_array( $term->term_id, $group ) ) { - $valid_groups_count ++; + ++$valid_groups_count; break; } } @@ -20,4 +20,4 @@ protected static function check_item_terms_against_categories( $item_terms, $cat return $valid_groups_count == count( $category_groups ); } -} \ No newline at end of file +} diff --git a/src/Map/MapItemAvailable.php b/src/Map/MapItemAvailable.php index 0af8e1581..e85069193 100644 --- a/src/Map/MapItemAvailable.php +++ b/src/Map/MapItemAvailable.php @@ -70,19 +70,19 @@ public static function create_items_availabilities( $locations, $date_start, $da $availability = []; foreach ( $filter_period as $date ) { $availability[] = [ - "date" => $date->format( 'Y-m-d' ), - "status" => self::OUT_OF_TIMEFRAME, + 'date' => $date->format( 'Y-m-d' ), + 'status' => self::OUT_OF_TIMEFRAME, ]; } - $calendarData = Calendar::getCalendarDataArray( - $item['id'], - $location_id, - $startDay->getFormattedDate( 'Y-m-d' ), - $endDay->getFormattedDate( 'Y-m-d' ), - ); + $calendarData = Calendar::getCalendarDataArray( + $item['id'], + $location_id, + $startDay->getFormattedDate( 'Y-m-d' ), + $endDay->getFormattedDate( 'Y-m-d' ), + ); - //mark days in timeframe + // mark days in timeframe $availability = self::markDaysInTimeframe( $calendarData, $availability ); $item['availability'] = $availability; @@ -111,21 +111,21 @@ public static function create_items_availabilities( $locations, $date_start, $da * @return mixed */ protected static function markDaysInTimeframe( $calendarData, $availabilities ) { - //mark days which are inside a timeframe + // mark days which are inside a timeframe foreach ( $availabilities as &$availability ) { if ( array_key_exists( $availability['date'], $calendarData['days'] ) ) { $day = $calendarData['days'][ $availability['date'] ]; - if (! count( $day['slots'])){ + if ( ! count( $day['slots'] ) ) { $availability['status'] = self::ITEM_LOCKED; - }elseif ( $day['holiday']) { + } elseif ( $day['holiday'] ) { $availability['status'] = self::LOCATION_HOLIDAY; - } elseif ($day['locked'] && $day['firstSlotBooked'] && $day['lastSlotBooked']){ + } elseif ( $day['locked'] && $day['firstSlotBooked'] && $day['lastSlotBooked'] ) { $availability['status'] = self::ITEM_BOOKED; - } elseif ( $day['locked'] && $day['partiallyBookedDay']) { + } elseif ( $day['locked'] && $day['partiallyBookedDay'] ) { $availability['status'] = self::ITEM_PARTIALLY_BOOKED; - } elseif ( $day['locked'] ) { - $availability['status'] = self::ITEM_LOCKED; - } else { + } elseif ( $day['locked'] ) { + $availability['status'] = self::ITEM_LOCKED; + } else { $availability['status'] = self::ITEM_AVAILABLE; } } @@ -133,5 +133,4 @@ protected static function markDaysInTimeframe( $calendarData, $availabilities ) return $availabilities; } - } diff --git a/src/Map/MapShortcode.php b/src/Map/MapShortcode.php index 451978dfa..a034da6d1 100644 --- a/src/Map/MapShortcode.php +++ b/src/Map/MapShortcode.php @@ -20,14 +20,16 @@ protected function parse_attributes( $atts ) { } protected function inject_script( $cb_map_id ) { - wp_add_inline_script( 'cb-map-shortcode', - "jQuery(document).ready(function ($) { + wp_add_inline_script( + 'cb-map-shortcode', + 'jQuery(document).ready(function ($) { var cb_map = new CB_Map(); - cb_map.settings = " . wp_json_encode( MapData::get_settings( $cb_map_id ) ) . "; - cb_map.translation = " . wp_json_encode( $this->get_translation( $cb_map_id ) ) . "; + cb_map.settings = ' . wp_json_encode( MapData::get_settings( $cb_map_id ) ) . '; + cb_map.translation = ' . wp_json_encode( $this->get_translation( $cb_map_id ) ) . '; cb_map.init_filters($); cb_map.init_map(); - });" ); + });' + ); wp_enqueue_style( 'cb-map-shortcode' ); wp_enqueue_script( 'cb-map-shortcode' ); } @@ -63,4 +65,4 @@ private function get_translation( $cb_map_id ): array { 'COMING_SOON' => esc_html__( 'comming soon', 'commonsbooking' ), ]; } -} \ No newline at end of file +} diff --git a/src/Map/SearchShortcode.php b/src/Map/SearchShortcode.php index ec9a0cfb1..566f020d7 100644 --- a/src/Map/SearchShortcode.php +++ b/src/Map/SearchShortcode.php @@ -9,25 +9,29 @@ class SearchShortcode extends BaseShortcode { protected $processed_map_ids = []; protected function parse_attributes( $atts ) { - return shortcode_atts([ - 'id' => null, - 'layouts' => 'Filter,MapWithAutoSidebar', - ], $atts); + return shortcode_atts( + [ + 'id' => null, + 'layouts' => 'Filter,MapWithAutoSidebar', + ], + $atts + ); } protected function inject_script( $cb_map_id ) { - wp_enqueue_style('cb-commons-search'); - wp_enqueue_script('cb-commons-search'); + wp_enqueue_style( 'cb-commons-search' ); + wp_enqueue_script( 'cb-commons-search' ); } protected function create_container( $cb_map_id, $attrs, $options, $content ) { // Ensure that the api and config object are only created once per page and per map - if (!in_array($cb_map_id, $this->processed_map_ids)) { - $settings = MapData::get_settings($cb_map_id); - $admin_ajax_url = wp_json_encode(pop_key($settings, 'data_url')); - $nonce = wp_json_encode(pop_key($settings, 'nonce')); - $data_loader = trim(" - const config = CommonsSearch.parseLegacyConfig(" . wp_json_encode($settings) . "); + if ( ! in_array( $cb_map_id, $this->processed_map_ids ) ) { + $settings = MapData::get_settings( $cb_map_id ); + $admin_ajax_url = wp_json_encode( pop_key( $settings, 'data_url' ) ); + $nonce = wp_json_encode( pop_key( $settings, 'nonce' ) ); + $data_loader = trim( + ' + const config = CommonsSearch.parseLegacyConfig(' . wp_json_encode( $settings ) . "); const api = CommonsSearch.createAdminAjaxAPI({ url: $admin_ajax_url, nonce: $nonce, @@ -35,24 +39,27 @@ protected function create_container( $cb_map_id, $attrs, $options, $content ) { }, config); if (!window.__CB_SEARCH_DATA) window.__CB_SEARCH_DATA = {}; window.__CB_SEARCH_DATA[$cb_map_id] = { config, api }; - "); + " + ); $this->processed_map_ids[] = $cb_map_id; } else { $data_loader = "const { config, api } = window.__CB_SEARCH_DATA[$cb_map_id];"; } - $content = trim(strip_tags($content)); - $content_is_config = $content && is_object(json_decode($content)) && json_last_error() == JSON_ERROR_NONE; - if ($content_is_config) { + $content = trim( strip_tags( $content ) ); + $content_is_config = $content && is_object( json_decode( $content ) ) && json_last_error() == JSON_ERROR_NONE; + if ( $content_is_config ) { $user_config = "const userConfig = $content;"; } else { - $user_config = "const userConfig = {};"; + $user_config = 'const userConfig = {};'; } - $layout_config = wp_json_encode(array( - 'types' => array_map('trim', explode(',', $attrs['layouts'])), - 'options' => $options, - )); + $layout_config = wp_json_encode( + array( + 'types' => array_map( 'trim', explode( ',', $attrs['layouts'] ) ), + 'options' => $options, + ) + ); $init_script = "(function (el) { document.addEventListener('DOMContentLoaded', function() { @@ -66,8 +73,8 @@ protected function create_container( $cb_map_id, $attrs, $options, $content ) { } } -function pop_key (&$array, $key) { - $value = $array[$key]; - unset($array[$key]); +function pop_key( &$array, $key ) { + $value = $array[ $key ]; + unset( $array[ $key ] ); return $value; -} \ No newline at end of file +} diff --git a/src/Messages/AdminMessage.php b/src/Messages/AdminMessage.php index 857c0805c..d25f0fe45 100644 --- a/src/Messages/AdminMessage.php +++ b/src/Messages/AdminMessage.php @@ -42,5 +42,4 @@ public function render() { echo '

        '; echo ''; } - -} \ No newline at end of file +} diff --git a/src/Messages/BookingCodesMessage.php b/src/Messages/BookingCodesMessage.php index 63263bdb3..0fc7c9013 100644 --- a/src/Messages/BookingCodesMessage.php +++ b/src/Messages/BookingCodesMessage.php @@ -19,67 +19,85 @@ */ class BookingCodesMessage extends Message { - protected $validActions = [ "codes" ]; - protected $to; - private ?int $tsFrom; - private ?int $tsTo; - private ?array $locationAdmins; + protected $validActions = [ 'codes' ]; + protected $to; + private ?int $tsFrom; + private ?int $tsTo; + private ?array $locationAdmins; /** * @param int /post $postId ID or Post of timeframe - * @param string $action Message action - * @param int|null $tsFrom Timestamp of first Booking Code - * @param int|null $tsTo Timestamp of last Booking Code + * @param string $action Message action + * @param int|null $tsFrom Timestamp of first Booking Code + * @param int|null $tsTo Timestamp of last Booking Code + */ + public function __construct( $postId, string $action, int $tsFrom = null, int $tsTo = null ) { + parent::__construct( $postId, $action ); + $this->tsFrom = $tsFrom; + $this->tsTo = $tsTo; + } + + /** + * prepares Message and sends by E-mail + * + * @return bool true if message was sent, false otherwise. If the message is not sent, an error is raised. */ - public function __construct( $postId, string $action, int $tsFrom=null, int $tsTo=null ) { - parent::__construct($postId, $action); - $this->tsFrom=$tsFrom; - $this->tsTo=$tsTo; - } - - /** - * prepares Message and sends by E-mail - * - * @return bool true if message was sent, false otherwise. If the message is not sent, an error is raised. - */ public function sendMessage(): bool { - $timeframeId=(int)$this->getPostId(); - $timeframe=new Timeframe($timeframeId); - - if(!$this->prepareReceivers($timeframe)) return $this->raiseError( - __( "Unable to send Emails. No location email(s) configured, check location", "commonsbooking" )); - - $bookingCodes = BookingCodes::getCodes($timeframeId, $this->tsFrom,$this->tsTo); - if(empty($bookingCodes)) return $this->raiseError( __( "Could not find booking codes for this timeframe/period", "commonsbooking" )); - - $bookingTable=apply_filters('commonsbooking_emailcodes_rendertable', - \CommonsBooking\View\BookingCodes::renderBookingCodesTable( $bookingCodes ), - $bookingCodes,'email'); - - $bAddIcal=apply_filters('commonsbooking_emailcodes_addical', - Settings::getOption( 'commonsbooking_options_bookingcodes', 'mail-booking-' . $this->action . '-attach-ical' ), - $timeframe); - $attachment=$bAddIcal?$this->getIcalAttachment($bookingCodes):null; - - //Workaround: arbitrary object for template parser - $codes=new \WP_User((object)array( "ID" => -1)); - $codes->codeTable=$bookingTable; - - $dispTo= wp_date("M-Y",strtotime(end($bookingCodes)->getDate())); - $dispFrom= wp_date("M-Y",strtotime(reset($bookingCodes)->getDate())); - $codes->formatDateRange=($dispFrom == $dispTo)?$dispFrom:$dispFrom . " - " . $dispTo; + $timeframeId = (int) $this->getPostId(); + $timeframe = new Timeframe( $timeframeId ); + + if ( ! $this->prepareReceivers( $timeframe ) ) { + return $this->raiseError( + __( 'Unable to send Emails. No location email(s) configured, check location', 'commonsbooking' ) + ); + } + + $bookingCodes = BookingCodes::getCodes( $timeframeId, $this->tsFrom, $this->tsTo ); + if ( empty( $bookingCodes ) ) { + return $this->raiseError( __( 'Could not find booking codes for this timeframe/period', 'commonsbooking' ) ); + } + + $bookingTable = apply_filters( + 'commonsbooking_emailcodes_rendertable', + \CommonsBooking\View\BookingCodes::renderBookingCodesTable( $bookingCodes ), + $bookingCodes, + 'email' + ); + + $bAddIcal = apply_filters( + 'commonsbooking_emailcodes_addical', + Settings::getOption( 'commonsbooking_options_bookingcodes', 'mail-booking-' . $this->action . '-attach-ical' ), + $timeframe + ); + $attachment = $bAddIcal ? $this->getIcalAttachment( $bookingCodes ) : null; + + // Workaround: arbitrary object for template parser + $codes = new \WP_User( (object) array( 'ID' => -1 ) ); + $codes->codeTable = $bookingTable; + + $dispTo = wp_date( 'M-Y', strtotime( end( $bookingCodes )->getDate() ) ); + $dispFrom = wp_date( 'M-Y', strtotime( reset( $bookingCodes )->getDate() ) ); + $codes->formatDateRange = ( $dispFrom == $dispTo ) ? $dispFrom : $dispFrom . ' - ' . $dispTo; // get templates from Admin Options - $template_body = Settings::getOption( 'commonsbooking_options_bookingcodes', - 'mail-booking-' . $this->action . '-body' ); - $template_subject = Settings::getOption( 'commonsbooking_options_bookingcodes', - 'mail-booking-' . $this->action . '-subject' ); - $template_bcc = sanitize_email(Settings::getOption( 'commonsbooking_options_bookingcodes', - 'mail-booking-' . $this->action . '-bcc' )); + $template_body = Settings::getOption( + 'commonsbooking_options_bookingcodes', + 'mail-booking-' . $this->action . '-body' + ); + $template_subject = Settings::getOption( + 'commonsbooking_options_bookingcodes', + 'mail-booking-' . $this->action . '-subject' + ); + $template_bcc = sanitize_email( + Settings::getOption( + 'commonsbooking_options_bookingcodes', + 'mail-booking-' . $this->action . '-bcc' + ) + ); // Setup email: From $fromHeaders = sprintf( - "From: %s <%s>", + 'From: %s <%s>', Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-name' ), sanitize_email( Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-email' ) ) ); @@ -91,61 +109,60 @@ public function sendMessage(): bool { $fromHeaders, $template_bcc, [ - 'codes' => $codes, - 'item' => $timeframe->getItem(), - 'location' => $timeframe->getLocation(), - ], + 'codes' => $codes, + 'item' => $timeframe->getItem(), + 'location' => $timeframe->getLocation(), + ], $attachment ); - - add_action( 'commonsbooking_mail_sent',array($this,'updateEmailSent'), 5, 2 ); - - if(count($this->locationAdmins) > 1) { - add_filter('commonsbooking_mail_to', array($this,'addMultiTo'), 25); - $this->SendNotificationMail(); - remove_filter('commonsbooking_mail_to', array($this,'addMultiTo'), 25); - } - else - $this->SendNotificationMail(); - - remove_action( 'commonsbooking_mail_sent',array($this,'updateEmailSent'), 5 ); - - return true; - } + + add_action( 'commonsbooking_mail_sent', array( $this, 'updateEmailSent' ), 5, 2 ); + + if ( count( $this->locationAdmins ) > 1 ) { + add_filter( 'commonsbooking_mail_to', array( $this, 'addMultiTo' ), 25 ); + $this->sendNotificationMail(); + remove_filter( 'commonsbooking_mail_to', array( $this, 'addMultiTo' ), 25 ); + } else { + $this->sendNotificationMail(); + } + + remove_action( 'commonsbooking_mail_sent', array( $this, 'updateEmailSent' ), 5 ); + + return true; + } /** * Updates the information about the last sent email. * This is triggered through the commonsbooking_mail_sent action. * - * * @param $action * @param $result * * @return void */ - public function updateEmailSent($action,$result) - { - if($this->action != $action) return; - - if($result === true) - { - update_post_meta( (int)$this->getPostId(), \CommonsBooking\View\BookingCodes::LAST_CODES_EMAIL, time() ); - } - - } - - /** + public function updateEmailSent( $action, $result ) { + if ( $this->action != $action ) { + return; + } + + if ( $result === true ) { + update_post_meta( (int) $this->getPostId(), \CommonsBooking\View\BookingCodes::LAST_CODES_EMAIL, time() ); + } + } + + /** * filter commonsbooking_mail_to for adding multiple to email addresses - * - * @return array - */ - public function addMultiTo(): array { - $to=array(); - foreach($this->locationAdmins as $admin) - $to[]=sprintf( '%s <%s>', $admin->user_nicename, $admin->user_email ); + * + * @return array + */ + public function addMultiTo(): array { + $to = array(); + foreach ( $this->locationAdmins as $admin ) { + $to[] = sprintf( '%s <%s>', $admin->user_nicename, $admin->user_email ); + } - return $to; - } + return $to; + } /** * builds e-mail receivers by creating dummy WP_User objects from location emails @@ -156,51 +173,55 @@ public function addMultiTo(): array { * * @return bool */ - protected function prepareReceivers(Timeframe $timeframe): bool { - $dummy_id=-2; - $location_emails = CB::get( Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email', $timeframe->getLocation() ) ; /* email addresses, comma-seperated */ - if(!empty($location_emails)) { - foreach(array_map('trim', explode(',', $location_emails)) as $email) { - $dUser=$this->locationAdmins[]=new \WP_User((object)array( "ID" => $dummy_id--)); - $dUser->user_nicename=''; - $dUser->user_email=$email; - } - } - - return !empty($this->locationAdmins); - } - - /** + protected function prepareReceivers( Timeframe $timeframe ): bool { + $dummy_id = -2; + $location_emails = CB::get( Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email', $timeframe->getLocation() ); /* email addresses, comma-seperated */ + if ( ! empty( $location_emails ) ) { + foreach ( array_map( 'trim', explode( ',', $location_emails ) ) as $email ) { + $dUser = $this->locationAdmins[] = new \WP_User( (object) array( 'ID' => $dummy_id-- ) ); + $dUser->user_nicename = ''; + $dUser->user_email = $email; + } + } + + return ! empty( $this->locationAdmins ); + } + + /** * generates iCalendar attachment with all requested booking codes * - * @param BookingCode[] $bookingCodes List of BookingCode objects - * - * @return array - */ - protected function getIcalAttachment( array $bookingCodes): array { + * @param BookingCode[] $bookingCodes List of BookingCode objects + * + * @return array + */ + protected function getIcalAttachment( array $bookingCodes ): array { $calendar = new iCalendar(); - foreach($bookingCodes as $bookingCode) { - $title=apply_filters('commonsbooking_emailcodes_icalevent_title', - $bookingCode->getItemName() . " (" . $bookingCode->getCode() . ")", $bookingCode); - $desc=apply_filters('commonsbooking_emailcodes_icalevent_desc', - sprintf( __( 'booking code for item "%1$s": %2$s', 'commonsbooking' ), $bookingCode->getItemName(),$bookingCode->getCode()), - $bookingCode); - - $calendar->addEvent( DateTimeImmutable::createFromFormat('Y-m-d',$bookingCode->getDate()), $title, $desc); - } - - $attachment = [ - 'string' => $calendar->getCalendarData(), // String attachment data (required) - 'filename' => "BookingCodes" . '.ics', // Name of the attachment (required) - 'encoding' => 'base64', // File encoding (defaults to 'base64') - 'type' => 'text/calendar', // File MIME type (if left unspecified, PHPMailer will try to work it out from the file name) - 'disposition' => 'attachment' // Disposition to use (defaults to 'attachment') - ]; + foreach ( $bookingCodes as $bookingCode ) { + $title = apply_filters( + 'commonsbooking_emailcodes_icalevent_title', + $bookingCode->getItemName() . ' (' . $bookingCode->getCode() . ')', + $bookingCode + ); + $desc = apply_filters( + 'commonsbooking_emailcodes_icalevent_desc', + sprintf( __( 'booking code for item "%1$s": %2$s', 'commonsbooking' ), $bookingCode->getItemName(), $bookingCode->getCode() ), + $bookingCode + ); + + $calendar->addEvent( DateTimeImmutable::createFromFormat( 'Y-m-d', $bookingCode->getDate() ), $title, $desc ); + } + + $attachment = [ + 'string' => $calendar->getCalendarData(), // String attachment data (required) + 'filename' => 'BookingCodes' . '.ics', // Name of the attachment (required) + 'encoding' => 'base64', // File encoding (defaults to 'base64') + 'type' => 'text/calendar', // File MIME type (if left unspecified, PHPMailer will try to work it out from the file name) + 'disposition' => 'attachment', // Disposition to use (defaults to 'attachment') + ]; return $attachment; - - } + } /** * raises mail_sent action with error info @@ -209,9 +230,8 @@ protected function getIcalAttachment( array $bookingCodes): array { * * @return bool false */ - protected function raiseError( string $msg): bool { - do_action( 'commonsbooking_mail_sent', $this->getAction(),new \WP_Error("e-mail",$msg)); - return false; - } - -} \ No newline at end of file + protected function raiseError( string $msg ): bool { + do_action( 'commonsbooking_mail_sent', $this->getAction(), new \WP_Error( 'e-mail', $msg ) ); + return false; + } +} diff --git a/src/Messages/BookingMessage.php b/src/Messages/BookingMessage.php index 64283638c..6417f2574 100644 --- a/src/Messages/BookingMessage.php +++ b/src/Messages/BookingMessage.php @@ -15,9 +15,10 @@ class BookingMessage extends Message { /** * Booking messages can either notify a user about a confirmed booking or a canceled booking. + * * @var string[] */ - protected $validActions = [ "confirmed", "canceled" ]; + protected $validActions = [ 'confirmed', 'canceled' ]; public function sendMessage() { /** @var \CommonsBooking\Model\Booking $booking */ @@ -33,44 +34,48 @@ public function sendMessage() { ]; // get location email adresses to send them bcc copies - $location = get_post($booking->getMeta('location-id')); - $location_emails = CB::get( Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email', $location ) ; /* email addresses, comma-seperated */ - $location_bcc_copy = CB::get( Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', $location ) == 'on' ; /* email addresses, comma-seperated */ - if ($location_emails && $location_bcc_copy) { - $bcc_adresses = str_replace(' ','',$location_emails); + $location = get_post( $booking->getMeta( 'location-id' ) ); + $location_emails = CB::get( Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email', $location ); /* email addresses, comma-seperated */ + $location_bcc_copy = CB::get( Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', $location ) == 'on'; /* email addresses, comma-seperated */ + if ( $location_emails && $location_bcc_copy ) { + $bcc_adresses = str_replace( ' ', '', $location_emails ); } else { $bcc_adresses = null; } // get templates from Admin Options - $template_body = Settings::getOption( 'commonsbooking_options_templates', - 'emailtemplates_mail-booking-' . $this->action . '-body' ); - $template_subject = Settings::getOption( 'commonsbooking_options_templates', - 'emailtemplates_mail-booking-' . $this->action . '-subject', 'sanitize_text_field' ); - + $template_body = Settings::getOption( + 'commonsbooking_options_templates', + 'emailtemplates_mail-booking-' . $this->action . '-body' + ); + $template_subject = Settings::getOption( + 'commonsbooking_options_templates', + 'emailtemplates_mail-booking-' . $this->action . '-subject', + 'sanitize_text_field' + ); // Setup email: From $fromHeaders = sprintf( - "From: %s <%s>", + 'From: %s <%s>', Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-name', 'sanitize_text_field' ), sanitize_email( Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-email' ) ) ); - //generate attachment when set in settings + // generate attachment when set in settings $attachment = null; - if ((Settings::getOption( 'commonsbooking_options_templates', 'emailtemplates_mail-booking_ics_attach' ) == 'on') ){ + if ( ( Settings::getOption( 'commonsbooking_options_templates', 'emailtemplates_mail-booking_ics_attach' ) == 'on' ) ) { $eventTitle = Settings::getOption( 'commonsbooking_options_templates', 'emailtemplates_mail-booking_ics_event-title' ); - $eventTitle = commonsbooking_sanitizeHTML ( commonsbooking_parse_template ( $eventTitle, $template_objects ) ); + $eventTitle = commonsbooking_sanitizeHTML( commonsbooking_parse_template( $eventTitle, $template_objects ) ); $eventDescription = Settings::getOption( 'commonsbooking_options_templates', 'emailtemplates_mail-booking_ics_event-description' ); - $eventDescription = commonsbooking_sanitizeHTML ( strip_tags ( commonsbooking_parse_template ( $eventDescription, $template_objects ) ) ); + $eventDescription = commonsbooking_sanitizeHTML( strip_tags( commonsbooking_parse_template( $eventDescription, $template_objects ) ) ); $attachment = [ - 'string' => $booking->getiCal($eventTitle,$eventDescription), // String attachment data (required) + 'string' => $booking->getiCal( $eventTitle, $eventDescription ), // String attachment data (required) 'filename' => $booking->post_name . '.ics', // Name of the attachment (required) 'encoding' => 'base64', // File encoding (defaults to 'base64') 'type' => 'text/calendar', // File MIME type (if left unspecified, PHPMailer will try to work it out from the file name) - 'disposition' => 'attachment' // Disposition to use (defaults to 'attachment') + 'disposition' => 'attachment', // Disposition to use (defaults to 'attachment') ]; } @@ -83,7 +88,6 @@ public function sendMessage() { $template_objects, $attachment ); - $this->SendNotificationMail(); + $this->sendNotificationMail(); } - -} \ No newline at end of file +} diff --git a/src/Messages/BookingReminderMessage.php b/src/Messages/BookingReminderMessage.php index e1fbc9e2a..7833eaff0 100644 --- a/src/Messages/BookingReminderMessage.php +++ b/src/Messages/BookingReminderMessage.php @@ -10,6 +10,7 @@ /** * This message is sent out to users to remind them of their upcoming booking. * This is sent using a cron job. + * * @see \CommonsBooking\Service\Scheduler */ class BookingReminderMessage extends Message { @@ -17,26 +18,32 @@ class BookingReminderMessage extends Message { /** * @var array|string[] */ - protected $validActions = [ "pre-booking-reminder", "post-booking-notice" ]; + protected $validActions = [ 'pre-booking-reminder', 'post-booking-notice' ]; /** * Sends reminder message. + * * @throws \Exception */ public function sendMessage() { /** @var \CommonsBooking\Model\Booking $booking */ - $booking = Booking::getPostById( $this->getPostId() ); + $booking = Booking::getPostById( $this->getPostId() ); $booking_user = get_userdata( $this->getPost()->post_author ); // get templates from Admin Options - $template_body = Settings::getOption( 'commonsbooking_options_reminder', - $this->action . '-body' ); - $template_subject = Settings::getOption( 'commonsbooking_options_reminder', - $this->action . '-subject', 'sanitize_text_field' ); + $template_body = Settings::getOption( + 'commonsbooking_options_reminder', + $this->action . '-body' + ); + $template_subject = Settings::getOption( + 'commonsbooking_options_reminder', + $this->action . '-subject', + 'sanitize_text_field' + ); // Setup email: From $fromHeaders = sprintf( - "From: %s <%s>", + 'From: %s <%s>', Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-name', 'sanitize_text_field' ), sanitize_email( Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-email' ) ) ); @@ -51,10 +58,9 @@ public function sendMessage() { 'booking' => $booking, 'item' => $booking->getItem(), 'location' => $booking->getLocation(), - 'user' => $booking_user, + 'user' => $booking_user, ] ); - $this->SendNotificationMail(); + $this->sendNotificationMail(); } - -} \ No newline at end of file +} diff --git a/src/Messages/LocationBookingReminderMessage.php b/src/Messages/LocationBookingReminderMessage.php index f71a22b22..e8ea25707 100644 --- a/src/Messages/LocationBookingReminderMessage.php +++ b/src/Messages/LocationBookingReminderMessage.php @@ -11,6 +11,7 @@ /** * This message is sent out to locations to remind them of bookings starting soon or ending soon. * This is sent using a cron job. + * * @see \CommonsBooking\Service\Scheduler */ class LocationBookingReminderMessage extends Message { @@ -18,7 +19,7 @@ class LocationBookingReminderMessage extends Message { /** * @var array|string[] */ - protected $validActions = [ "booking-start-location-reminder", "booking-end-location-reminder" ]; + protected $validActions = [ 'booking-start-location-reminder', 'booking-end-location-reminder' ]; /** * Sends reminder message. @@ -39,14 +40,19 @@ public function sendMessage() { $location_emails = explode( ',', $location_emails_option ); // get templates from Admin Options - $template_body = Settings::getOption( 'commonsbooking_options_reminder', - $this->action . '-body' ); - $template_subject = Settings::getOption( 'commonsbooking_options_reminder', - $this->action . '-subject', 'sanitize_text_field' ); + $template_body = Settings::getOption( + 'commonsbooking_options_reminder', + $this->action . '-body' + ); + $template_subject = Settings::getOption( + 'commonsbooking_options_reminder', + $this->action . '-subject', + 'sanitize_text_field' + ); // Setup email: From $fromHeaders = sprintf( - "From: %s <%s>", + 'From: %s <%s>', Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-name', 'sanitize_text_field' ), sanitize_email( Settings::getOption( 'commonsbooking_options_templates', 'emailheaders_from-email' ) ) ); @@ -77,4 +83,4 @@ public function sendMessage() { $this->sendNotificationMail(); } } -} \ No newline at end of file +} diff --git a/src/Messages/Message.php b/src/Messages/Message.php index ae5522bc9..60560add0 100644 --- a/src/Messages/Message.php +++ b/src/Messages/Message.php @@ -13,42 +13,49 @@ abstract class Message { /** * The actions that are valid for this message. Usually a string. + * * @var array */ protected $validActions = []; /** * The action that is used for this message. Needs to be contained in $validActions + * * @var */ protected $action; /** * The post that this message is about + * * @var */ protected $post; /** * The recipient(s) of this message + * * @var */ protected $to; /** * The e-mail headers + * * @var */ protected $headers; /** * The subject text of this message + * * @var */ protected $subject; /** * The body text of this message + * * @var */ protected $body; @@ -60,6 +67,7 @@ abstract class Message { * 'encoding' => File encoding (defaults to 'base64') * 'type' => File MIME type (if left unspecified, PHPMailer will try to work it out from the file name) * 'disposition' => Disposition to use (defaults to 'attachment') + * * @var array */ protected $attachment = []; @@ -106,12 +114,12 @@ public function getAttachment(): array { * Setup the email template, headers (BCC) * * @param MessageRecipient $recipientUser User-Object - * @param string $template_body template string - * @param string $template_subject template string - * @param string $from_headers From-Header (From:xxx) - * @param string|null $bcc_adresses comma separated string with e-mail adresses - * @param object[] $objects objects used in parse template function - * @param array|null $attachment + * @param string $template_body template string + * @param string $template_subject template string + * @param string $from_headers From-Header (From:xxx) + * @param string|null $bcc_adresses comma separated string with e-mail adresses + * @param object[] $objects objects used in parse template function + * @param array|null $attachment */ protected function prepareMail( MessageRecipient $recipientUser, @@ -130,35 +138,35 @@ protected function prepareMail( // check if templates are available if ( ! $template_body or ! $template_subject ) { - new WP_Error( 'e-mail ', commonsbooking_sanitizeHTML( __( "Could not send email because mail-template was not available. Check options -> templates", "commonsbooking" ) ) ); + new WP_Error( 'e-mail ', commonsbooking_sanitizeHTML( __( 'Could not send email because mail-template was not available. Check options -> templates', 'commonsbooking' ) ) ); } // parse templates & replaces template tags (e.g. {{item:name}}) // 'body' is HTML. 'subject' is not HTML needs alternative sanitation such that characters like & // do not get converted to HTML-entities like & $this->body = commonsbooking_sanitizeHTML( commonsbooking_parse_template( $template_body, $objects ) ); - $this->subject = sanitize_text_field( commonsbooking_parse_template( $template_subject, $objects, "sanitize_text_field" ) ); + $this->subject = sanitize_text_field( commonsbooking_parse_template( $template_subject, $objects, 'sanitize_text_field' ) ); // Setup mime type - $this->headers[] = "MIME-Version: 1.0"; - $this->headers[] = "Content-Type: text/html"; + $this->headers[] = 'MIME-Version: 1.0'; + $this->headers[] = 'Content-Type: text/html'; // Setup email: From $this->headers[] = $from_headers; - // add bcc adresses - if ( ! empty ( $bcc_adresses ) ) { + // add bcc adresses + if ( ! empty( $bcc_adresses ) ) { $addresses_array = explode( ',', $bcc_adresses ); $this->add_bcc( $addresses_array ); } - - //add attachment when it exists - if (!empty($attachment)) { + + // add attachment when it exists + if ( ! empty( $attachment ) ) { $this->attachment = $attachment; } } - + /** * Send the email using wp_mail function * @@ -166,19 +174,19 @@ protected function prepareMail( * * @return void */ - public function SendNotificationMail() { - $to = $this->getTo(); - $subject = $this->getSubject(); - $body = $this->getBody(); + public function sendNotificationMail() { + $to = $this->getTo(); + $subject = $this->getSubject(); + $body = $this->getBody(); $attachment = $this->getAttachment(); - $headers = implode( "\r\n", $this->headers ); - - if (!empty($attachment)) { //When attachment exists, modify wp_mail function to support attachment strings - add_filter('wp_mail', array($this,'addStringAttachments'), 25); //add arbitrary priority to identify filter for removal - $result = wp_mail($to, $subject, $body, $headers, $attachment); - remove_filter('wp_mail', array($this,'addStringAttachments'), 25); //remove filter directly after attachment is sent - } else { //Sends regular mail, when no attachment present - $result = wp_mail($to, $subject, $body, $headers); + $headers = implode( "\r\n", $this->headers ); + + if ( ! empty( $attachment ) ) { // When attachment exists, modify wp_mail function to support attachment strings + add_filter( 'wp_mail', array( $this, 'addStringAttachments' ), 25 ); // add arbitrary priority to identify filter for removal + $result = wp_mail( $to, $subject, $body, $headers, $attachment ); + remove_filter( 'wp_mail', array( $this, 'addStringAttachments' ), 25 ); // remove filter directly after attachment is sent + } else { // Sends regular mail, when no attachment present + $result = wp_mail( $to, $subject, $body, $headers ); } // WPML: Reset system lang do_action( 'wpml_reset_language_after_mailing' ); @@ -189,6 +197,7 @@ abstract public function sendMessage(); /** * Only send mail if action is valid + * * @return void */ public function triggerMail(): void { @@ -222,8 +231,8 @@ public function getPostId() { */ protected function add_bcc( array $address_array ) { // sanitize emails - $address_array = array_filter( array_map( 'sanitize_email', $address_array) ); - $this->headers[] = sprintf( "BCC:%s", implode(',', $address_array ) ); + $address_array = array_filter( array_map( 'sanitize_email', $address_array ) ); + $this->headers[] = sprintf( 'BCC:%s', implode( ',', $address_array ) ); } /** @@ -237,34 +246,35 @@ public function getValidActions(): array { * Adds support for defining attachments as data arrays in wp_mail(). * Allows us to send string-based or binary attachments (non-filesystem) * and gives us more control over the attachment data. - * - * @param array $atts Array of the `wp_mail()` arguments. - * - string|string[] $to Array or comma-separated list of email addresses to send message. - * - string $subject Email subject. - * - string $message Message contents. - * - string|string[] $headers Additional headers. - * - string|string[] $attachments Paths to files to attach. + * + * @param array $atts Array of the `wp_mail()` arguments. + * - string|string[] $to Array or comma-separated list of email addresses to send message. + * - string $subject Email subject. + * - string $message Message contents. + * - string|string[] $headers Additional headers. + * - string|string[] $attachments Paths to files to attach. * * @see https://gist.github.com/thomasfw/5df1a041fd8f9c939ef9d88d887ce023/ */ - public function addStringAttachments($atts) - { + public function addStringAttachments( $atts ) { $attachment_arrays = []; - if (array_key_exists('attachments', $atts) && isset($atts['attachments']) && $atts['attachments']) { + if ( array_key_exists( 'attachments', $atts ) && isset( $atts['attachments'] ) && $atts['attachments'] ) { $attachments = $atts['attachments']; - if (is_array($attachments) && !empty($attachments)) { - // Is the $attachments array a single array of attachment data, or an array containing multiple arrays of + if ( is_array( $attachments ) && ! empty( $attachments ) ) { + // Is the $attachments array a single array of attachment data, or an array containing multiple arrays of // attachment data? (note that the array may also be a one-dimensional array of file paths, as-per default usage). - $is_multidimensional_array = count($attachments) == count($attachments, COUNT_RECURSIVE) ? false : true; - if (!$is_multidimensional_array) $attachments = [$attachments]; - // Work out which attachments we want to process here. If the value is an array with either - // a 'path' or 'path' key, then we'll process it separately and remove it from the + $is_multidimensional_array = count( $attachments ) == count( $attachments, COUNT_RECURSIVE ) ? false : true; + if ( ! $is_multidimensional_array ) { + $attachments = [ $attachments ]; + } + // Work out which attachments we want to process here. If the value is an array with either + // a 'path' or 'path' key, then we'll process it separately and remove it from the // $atts['attachments'] so that WP doesn't try to process it in wp_mail(). - foreach ($attachments as $index => $attachment) { - if (is_array($attachment) && (array_key_exists('path', $attachment) || array_key_exists('string', $attachment))) { + foreach ( $attachments as $index => $attachment ) { + if ( is_array( $attachment ) && ( array_key_exists( 'path', $attachment ) || array_key_exists( 'string', $attachment ) ) ) { $attachment_arrays[] = $attachment; - if ($is_multidimensional_array) { - unset($atts['attachments'][$index]); + if ( $is_multidimensional_array ) { + unset( $atts['attachments'][ $index ] ); } else { $atts['attachments'] = []; } @@ -279,35 +289,38 @@ public function addStringAttachments($atts) global $wp_mail_attachments; $wp_mail_attachments = $attachment_arrays; - // We can't use the global $phpmailer to add our attachments directly in the 'wp_mail' filter callback because WP calls $phpmailer->clearAttachments() - // after this filter runs. Instead, we now hook into the 'phpmailer_init' action (triggered right before the email is sent), and read - // the $wp_mail_attachments global to check for any additional attachments to add. - add_action('phpmailer_init', function ( $phpmailer) { - // Check the $wp_mail_attachments global for any attachment data, and reset it for good measure. - $attachment_arrays = []; - if (array_key_exists('wp_mail_attachments', $GLOBALS)) { - global $wp_mail_attachments; - $attachment_arrays = $wp_mail_attachments; - $wp_mail_attachments = []; - } + // We can't use the global $phpmailer to add our attachments directly in the 'wp_mail' filter callback because WP calls $phpmailer->clearAttachments() + // after this filter runs. Instead, we now hook into the 'phpmailer_init' action (triggered right before the email is sent), and read + // the $wp_mail_attachments global to check for any additional attachments to add. + add_action( + 'phpmailer_init', + function ( $phpmailer ) { + // Check the $wp_mail_attachments global for any attachment data, and reset it for good measure. + $attachment_arrays = []; + if ( array_key_exists( 'wp_mail_attachments', $GLOBALS ) ) { + global $wp_mail_attachments; + $attachment_arrays = $wp_mail_attachments; + $wp_mail_attachments = []; + } - // Loop through our attachment arrays and attempt to add them using PHPMailer::addAttachment() or PHPMailer::addStringAttachment(): - foreach ($attachment_arrays as $attachment) { - $is_filesystem_attachment = array_key_exists('path', $attachment) ? true : false; - try { - $encoding = $attachment['encoding'] ?? $phpmailer::ENCODING_BASE64; - $type = $attachment['type'] ?? ''; - $disposition = $attachment['disposition'] ?? 'attachment'; - if ($is_filesystem_attachment) { - $phpmailer->addAttachment(($attachment['path'] ?? null), ($attachment['name'] ?? ''), $encoding, $type, $disposition); - } else { - $phpmailer->addStringAttachment(($attachment['string'] ?? null), ($attachment['filename'] ?? ''), $encoding, $type, $disposition); + // Loop through our attachment arrays and attempt to add them using PHPMailer::addAttachment() or PHPMailer::addStringAttachment(): + foreach ( $attachment_arrays as $attachment ) { + $is_filesystem_attachment = array_key_exists( 'path', $attachment ) ? true : false; + try { + $encoding = $attachment['encoding'] ?? $phpmailer::ENCODING_BASE64; + $type = $attachment['type'] ?? ''; + $disposition = $attachment['disposition'] ?? 'attachment'; + if ( $is_filesystem_attachment ) { + $phpmailer->addAttachment( ( $attachment['path'] ?? null ), ( $attachment['name'] ?? '' ), $encoding, $type, $disposition ); + } else { + $phpmailer->addStringAttachment( ( $attachment['string'] ?? null ), ( $attachment['filename'] ?? '' ), $encoding, $type, $disposition ); + } + } catch ( \Exception $e ) { + continue; } - } catch (\Exception $e) { - continue; } } - }); + ); } return $atts; } diff --git a/src/Messages/RestrictionMessage.php b/src/Messages/RestrictionMessage.php index 465677e5d..b1a43ba98 100644 --- a/src/Messages/RestrictionMessage.php +++ b/src/Messages/RestrictionMessage.php @@ -26,7 +26,7 @@ class RestrictionMessage extends Message { protected $validActions = [ Restriction::TYPE_REPAIR, - Restriction::TYPE_HINT + Restriction::TYPE_HINT, ]; /** @@ -36,10 +36,10 @@ class RestrictionMessage extends Message { * @param $action */ public function __construct( $restriction, $user, Booking $booking, $action, bool $firstMessage = false ) { - $this->restriction = $restriction; - $this->user = $user; - $this->booking = $booking; - $this->action = $action; + $this->restriction = $restriction; + $this->user = $user; + $this->booking = $booking; + $this->action = $action; $this->firstMessage = $firstMessage; } @@ -75,7 +75,7 @@ protected function sendHintMail() { $subject ); - $this->SendNotificationMail(); + $this->sendNotificationMail(); } /** @@ -90,7 +90,7 @@ protected function sendRepairMail() { $subject ); - $this->SendNotificationMail(); + $this->sendNotificationMail(); } /** @@ -105,7 +105,7 @@ protected function sendRestrictionCancelationMail() { $subject ); - $this->SendNotificationMail(); + $this->sendNotificationMail(); } /** @@ -117,14 +117,14 @@ protected function sendRestrictionCancelationMail() { * @throws \Exception */ protected function prepareRestrictionMail( $body, $subject ) { - $fromHeader = 'From: ' . Settings::getOption( 'commonsbooking_options_restrictions', 'restrictions-from-name', 'sanitize_text_field' ) . - ' <' . Settings::getOption( 'commonsbooking_options_restrictions', 'restrictions-from-email' ) . '>'; + $fromHeader = 'From: ' . Settings::getOption( 'commonsbooking_options_restrictions', 'restrictions-from-name', 'sanitize_text_field' ) . + ' <' . Settings::getOption( 'commonsbooking_options_restrictions', 'restrictions-from-email' ) . '>'; $restriction = $this->getRestriction(); - $bcc_addresses = ""; - if ($this->firstMessage){ //Notify the maintainer about the damage by putting them in the BCC for the first notice. Avoids the maintainer getting flooded with restriction messages. - $item_maintainer_email = CB::get( Item::$postType, COMMONSBOOKING_METABOX_PREFIX . 'item_maintainer_email', $this->booking->getItem() ) ; /* email addresses, comma-seperated */ - $bcc_addresses = str_replace(' ','',$item_maintainer_email); + $bcc_addresses = ''; + if ( $this->firstMessage ) { // Notify the maintainer about the damage by putting them in the BCC for the first notice. Avoids the maintainer getting flooded with restriction messages. + $item_maintainer_email = CB::get( Item::$postType, COMMONSBOOKING_METABOX_PREFIX . 'item_maintainer_email', $this->booking->getItem() ); /* email addresses, comma-seperated */ + $bcc_addresses = str_replace( ' ', '', $item_maintainer_email ); } $this->prepareMail( @@ -138,7 +138,7 @@ protected function prepareRestrictionMail( $body, $subject ) { 'item' => $this->booking->getItem(), 'location' => $this->booking->getLocation(), 'booking' => $this->getBooking(), - 'user' => $this->getUser() + 'user' => $this->getUser(), ] ); } @@ -163,5 +163,4 @@ public function getRestriction() { public function getBooking(): Booking { return $this->booking; } - -} \ No newline at end of file +} diff --git a/src/Migration/Booking.php b/src/Migration/Booking.php index 62c43f693..48947c2d9 100644 --- a/src/Migration/Booking.php +++ b/src/Migration/Booking.php @@ -14,7 +14,7 @@ public static function migrate() { $bookings = Timeframe::getPostIdsByType( [ \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_ID, - \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_CANCELED_ID + \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_CANCELED_ID, ] ); @@ -27,10 +27,10 @@ public static function migrate() { /** * Runs migration script and returns booking IDs as json array. + * * @return void */ public static function ajaxMigrate() { wp_send_json( self::migrate() ); } - -} \ No newline at end of file +} diff --git a/src/Migration/Migration.php b/src/Migration/Migration.php index a4e2e7764..d9eb2d4e4 100644 --- a/src/Migration/Migration.php +++ b/src/Migration/Migration.php @@ -24,7 +24,7 @@ class Migration { /** * Fields we don't want/need to migrate. - * + * * @var string[] */ private static $ignoredMetaFields = [ @@ -135,7 +135,6 @@ public static function migrateAll() { array_key_exists( 'migrationFunction', $taskFunctions[ $key ] ) && $taskFunctions[ $key ]['migrationFunction'] ) { - if ( $taskIndex >= $taskLimit ) { break; } @@ -150,9 +149,8 @@ public static function migrateAll() { // If there are items to migrate if ( count( $items ) ) { - for ( $index = $task['index']; $index < count( $items ); $index ++ ) { - - if ( $taskIndex ++ >= $taskLimit ) { + for ( $index = $task['index']; $index < count( $items ); $index++ ) { + if ( $taskIndex++ >= $taskLimit ) { break; } @@ -168,7 +166,7 @@ public static function migrateAll() { // No items for migration found } else { - if ( $taskIndex ++ >= $taskLimit ) { + if ( $taskIndex++ >= $taskLimit ) { break; } $task['complete'] = 1; @@ -176,7 +174,7 @@ public static function migrateAll() { // Single Migration } else { - if ( $taskIndex ++ >= $taskLimit ) { + if ( $taskIndex++ >= $taskLimit ) { break; } @@ -200,8 +198,8 @@ public static function migrateAll() { public static function migrateLocation( WP_Post $location ): bool { // Collect post data $postData = array_merge( - $location->to_array(), - [ + $location->to_array(), + [ 'post_type' => Location::$postType, ] ); @@ -211,12 +209,12 @@ public static function migrateLocation( WP_Post $location ): bool { // Exctract e-mails from CB1 contactinfo field so we can migrate it into new cb2 field _cb_location_email $cb1_location_emails = self::fetchEmails( - get_post_meta( - $location->ID, - 'commons-booking_location_contactinfo_text', - true - ) - ); + get_post_meta( + $location->ID, + 'commons-booking_location_contactinfo_text', + true + ) + ); if ( $cb1_location_emails ) { $cb1_location_email_string = implode( ',', $cb1_location_emails ); @@ -272,11 +270,11 @@ public static function fetchEmails( $text ): array { $words = str_word_count( $text, 1, '.@-_' ); return array_filter( - $words, - function ( $word ) { - return filter_var( $word, FILTER_VALIDATE_EMAIL ); - } - ); + $words, + function ( $word ) { + return filter_var( $word, FILTER_VALIDATE_EMAIL ); + } + ); } /** @@ -442,14 +440,14 @@ public static function migrateElementorMetaKeys( $cb1_id, $cb2_id ) { public static function migrateItem( WP_Post $item ): bool { // Collect post data $postData = array_merge( - $item->to_array(), - [ + $item->to_array(), + [ 'post_type' => Item::$postType, 'post_excerpt' => get_post_meta( - $item->ID, + $item->ID, 'commons-booking_item_descr', - true - ), + true + ), ] ); @@ -501,22 +499,22 @@ public static function migrateTimeframe( $timeframe ): bool { ]; // convert cb1 metadata in cb2 postmeta fields - // CB2 <-> CB1 + // CB2 <-> CB1 $postMeta[ COMMONSBOOKING_METABOX_PREFIX . 'cb1_post_post_ID' ] = $timeframe['id']; $postMeta[ \CommonsBooking\Model\Timeframe::REPETITION_START ] = strtotime( $timeframe['date_start'] ); $postMeta[ \CommonsBooking\Model\Timeframe::REPETITION_END ] = strtotime( $timeframe['date_end'] ); $postMeta[ \CommonsBooking\Model\Timeframe::META_ITEM_ID ] = $cbItem ? $cbItem->ID : ''; $postMeta[ \CommonsBooking\Model\Timeframe::META_LOCATION_ID ] = $cbLocation ? $cbLocation->ID : ''; - $postMeta['type'] = Timeframe::BOOKABLE_ID; - $postMeta[ \CommonsBooking\Model\Timeframe::META_REPETITION ] = $timeframe_repetition; - $postMeta['start-time'] = '00:00'; - $postMeta['end-time'] = '23:59'; - $postMeta['full-day'] = 'on'; - $postMeta['grid'] = '0'; - $postMeta['weekdays'] = $weekdays; - $postMeta[ \CommonsBooking\Model\Timeframe::META_SHOW_BOOKING_CODES] = 'on'; - $postMeta[ \CommonsBooking\Model\Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS] = Settings::getOption( 'commons-booking-settings-bookings', 'commons-booking_bookingsettings_daystoshow' ); - $postMeta[ \CommonsBooking\Model\Timeframe::META_MAX_DAYS ] = Settings::getOption( 'commons-booking-settings-bookings', 'commons-booking_bookingsettings_maxdays' ); + $postMeta['type'] = Timeframe::BOOKABLE_ID; + $postMeta[ \CommonsBooking\Model\Timeframe::META_REPETITION ] = $timeframe_repetition; + $postMeta['start-time'] = '00:00'; + $postMeta['end-time'] = '23:59'; + $postMeta['full-day'] = 'on'; + $postMeta['grid'] = '0'; + $postMeta['weekdays'] = $weekdays; + $postMeta[ \CommonsBooking\Model\Timeframe::META_SHOW_BOOKING_CODES ] = 'on'; + $postMeta[ \CommonsBooking\Model\Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS ] = Settings::getOption( 'commons-booking-settings-bookings', 'commons-booking_bookingsettings_daystoshow' ); + $postMeta[ \CommonsBooking\Model\Timeframe::META_MAX_DAYS ] = Settings::getOption( 'commons-booking-settings-bookings', 'commons-booking_bookingsettings_maxdays' ); $existingPost = self::getExistingPost( $timeframe['id'], Timeframe::$postType, Timeframe::BOOKABLE_ID ); @@ -580,9 +578,9 @@ public static function migrateBooking( $booking ): bool { * @return mixed */ public static function migrateBookingCode( $bookingCode ) { - $cb2ItemId = CB1::getCB2ItemId( $bookingCode['item_id'] ); - $date = $bookingCode['booking_date']; - $code = $bookingCode['bookingcode']; + $cb2ItemId = CB1::getCB2ItemId( $bookingCode['item_id'] ); + $date = $bookingCode['booking_date']; + $code = $bookingCode['bookingcode']; $bookingCode = new BookingCode( $date, @@ -640,5 +638,4 @@ public static function migrateTaxonomy( $cb1Taxonomy ) { wp_set_object_terms( $cb2PostId, $term, $cb1Taxonomy->taxonomy ); } } - } diff --git a/src/Model/BookablePost.php b/src/Model/BookablePost.php index 47cb7ff96..fc4afbf32 100644 --- a/src/Model/BookablePost.php +++ b/src/Model/BookablePost.php @@ -10,7 +10,6 @@ /** * Logical wrapper for `bookable` (timeframe) posts * Inherited by Location and Item. - * */ class BookablePost extends CustomPost { @@ -21,9 +20,9 @@ class BookablePost extends CustomPost { * * @uses Timeframe::getBookableForCurrentUser() * - * @param false $asModel - Whether to return the timeframes as model (CommonsBooking\Model\Timeframe) or as array of WP_Post - * @param array $locations - If called from Item, this array should contain the location IDs to filter the timeframes - * @param array $items - If called from Location, this array should contain the item IDs to filter the timeframes + * @param false $asModel - Whether to return the timeframes as model (CommonsBooking\Model\Timeframe) or as array of WP_Post + * @param array $locations - If called from Item, this array should contain the location IDs to filter the timeframes + * @param array $items - If called from Location, this array should contain the item IDs to filter the timeframes * @param string|null $date - A datestring to get only the timeframes that are bookable on a specific date * * @return array - An array of CommonsBooking\Model\Timeframe or WP_Post, an empty array if no bookable timeframes were found @@ -44,7 +43,6 @@ public function getBookableTimeframes( $asModel, Helper::getLastFullHourTimestamp() ); - } if ( get_called_class() == Item::class ) { $bookableTimeframes = Timeframe::getBookableForCurrentUser( @@ -69,5 +67,4 @@ public function getBookableTimeframes( public function isBookable(): bool { return count( $this->getBookableTimeframes() ) > 0; } - } diff --git a/src/Model/Booking.php b/src/Model/Booking.php index 9e7462fda..fd6810868 100755 --- a/src/Model/Booking.php +++ b/src/Model/Booking.php @@ -43,11 +43,11 @@ class Booking extends \CommonsBooking\Model\Timeframe { */ const META_LAST_TIMEFRAME = 'last-connected-timeframe'; - public const ERROR_TYPE = 'BookingValidationFailed'; + public const ERROR_TYPE = 'BookingValidationFailed'; /** * Booking states. - * + * * @var string[] */ public static $bookingStates = [ @@ -58,7 +58,7 @@ class Booking extends \CommonsBooking\Model\Timeframe { /** * Returns the booking code as a string. - * + * * @return mixed */ public function getBookingCode() { @@ -66,37 +66,34 @@ public function getBookingCode() { } - /** - * Determines if a current booking can be cancelled or not by the current user. - * Bookings which do not belong to the current user or the user is not admin of cannot be edited. + /** + * Determines if a current booking can be cancelled or not by the current user. + * Bookings which do not belong to the current user or the user is not admin of cannot be edited. * - * Returns true if booking can be cancelled. - * False if booking may not be cancelled. + * Returns true if booking can be cancelled. + * False if booking may not be cancelled. * - * @return bool - */ - public function canCancel():bool { - if ($this->isPast() ){ - return false; - } - - if ( intval( $this->post_author ) === get_current_user_id() ){ - return true; - } - elseif (commonsbooking_isCurrentUserAllowedToEdit($this->post)){ - return true; - } - else { - return false; - } + * @return bool + */ + public function canCancel(): bool { + if ( $this->isPast() ) { + return false; + } - } + if ( intval( $this->post_author ) === get_current_user_id() ) { + return true; + } elseif ( commonsbooking_isCurrentUserAllowedToEdit( $this->post ) ) { + return true; + } else { + return false; + } + } /** * Cancel the current booking and send a cancellation mail to the user. * Because we are directly updating the database, we need another function to flush the database cache (wp_cache_flush()) to test this function. */ - public function cancel() : void { + public function cancel(): void { // check if booking has ended if ( $this->isPast() ) { @@ -128,7 +125,7 @@ protected function sendCancellationMail() { /** * Returns rendered booking code for using in email-template (booking confirmation mail). * If booking code is not set, it returns an empty string. - * + * * @return string * @throws Exception */ @@ -150,7 +147,7 @@ public function formattedBookingCode(): string { /** * Returns true if booking codes shall be shown in frontend. - * + * * @return bool */ public function showBookingCodes(): bool { @@ -160,7 +157,7 @@ public function showBookingCodes(): bool { /** * Returns the corresponding Timeframe object for booking. * If no timeframe is found, it returns null. - * + * * @return null|\CommonsBooking\Model\Timeframe * @throws Exception */ @@ -186,7 +183,7 @@ public function getBookableTimeFrame(): ?\CommonsBooking\Model\Timeframe { * Assigns relevant meta fields from related bookable timeframe to booking. * We have to do this, because bookings used to be just a type of timeframe post. * This leads to a lot of post meta for bookings that only make sense in a timeframe context. - * + * * @throws Exception */ public function assignBookableTimeframeFields() { @@ -225,7 +222,7 @@ public function assignBookableTimeframeFields() { date( 'Y-m-d', $this->getStartDate() ) ); } catch ( BookingCodeException $e ) { - //do nothing, just set the booking code to null + // do nothing, just set the booking code to null $bookingCode = null; } @@ -250,8 +247,7 @@ private function adjacent( bool $previous = true ): ?Booking { if ( $previous ) { $startDate = $this->getStartDateDateTime()->modify( '-2 minutes' )->getTimestamp(); $endDate = $this->getStartDateDateTime()->modify( '-1 minute' )->getTimestamp(); - } - else { + } else { $startDate = $this->getEndDateDateTime()->modify( '+1 minute' )->getTimestamp(); $endDate = $this->getEndDateDateTime()->modify( '+2 minutes' )->getTimestamp(); } @@ -263,13 +259,11 @@ private function adjacent( bool $previous = true ): ?Booking { [], [ 'confirmed' ] ); - if (count($adjacentBookings) == 1){ - return reset($adjacentBookings); - } - elseif (count($adjacentBookings) > 1){ - throw new Exception("Overlapping booking detected."); - } - else { + if ( count( $adjacentBookings ) == 1 ) { + return reset( $adjacentBookings ); + } elseif ( count( $adjacentBookings ) > 1 ) { + throw new Exception( 'Overlapping booking detected.' ); + } else { return null; } } @@ -283,9 +277,9 @@ private function adjacent( bool $previous = true ): ?Booking { * @throws Exception */ public function getAdjacentBookings(): ?array { - $previousAdjacent = $this->adjacent(); + $previousAdjacent = $this->adjacent(); $followingAdjacent = $this->adjacent( false ); - return array_filter([$previousAdjacent, $followingAdjacent]); + return array_filter( [ $previousAdjacent, $followingAdjacent ] ); } /** @@ -296,27 +290,27 @@ public function getAdjacentBookings(): ?array { * @param WP_User $user * @return array */ - public function getBookingChain(WP_User $user): array { - $bookingChain = []; + public function getBookingChain( WP_User $user ): array { + $bookingChain = []; $previousBooking = $this->adjacent(); - if ($previousBooking && $previousBooking->getUserData()->ID != $user->ID){ + if ( $previousBooking && $previousBooking->getUserData()->ID != $user->ID ) { $previousBooking = null; } $followingBooking = $this->adjacent( false ); - if ($followingBooking && $followingBooking->getUserData()->ID != $user->ID){ + if ( $followingBooking && $followingBooking->getUserData()->ID != $user->ID ) { $followingBooking = null; } - while ($previousBooking != null){ - $bookingChain[] = $previousBooking; + while ( $previousBooking != null ) { + $bookingChain[] = $previousBooking; $previousBooking = $previousBooking->adjacent(); - if ($previousBooking && $previousBooking->getUserData()->ID != $user->ID){ + if ( $previousBooking && $previousBooking->getUserData()->ID != $user->ID ) { $previousBooking = null; } } - while ($followingBooking != null){ - $bookingChain[] = $followingBooking; + while ( $followingBooking != null ) { + $bookingChain[] = $followingBooking; $followingBooking = $followingBooking->adjacent( false ); - if ($followingBooking && $followingBooking->getUserData()->ID != $user->ID){ + if ( $followingBooking && $followingBooking->getUserData()->ID != $user->ID ) { $followingBooking = null; } } @@ -362,6 +356,7 @@ public function getItem(): ?Item { * Gets the corresponding location object for this booking. * If no location is found, it returns null. * This should not happen, because a booking is always based on a location. But this might happen if the location was deleted. + * * @return ?Location * @throws Exception */ @@ -383,20 +378,20 @@ public function getLocation(): ?Location { * @param int $rawDaysOverbooked The raw days a booking spans over a locked / holiday. * @return int The amount of those days that were not counted towards the maximum booking length. */ - public function setOverbookedDays(int $rawDaysOverbooked): int { - $location = $this->getLocation(); - $countLockdaysInRange = $location->getMeta(COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_in_range') === 'on'; - $countLockdaysMaximum = $location->getMeta(COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_maximum'); + public function setOverbookedDays( int $rawDaysOverbooked ): int { + $location = $this->getLocation(); + $countLockdaysInRange = $location->getMeta( COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_in_range' ) === 'on'; + $countLockdaysMaximum = $location->getMeta( COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_maximum' ); - if (!$countLockdaysInRange) { + if ( ! $countLockdaysInRange ) { $days = $rawDaysOverbooked; - } elseif ($countLockdaysMaximum == 0) { + } elseif ( $countLockdaysMaximum == 0 ) { $days = 0; } else { - $days = max(0, $rawDaysOverbooked - $countLockdaysMaximum); + $days = max( 0, $rawDaysOverbooked - $countLockdaysMaximum ); } - update_post_meta($this->post->ID, self::META_OVERBOOKED_DAYS, $days); + update_post_meta( $this->post->ID, self::META_OVERBOOKED_DAYS, $days ); return $days; } @@ -412,7 +407,7 @@ public function getOverbookedDays(): int { if ( ! $metaField ) { return 0; } - return intval ( $metaField ); + return intval( $metaField ); } public function getFormattedStartDate(): string { @@ -459,7 +454,7 @@ public function pickupDatetime(): string { $time_format = commonsbooking_sanitizeHTML( get_option( 'time_format' ) ); $repetitionStart = $this->getStartDate(); - $repetitionEnd = $this->getEndDate(); + $repetitionEnd = $this->getEndDate(); $date_start = date_i18n( $date_format, $repetitionStart ); $time_start = date_i18n( $time_format, $repetitionStart ); @@ -493,7 +488,6 @@ public function pickupDatetime(): string { * * @return string */ - public function returnDatetime(): string { $date_format = commonsbooking_sanitizeHTML( get_option( 'date_format' ) ); $time_format = commonsbooking_sanitizeHTML( get_option( 'time_format' ) ); @@ -533,7 +527,7 @@ public function returnDatetime(): string { * * @return mixed|string */ - public function getStartDate() : int { + public function getStartDate(): int { return intval( $this->getMeta( \CommonsBooking\Model\Timeframe::REPETITION_START ) ); } @@ -546,15 +540,15 @@ public function getStartDate() : int { * * @return mixed|string */ - public function getEndDate() : int{ - return intval($this->getMeta( \CommonsBooking\Model\Timeframe::REPETITION_END )); + public function getEndDate(): int { + return intval( $this->getMeta( \CommonsBooking\Model\Timeframe::REPETITION_END ) ); } /** * Returns comment field text. * The booking comment is a field that can be filled in by the user when booking (when enabled). * The content of the field is not publicly visible and is only visible to the admin(s) and the user who made the booking. - * + * * @return string */ public function returnComment(): string { @@ -595,22 +589,22 @@ public function bookingNotice(): ?string { /** * Will check if a backend booking is valid. * Throws a TimeframeInvalidException containing the error message if the booking is not valid. + * * @return true if booking is valid * @throws TimeframeInvalidException */ public function isValid(): bool { - if ($this->getStartDate() > $this->getEndDate()) { - throw new TimeframeInvalidException('Start date is after end date' ); + if ( $this->getStartDate() > $this->getEndDate() ) { + throw new TimeframeInvalidException( 'Start date is after end date' ); } - try { $item = $this->getItem(); if ( ! $item ) { throw new Exception(); } } catch ( Exception $e ) { - throw new TimeframeInvalidException( __('Item not found', 'commonsbooking' ) ); + throw new TimeframeInvalidException( __( 'Item not found', 'commonsbooking' ) ); } try { @@ -619,7 +613,7 @@ public function isValid(): bool { throw new Exception(); } } catch ( Exception $e ) { - throw new TimeframeInvalidException( __('Location not found', 'commonsbooking' ) ); + throw new TimeframeInvalidException( __( 'Location not found', 'commonsbooking' ) ); } $timeframe = $this->getBookableTimeFrame(); @@ -637,7 +631,6 @@ public function isValid(): bool { ); if ( $overlappingBookings && count( $overlappingBookings ) >= 1 ) { - foreach ( $overlappingBookings as $overlappingBooking ) { $overlappingBookingLinks[] = $overlappingBooking->getFormattedEditLink(); } @@ -671,7 +664,7 @@ public function bookingLink( $linktext = null ): string { $linktext = esc_html__( 'Link to your booking', 'commonsbooking' ); } - return sprintf( '%2$s', $this->bookingLinkUrl() , $linktext ); + return sprintf( '%2$s', $this->bookingLinkUrl(), $linktext ); } /** @@ -701,9 +694,9 @@ public function isCancelled(): bool { * @param WP_User|null $user * @return bool */ - public function isUserPrivileged( WP_User $user = null): bool { + public function isUserPrivileged( WP_User $user = null ): bool { $user ??= $this->getUserData(); - return parent::isUserPrivileged($user); + return parent::isUserPrivileged( $user ); } /** @@ -713,11 +706,12 @@ public function isUserPrivileged( WP_User $user = null): bool { * or when a bookable timeframe is changed to a non-bookable timeframe and the booking is still in the database. * * This can also happen when a booking is created without a bookable timeframe, e.g. when a booking is created through the backend. + * * @return bool * @throws Exception */ public function isOrphaned(): bool { - if ($this->getBookableTimeFrame() === null) { + if ( $this->getBookableTimeFrame() === null ) { return true; } else { return false; @@ -749,16 +743,15 @@ public function isPast(): bool { */ public function termsApply( $term ): bool { try { - $item = $this->getItem(); + $item = $this->getItem(); $location = $this->getLocation(); - } - catch ( Exception $e ) { - //terms are not applicable if either location or item is not found + } catch ( Exception $e ) { + // terms are not applicable if either location or item is not found return false; } - $isInItemCat = has_term( $term, \CommonsBooking\Wordpress\CustomPostType\Item::$postType . 's_category', $item->getPost() ); + $isInItemCat = has_term( $term, \CommonsBooking\Wordpress\CustomPostType\Item::$postType . 's_category', $item->getPost() ); $isInLocationCat = has_term( $term, \CommonsBooking\Wordpress\CustomPostType\Location::$postType . 's_category', $location->getPost() ); - return ( $isInItemCat || $isInLocationCat); + return ( $isInItemCat || $isInLocationCat ); } /** @@ -773,32 +766,30 @@ public function termsApply( $term ): bool { * * @return int */ - public function getDuration(): int{ + public function getDuration(): int { $interval = null; if ( $this->isUnconfirmed() || $this->isConfirmed() ) { - $interval = $this->getStartDateDateTime()->diff($this->getEndDateDateTime()->modify("+5 min")); - } - elseif ($this->isCancelled()){ - $startDate = $this->getStartDateDateTime(); + $interval = $this->getStartDateDateTime()->diff( $this->getEndDateDateTime()->modify( '+5 min' ) ); + } elseif ( $this->isCancelled() ) { + $startDate = $this->getStartDateDateTime(); $cancellationDate = $this->getCancellationDateDateTime(); - //count as 0 days when booking is cancelled before it has started - if ($cancellationDate < $startDate){ + // count as 0 days when booking is cancelled before it has started + if ( $cancellationDate < $startDate ) { return 0; } - $interval = $startDate->diff( $cancellationDate ); - } - else { - //Booking has no valid status + $interval = $startDate->diff( $cancellationDate ); + } else { + // Booking has no valid status return 0; } - if ($interval === null){ - //no interval created + if ( $interval === null ) { + // no interval created return 0; } $days = $interval->d; - //when we have already moved into the next day for more one hour,it is counted as another day even if it is not completed - if ($interval->h > 0){ - $days++; + // when we have already moved into the next day for more one hour,it is counted as another day even if it is not completed + if ( $interval->h > 0 ) { + ++$days; } return $days - $this->getOverbookedDays(); } @@ -854,14 +845,15 @@ public function getEmailSignature(): string { * Will return if a booking is affected by a total breakdown ( the booked item is not usable ). * Because since #866 not all total breakdowns are cancelled, we need a way to make sure that the user * will not be notified about their upcoming bookings or asked to give feedback because they might not have used the item. + * * @return bool true if booking is affected by a total breakdown */ public function hasTotalBreakdown(): bool { - $itemID = $this->getItem()->ID; - $locationID = $this->getLocation()->ID; + $itemID = $this->getItem()->ID; + $locationID = $this->getLocation()->ID; $restrictions = \CommonsBooking\Repository\Restriction::get( - [$locationID], - [$itemID], + [ $locationID ], + [ $itemID ], null, true, $this->getStartDate() @@ -880,57 +872,58 @@ public function hasTotalBreakdown(): bool { return false; } - /** - * Returns formatted user info based on the template field in settings -> templates - * - * @return void - */ - public static function getFormattedUserInfo() { - return commonsbooking_parse_template( - Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'user_details_template' ) - ); - } - - /** - * Returns formatted backend edit link of current booking - * - * @return string - */ - public function getFormattedEditLink() { - return ' Booking #' . $this->ID . ' : ' . $this->formattedBookingDate() . ' | User: ' . $this->getUserData()->user_nicename . ''; - } + /** + * Returns formatted user info based on the template field in settings -> templates + * + * @return mixed + */ + public static function getFormattedUserInfo() { + return commonsbooking_parse_template( + Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'user_details_template' ) + ); + } + + /** + * Returns formatted backend edit link of current booking + * + * @return string + */ + public function getFormattedEditLink() { + return ' Booking #' . $this->ID . ' : ' . $this->formattedBookingDate() . ' | User: ' . $this->getUserData()->user_nicename . ''; + } /** * Will return a location where an orphaned booking can be moved to. This is * the new location of the timeframe the booking was previously attached to. + * * @return ?Location */ public function getMoveableLocation(): ?Location { - if (!$this->isOrphaned()) { + if ( ! $this->isOrphaned() ) { return null; } $attachedTFMeta = intval( get_post_meta( $this->ID, self::META_LAST_TIMEFRAME, true ) ); - if ( empty ($attachedTFMeta)) { - throw new Exception("No attached timeframe found for orphaned booking."); + if ( empty( $attachedTFMeta ) ) { + throw new Exception( 'No attached timeframe found for orphaned booking.' ); } $attachedTF = new \CommonsBooking\Model\Timeframe( $attachedTFMeta ); return $attachedTF->getLocation(); } - /** - * Updates internal booking comment by adding new comment in a new line - * - * @param string $comment - * @param int $userID - * @return void - */ - public function appendToInternalComment( string $comment, int $userID ) { - $existing_comment = $this->getMeta( 'internal-comment' ); - $dateTimeInfo = current_datetime()->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ); - $meta_string = $dateTimeInfo . ' / ' . get_the_author_meta( 'user_login', $userID ) . "\n"; - $new_comment = $existing_comment . "\n" . $meta_string . $comment . "\n--------------------"; - update_post_meta( $this->ID, 'internal-comment', $new_comment ); - } + /** + * Updates internal booking comment by adding new comment in a new line + * + * @param string $comment + * @param int $userID + * @return void + */ + public function appendToInternalComment( string $comment, int $userID ) { + $existing_comment = $this->getMeta( 'internal-comment' ); + $dateTimeInfo = current_datetime()->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ); + $meta_string = $dateTimeInfo . ' / ' . get_the_author_meta( 'user_login', $userID ) . "\n"; + $new_comment = $existing_comment . "\n" . $meta_string . $comment . "\n--------------------"; + update_post_meta( $this->ID, 'internal-comment', $new_comment ); + } /** @@ -938,7 +931,7 @@ public function appendToInternalComment( string $comment, int $userID ) { * * @return bool */ - public function isConfirmed() : bool { + public function isConfirmed(): bool { return $this->post_status === 'confirmed'; } @@ -947,7 +940,7 @@ public function isConfirmed() : bool { * * @return bool */ - public function isUnconfirmed() : bool { + public function isUnconfirmed(): bool { return $this->post_status === 'unconfirmed'; } @@ -956,12 +949,12 @@ public function isUnconfirmed() : bool { * * @since 2.9.0 * - * @param \CommonsBooking\Model\Booking[] $bookings + * @param \CommonsBooking\Model\Booking[] $bookings * @return void */ - public static function getTotalDuration ( array $bookings ): int { + public static function getTotalDuration( array $bookings ): int { $totalDurationOfDays = 0; - foreach ($bookings as $booking){ + foreach ( $bookings as $booking ) { $totalDurationOfDays += $booking->getDuration(); } return $totalDurationOfDays; @@ -975,23 +968,22 @@ public static function getTotalDuration ( array $bookings ): int { * * @since 2.9.0 * - * @param Booking[] $bookings The booking to check + * @param Booking[] $bookings The booking to check * @param array|false $terms The terms that the bookings are filtered against * @return array|null */ - public static function filterTermsApply ( array $bookings, $terms ): ?array { - if ( ! empty($terms) ){ - $filteredBookingsArray = array_filter($bookings, - fn( Booking $booking ) => $booking->termsApply($terms) + public static function filterTermsApply( array $bookings, $terms ): ?array { + if ( ! empty( $terms ) ) { + $filteredBookingsArray = array_filter( + $bookings, + fn( Booking $booking ) => $booking->termsApply( $terms ) ); - if ( ! empty ($filteredBookingsArray) ){ + if ( ! empty( $filteredBookingsArray ) ) { return $filteredBookingsArray; - } - else { + } else { return null; } - } - else { + } else { return $bookings; } } @@ -1002,12 +994,13 @@ public static function filterTermsApply ( array $bookings, $terms ): ?array { * * @since 2.9.0 * - * @param array $bookings - * @param WP_User $user + * @param array $bookings + * @param WP_User $user * @return array|null */ - public static function filterForUser ( array $bookings, WP_User $user): ?array { - return array_filter( $bookings, + public static function filterForUser( array $bookings, WP_User $user ): ?array { + return array_filter( + $bookings, fn( Booking $booking ) => $booking->getUserData()->ID == $user->ID ); } @@ -1015,9 +1008,10 @@ public static function filterForUser ( array $bookings, WP_User $user): ?array { /** * Will get the status of a booking as a human-readable string + * * @return string */ - public function getStatus() : string { + public function getStatus(): string { if ( $this->isConfirmed() ) { return __( 'Confirmed', 'commonsbooking' ); } elseif ( $this->isUnconfirmed() ) { diff --git a/src/Model/BookingCode.php b/src/Model/BookingCode.php index d583864b6..da9adeb13 100644 --- a/src/Model/BookingCode.php +++ b/src/Model/BookingCode.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Model; - /** * This is the data type for a single booking code. * It is generated by the BookingCodes repository. @@ -18,22 +17,25 @@ class BookingCode { /** * Error type id. */ - public const ERROR_TYPE = "bookingCodeCreationError"; + public const ERROR_TYPE = 'bookingCodeCreationError'; /** * Datestring in the format Y-m-d + * * @var string */ private $date; /** * Item ID + * * @var int */ private $item; /** * Code string + * * @var string */ private $code; @@ -46,9 +48,9 @@ class BookingCode { * @param $code */ public function __construct( $date, $item, $code ) { - $this->date = $date; - $this->item = $item; - $this->code = $code; + $this->date = $date; + $this->item = $item; + $this->code = $code; } /** diff --git a/src/Model/Calendar.php b/src/Model/Calendar.php index a3df4ef0a..3b7e176e0 100644 --- a/src/Model/Calendar.php +++ b/src/Model/Calendar.php @@ -45,6 +45,7 @@ class Calendar { /** * The timeframes that are relevant for this calendar. + * * @var Timeframe[] */ protected array $timeframes; @@ -52,14 +53,14 @@ class Calendar { /** * Calendar constructor. * - * @param Day $startDate - * @param Day $endDate + * @param Day $startDate + * @param Day $endDate * @param int[] $locations * @param int[] $items * @param array $types */ public function __construct( Day $startDate, Day $endDate, array $locations = [], array $items = [], array $types = [] ) { - //check, that it spans at least two days + // check, that it spans at least two days if ( $startDate->getDate() == $endDate->getDate() ) { throw new \InvalidArgumentException( 'Calendar must span at least two days' ); } @@ -90,7 +91,6 @@ public function getWeeks(): array { serialize( $this->types ) ); - $cacheItem = Plugin::getCacheItem( $customId ); if ( $cacheItem ) { return $cacheItem; @@ -128,7 +128,7 @@ public function getWeeks(): array { * @throws \Exception */ public function getAvailabilitySlots(): array { - $slots = []; + $slots = []; $doneSlots = []; /** @var Week $week */ foreach ( $this->getWeeks() as $week ) { @@ -138,12 +138,12 @@ public function getAvailabilitySlots(): array { $timeframe = new Timeframe( $slot['timeframe'] ); $timeFrameType = get_post_meta( $slot['timeframe']->ID, 'type', true ); - //Skip everything where the most important slot is not bookable. We are only interested in direct availability. + // Skip everything where the most important slot is not bookable. We are only interested in direct availability. if ( $timeFrameType != \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID ) { continue; } - //Skip timeframes that are not bookable today + // Skip timeframes that are not bookable today if ( $timeframe->getFirstBookableDay() > $day->getDate() ) { continue; } @@ -151,23 +151,23 @@ public function getAvailabilitySlots(): array { $availabilitySlot = new stdClass(); // Init DateTime object for start - $dateTimeStart = Wordpress::getUTCDateTime('now'); + $dateTimeStart = Wordpress::getUTCDateTime( 'now' ); $dateTimeStart->setTimestamp( $slot['timestampstart'] ); $availabilitySlot->start = $dateTimeStart->format( 'Y-m-d\TH:i:sP' ); // Init DateTime object for end - $dateTimeend = Wordpress::getUTCDateTime('now'); + $dateTimeend = Wordpress::getUTCDateTime( 'now' ); $dateTimeend->setTimestamp( $slot['timestampend'] ); $availabilitySlot->end = $dateTimeend->format( 'Y-m-d\TH:i:sP' ); - $availabilitySlot->locationId = ""; + $availabilitySlot->locationId = ''; if ( $timeframe->getLocation() ) { - $availabilitySlot->locationId = $timeframe->getLocationID() . ""; + $availabilitySlot->locationId = $timeframe->getLocationID() . ''; } - $availabilitySlot->itemId = ""; + $availabilitySlot->itemId = ''; if ( $timeframe->getItem() ) { - $availabilitySlot->itemId = $timeframe->getItemID() . ""; + $availabilitySlot->itemId = $timeframe->getItemID() . ''; } $slotId = md5( serialize( $availabilitySlot ) ); @@ -198,5 +198,4 @@ private function getTimeframes(): array { return $this->timeframes; } - } diff --git a/src/Model/CustomPost.php b/src/Model/CustomPost.php index e105d7e7e..6bccde17e 100644 --- a/src/Model/CustomPost.php +++ b/src/Model/CustomPost.php @@ -81,6 +81,7 @@ public function getMeta( $field ) { /** * When getting a value from a Model Object, we can use this magic method to get the value from the WP_Post object instead. * This, for example, allows us to use $booking->post_title instead of $booking->post->post_title. + * * @param $name * * @return array|mixed|void @@ -117,6 +118,7 @@ public function __call( $name, $arguments ) { /** * Get the corresponding WP_Post object + * * @return WP_Post */ public function getPost(): WP_Post { @@ -144,7 +146,7 @@ public function excerpt(): string { * @return string html */ public function titleLink(): string { - return sprintf( '%s', esc_url(get_the_permalink( $this->ID )), commonsbooking_sanitizeHTML($this->post_title) ); + return sprintf( '%s', esc_url( get_the_permalink( $this->ID ) ), commonsbooking_sanitizeHTML( $this->post_title ) ); } /** @@ -153,7 +155,7 @@ public function titleLink(): string { * @return string */ public function title(): string { - return sprintf( '%s', commonsbooking_sanitizeHTML($this->post_title) ); + return sprintf( '%s', commonsbooking_sanitizeHTML( $this->post_title ) ); } /** @@ -167,8 +169,11 @@ public function title(): string { */ public function thumbnail( $size = 'thumbnail' ): string { if ( has_post_thumbnail( $this->ID ) ) { - return '
        ' . get_the_post_thumbnail( $this->ID, $size, - array( 'class' => 'alignleft cb-image' ) ) . '
        '; + return '
        ' . get_the_post_thumbnail( + $this->ID, + $size, + array( 'class' => 'alignleft cb-image' ) + ) . '
        '; } return ''; @@ -183,6 +188,7 @@ public function getDate() { /** * Returns user data. + * * @return false|\WP_User */ public function getUserData() { @@ -192,11 +198,12 @@ public function getUserData() { /** * Checks if the given user is the author of the current post. + * * @param \WP_User $user * - * @return boolean - true if user is author, false if not. + * @return bool - true if user is author, false if not. */ - public function isAuthor (\WP_User $user): bool { + public function isAuthor( \WP_User $user ): bool { return $user->ID === intval( $this->post_author ); } @@ -210,5 +217,4 @@ public function setDate( string $date = null ) { return $this; } - } diff --git a/src/Model/Day.php b/src/Model/Day.php index b7bc6755a..d7f008490 100644 --- a/src/Model/Day.php +++ b/src/Model/Day.php @@ -46,23 +46,29 @@ class Day { * Day constructor. * * @param string $date - * @param array $locations - * @param array $items - * @param array $types - * @param array $possibleTimeframes + * @param array $locations + * @param array $items + * @param array $types + * @param array $possibleTimeframes */ public function __construct( string $date, array $locations = [], array $items = [], array $types = [], array $possibleTimeframes = [] ) { $this->date = $date; - $this->locations = array_map( function ( $location ) { - return $location instanceof WP_Post ? $location->ID : $location; - }, $locations ); - $this->items = array_map( function ( $item ) { - return $item instanceof WP_Post ? $item->ID : $item; - }, $items ); + $this->locations = array_map( + function ( $location ) { + return $location instanceof WP_Post ? $location->ID : $location; + }, + $locations + ); + $this->items = array_map( + function ( $item ) { + return $item instanceof WP_Post ? $item->ID : $item; + }, + $items + ); $this->types = $types; - if ( ! empty ( $possibleTimeframes ) ) { + if ( ! empty( $possibleTimeframes ) ) { $this->timeframes = \CommonsBooking\Repository\Timeframe::filterTimeframesForTimerange( $possibleTimeframes, $this->getStartTimestamp(), $this->getEndTimestamp() ); $this->timeframes = array_filter( $this->timeframes, fn( $timeframe ) => $this->filterTimeframe( $timeframe ) ); } @@ -103,6 +109,7 @@ public function getFormattedDate( string $format ) { /** * Returns name of the day. + * * @return false|string */ public function getName() { @@ -113,6 +120,7 @@ public function getName() { * Returns array with timeframes relevant for the Day. * This function will only be able to run once. * When on the first try, no Timeframes are found, it will set it to an empty array + * * @return \CommonsBooking\Model\Timeframe[] * @throws Exception */ @@ -140,6 +148,7 @@ public function getTimeframes(): array { /** * Returns array with restrictions. + * * @return array * @throws Exception */ @@ -169,7 +178,7 @@ public function getGrid(): array { * Returns the slot number for specific timeframe and time. * * @param DateTime $date - * @param int $grid + * @param int $grid * * @return float|int */ @@ -183,7 +192,7 @@ protected function getSlotByTime( DateTime $date, int $grid ) { /** * Returns start-slot id. * - * @param int $grid + * @param int $grid * @param \CommonsBooking\Model\Timeframe $timeframe * * @return float|int @@ -197,7 +206,6 @@ protected function getStartSlot( int $grid, \CommonsBooking\Model\Timeframe $tim // If we have an overbooked day, we need to mark all slots as booked if ( $timeframe->getType() === Timeframe::BOOKING_ID ) { - $booking = new Booking( $timeframe->getPost() ); $startDateBooking = $booking->getStartDate(); $startDateDay = strtotime( $this->getDate() ); @@ -219,17 +227,17 @@ protected function getStartSlot( int $grid, \CommonsBooking\Model\Timeframe $tim /** * Returns start slot for restriction. * - * @param int $grid + * @param int $grid * @param Restriction $restriction - + * @return float|int */ - protected function getRestrictionStartSlot( int $grid, \CommonsBooking\Model\Restriction $restriction ) { + protected function getRestrictionStartSlot( int $grid, Restriction $restriction ) { $startTime = $restriction->getStartTimeDateTime(); $startSlot = $this->getSlotByTime( $startTime, $grid ); - $startDateBooking = intval( $restriction->getStartDate() ); + $startDateBooking = $restriction->getStartDate(); $startDateDay = strtotime( $this->getDate() ); // if restriction starts on day before, we set startslot to 0 @@ -243,8 +251,8 @@ protected function getRestrictionStartSlot( int $grid, \CommonsBooking\Model\Res /** * Returns end-slot id. * - * @param array $slots - * @param int $grid + * @param array $slots + * @param int $grid * @param \CommonsBooking\Model\Timeframe $timeframe * * @return float|int @@ -265,7 +273,7 @@ protected function getEndSlot( array $slots, int $grid, \CommonsBooking\Model\Ti } // If we have a overbooked day, we need to mark all slots as booked - if ( ! $timeframe->isOverBookable() && !empty( $endDate ) ) { + if ( ! $timeframe->isOverBookable() && ! empty( $endDate ) ) { // Check if timeframe ends after the current day if ( strtotime( $this->getFormattedDate( 'd.m.Y 23:59' ) ) < $endDate->getTimestamp() ) { $endSlot = count( $slots ); @@ -278,14 +286,14 @@ protected function getEndSlot( array $slots, int $grid, \CommonsBooking\Model\Ti /** * Returns end slot for restriction. * - * @param array $slots - * @param int $grid + * @param array $slots + * @param int $grid * @param Restriction $restriction * * @return float|int * @throws Exception */ - protected function getRestrictionEndSlot( array $slots, int $grid, \CommonsBooking\Model\Restriction $restriction ) { + protected function getRestrictionEndSlot( array $slots, int $grid, Restriction $restriction ) { $endTime = $restriction->getEndTimeDateTime( $this->getDateObject()->getTimestamp() ); $endDate = $restriction->getEndDateDateTime(); @@ -313,7 +321,7 @@ public function isInTimeframe( \CommonsBooking\Model\Timeframe $timeframe ): boo if ( $timeframe->getRepetition() ) { switch ( $timeframe->getRepetition() ) { // Weekly Rep - case "w": + case 'w': $dayOfWeek = intval( $this->getDateObject()->format( 'w' ) ); $timeframeWeekdays = get_post_meta( $timeframe->ID, 'weekdays', true ); @@ -328,10 +336,10 @@ public function isInTimeframe( \CommonsBooking\Model\Timeframe $timeframe ): boo return false; } - // Monthly Rep - case "m": + // Monthly Rep + case 'm': $dayOfMonth = intval( $this->getDateObject()->format( 'j' ) ); - $timeframeStartDayOfMonth = date('j',$timeframe->getStartDate()); + $timeframeStartDayOfMonth = date( 'j', $timeframe->getStartDate() ); if ( $dayOfMonth == $timeframeStartDayOfMonth ) { return true; @@ -339,32 +347,32 @@ public function isInTimeframe( \CommonsBooking\Model\Timeframe $timeframe ): boo return false; } - // Yearly Rep - case "y": + // Yearly Rep + case 'y': $date = intval( $this->getDateObject()->format( 'dm' ) ); - $timeframeDate = date('dm',$timeframe->getStartDate()); + $timeframeDate = date( 'dm', $timeframe->getStartDate() ); if ( $date == $timeframeDate ) { return true; } else { return false; } - // Manual Rep - case "manual": + // Manual Rep + case 'manual': return in_array( $this->getDate(), $timeframe->getManualSelectionDates() ); // No Repetition - case "norep": - $timeframeStartTimestamp = intval( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::REPETITION_START )); - $timeframeEndTimestamp = intval( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::REPETITION_END )); + case 'norep': + $timeframeStartTimestamp = intval( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::REPETITION_START ) ); + $timeframeEndTimestamp = intval( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::REPETITION_END ) ); - $currentDayStartTimestamp = strtotime('midnight', $this->getDateObject()->getTimestamp()); - $currentDayEndTimestamp = strtotime('+1 day midnight', $this->getDateObject()->getTimestamp()) - 1; + $currentDayStartTimestamp = strtotime( 'midnight', $this->getDateObject()->getTimestamp() ); + $currentDayEndTimestamp = strtotime( '+1 day midnight', $this->getDateObject()->getTimestamp() ) - 1; $timeframeStartsBeforeEndOfToday = $timeframeStartTimestamp <= $currentDayEndTimestamp; - $timeframeEndsAfterStartOfToday = $timeframeEndTimestamp >= $currentDayStartTimestamp; + $timeframeEndsAfterStartOfToday = $timeframeEndTimestamp >= $currentDayStartTimestamp; - if(!$timeframeEndTimestamp) { + if ( ! $timeframeEndTimestamp ) { return $timeframeStartsBeforeEndOfToday; } else { return $timeframeStartsBeforeEndOfToday && $timeframeEndsAfterStartOfToday; @@ -424,7 +432,7 @@ protected function mapTimeFrames( array &$slots ) { $slots[ $startSlot ]['timeframe'] = Timeframe::getHigherPrioFrame( $timeframePost, $slots[ $startSlot ]['timeframe'] ); } - $startSlot ++; + ++$startSlot; } } } @@ -440,7 +448,7 @@ protected function mapRestrictions( array &$slots ) { $grid = 24 / count( $slots ); // Iterate through timeframes and fill slots - /** @var \CommonsBooking\Model\Restriction $restriction */ + /** @var Restriction $restriction */ foreach ( $this->getRestrictions() as $restriction ) { // Only if there is a repair we block the timeframe @@ -455,7 +463,7 @@ protected function mapRestrictions( array &$slots ) { $restrictionPost = $restriction->getPost(); $restrictionPost->locked = true; $slots[ $startSlot ]['timeframe'] = $restrictionPost; - $startSlot ++; + ++$startSlot; } } } @@ -539,7 +547,7 @@ protected function removeEmptySlots( &$slots ) { protected function getTimeframeSlots(): array { $customCacheKey = $this->getDate() . serialize( $this->items ) . serialize( $this->locations ); $customCacheKey = md5( $customCacheKey ); - $cacheItem = Plugin::getCacheItem( $customCacheKey ); + $cacheItem = Plugin::getCacheItem( $customCacheKey ); if ( $cacheItem ) { return $cacheItem; } else { @@ -547,12 +555,12 @@ protected function getTimeframeSlots(): array { $slotsPerDay = 24; // Init Slots - for ( $i = 0; $i < $slotsPerDay; $i ++ ) { + for ( $i = 0; $i < $slotsPerDay; $i++ ) { $slots[ $i ] = [ - 'timestart' => date( esc_html(get_option( 'time_format' )), $i * ( ( 24 / $slotsPerDay ) * 3600 ) ), - 'timeend' => date( esc_html(get_option( 'time_format' )), ( $i + 1 ) * ( ( 24 / $slotsPerDay ) * 3600 ) ), + 'timestart' => date( esc_html( get_option( 'time_format' ) ), $i * ( ( 24 / $slotsPerDay ) * 3600 ) ), + 'timeend' => date( esc_html( get_option( 'time_format' ) ), ( $i + 1 ) * ( ( 24 / $slotsPerDay ) * 3600 ) ), 'timestampstart' => $this->getSlotTimestampStart( $slotsPerDay, $i ), - 'timestampend' => $this->getSlotTimestampEnd( $slotsPerDay, $i ) + 'timestampend' => $this->getSlotTimestampEnd( $slotsPerDay, $i ), ]; } @@ -562,7 +570,7 @@ protected function getTimeframeSlots(): array { Plugin::setCacheItem( $slots, - Wordpress::getTags($this->getTimeframes(), $this->items, $this->locations), + Wordpress::getTags( $this->getTimeframes(), $this->items, $this->locations ), $customCacheKey ); @@ -593,5 +601,4 @@ protected function getSlotTimestampStart( $slotsPerDay, $slotNr ) { protected function getSlotTimestampEnd( $slotsPerDay, $slotNr ) { return strtotime( $this->getDate() ) + ( ( $slotNr + 1 ) * ( ( 24 / $slotsPerDay ) * 3600 ) ) - 1; } - } diff --git a/src/Model/Item.php b/src/Model/Item.php index 4d6fc73b5..1fdc3452e 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Model; - use CommonsBooking\Helper\Helper; use CommonsBooking\Repository\Timeframe; use Exception; @@ -21,7 +20,7 @@ class Item extends BookablePost { * * @param $locationId * - * @param bool $asModel + * @param bool $asModel * * @return array * @throws Exception @@ -60,7 +59,7 @@ public function getAdmins() { return array_values( array_unique( - array_map('intval', $itemAdminIds ) + array_map( 'intval', $itemAdminIds ) ) ); } @@ -69,16 +68,16 @@ public function getAdmins() { * Returns all applicable restrictions for this item. * * This function is not used anywhere yet. + * * @return array * @throws Exception */ public function getRestrictions(): array { return \CommonsBooking\Repository\Restriction::get( [], - [$this->ID], + [ $this->ID ], null, true ); } - } diff --git a/src/Model/Location.php b/src/Model/Location.php index 4ace5c0d7..8a3581c61 100644 --- a/src/Model/Location.php +++ b/src/Model/Location.php @@ -23,7 +23,7 @@ class Location extends BookablePost { * returns bookable timeframes for a given itemID * * @param mixed $itemId - * @param bool $asModel + * @param bool $asModel * * @return array * @throws \Exception @@ -47,25 +47,30 @@ public function getBookableTimeframesByItem( $itemId, bool $asModel = false ): a * E.g. a textarea "location format" in the backend that gets run through CB::get(): * {{location_street}}
        {{location_postcode}} {{location_city}} * - * * @return string * @throws \Exception */ public function formattedAddress() { - $html_after = '
        '; - $html_output[] = CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, 'post_title', $this->post ) . $html_after; - $location_street = CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_street', - $this->post ); - if (!empty($location_street)){ + $html_after = '
        '; + $html_output[] = CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, 'post_title', $this->post ) . $html_after; + $location_street = CB::get( + \CommonsBooking\Wordpress\CustomPostType\Location::$postType, + COMMONSBOOKING_METABOX_PREFIX . 'location_street', + $this->post + ); + if ( ! empty( $location_street ) ) { $html_output[] = $location_street . $html_after; } $location_postcode = CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_postcode', $this->post ); - if (!empty($location_postcode)){ + if ( ! empty( $location_postcode ) ) { $html_output[] = $location_postcode; } - $location_city = CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_city', - $this->post ); - if (!empty($location_city)){ + $location_city = CB::get( + \CommonsBooking\Wordpress\CustomPostType\Location::$postType, + COMMONSBOOKING_METABOX_PREFIX . 'location_city', + $this->post + ); + if ( ! empty( $location_city ) ) { $html_output[] = $location_city . $html_after; } @@ -77,6 +82,7 @@ public function formattedAddress() { * This function is usually called using template tags in the e-mail templates. * * TODO: Fix the uncaught exception. + * * @return string html * @throws \Exception */ @@ -87,11 +93,11 @@ public function formattedAddressOneLine(): string { $location_city = CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_city', $this->post ); - if (empty($location_street) && empty($location_postcode) && empty($location_city)){ - return ""; - } - elseif (empty($location_street) || empty($location_postcode)){ - return sprintf('%s %s %s', + if ( empty( $location_street ) && empty( $location_postcode ) && empty( $location_city ) ) { + return ''; + } elseif ( empty( $location_street ) || empty( $location_postcode ) ) { + return sprintf( + '%s %s %s', $location_street, $location_postcode, $location_city @@ -120,14 +126,15 @@ public function formattedAddressOneLine(): string { public function formattedContactInfo() { $contact = array(); if ( ! empty( CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_contact', $this->post ) ) ) { - $contact[] = "
        "; // needed for email template - $contact[] = esc_html__( 'Please contact the contact persons at the location directly if you have any questions regarding collection or return:', - 'commonsbooking' ); + $contact[] = '
        '; // needed for email template + $contact[] = esc_html__( + 'Please contact the contact persons at the location directly if you have any questions regarding collection or return:', + 'commonsbooking' + ); $contact[] = nl2br( CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_contact', $this->post ) ); } return implode( '
        ', $contact ); - } /** @@ -143,7 +150,7 @@ public function formattedContactInfo() { * @throws \Exception */ public function formattedContactInfoOneLine() { - return commonsbooking_sanitizeHTML(CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_contact', $this->post)) . '
        '; + return commonsbooking_sanitizeHTML( CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_contact', $this->post ) ) . '
        '; } /** @@ -154,10 +161,13 @@ public function formattedContactInfoOneLine() { * @throws \Exception */ public function formattedPickupInstructions(): string { - $html_br = '
        '; + $html_br = '
        '; - return $html_br . $html_br . CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, - COMMONSBOOKING_METABOX_PREFIX . 'location_pickupinstructions', $this->post ) . $html_br; + return $html_br . $html_br . CB::get( + \CommonsBooking\Wordpress\CustomPostType\Location::$postType, + COMMONSBOOKING_METABOX_PREFIX . 'location_pickupinstructions', + $this->post + ) . $html_br; } /** @@ -176,7 +186,6 @@ public function formattedPickupInstructionsOneLine() { /** * Calls the geocoder to update the geo coordinates of the location. * Caution: Do not call this function without a one-second delay between calls. Do not overload the geocoder. - * */ public function updateGeoLocation() { $street = $this->getMeta( COMMONSBOOKING_METABOX_PREFIX . 'location_street' ); @@ -191,7 +200,7 @@ public function updateGeoLocation() { return; } - $addressString = $street . ", " . $postCode . " " . $city . ", " . $country; + $addressString = $street . ', ' . $postCode . ' ' . $city . ', ' . $country; try { $addressData = GeoHelper::getAddressData( $addressString ); } catch ( Exception $e ) { @@ -238,8 +247,9 @@ public function getAdmins() { $locationAdminIds[] = get_post_field( 'post_author', $locationId ); return array_unique( - array_map('intval', - array_values($locationAdminIds) + array_map( + 'intval', + array_values( $locationAdminIds ) ) ); } @@ -252,7 +262,7 @@ public function getAdmins() { */ public function getRestrictions(): array { return \CommonsBooking\Repository\Restriction::get( - [$this->ID], + [ $this->ID ], [], null, true @@ -267,6 +277,6 @@ public function getRestrictions(): array { * @return mixed */ public function hasMap() { - return $this->getMeta( 'loc_showmap') === "on"; + return $this->getMeta( 'loc_showmap' ) === 'on'; } } diff --git a/src/Model/Map.php b/src/Model/Map.php index 224620c42..5d86580fb 100644 --- a/src/Model/Map.php +++ b/src/Model/Map.php @@ -10,7 +10,6 @@ /** * This class does the heavy lifting for the map shortcode * Code style differs because it has been taken from the fLotte Map shortcode plugin - * */ class Map extends CustomPost { @@ -33,7 +32,6 @@ public function get_locations( array $mapItemTerms ): array { $preset_categories = $this->getMeta( 'cb_items_preset_categories' ); $preset_location_categories = $this->getMeta( 'cb_locations_preset_categories' ); - $args = [ 'post_type' => Location::$postType, 'posts_per_page' => - 1, @@ -55,8 +53,8 @@ public function get_locations( array $mapItemTerms ): array { foreach ( $locationObjects as $post ) { $location_meta = get_post_meta( $post->ID, null, true ); - //set serialized empty array if not set - //THIS FUNCTIONALITY IS DEPRECATED, closing days were a feature of 0.9.X + // set serialized empty array if not set + // THIS FUNCTIONALITY IS DEPRECATED, closing days were a feature of 0.9.X $closed_days = isset( $location_meta['commons-booking_location_closeddays'] ) ? $location_meta['commons-booking_location_closeddays'][0] : 'a:0:{}'; $items = []; @@ -67,12 +65,11 @@ public function get_locations( array $mapItemTerms ): array { if ( $preset_location_categories ) { if ( ! has_term( $preset_location_categories, 'cb_locations_category', $post->ID ) ) { - continue; //skip to next location in loop + continue; // skip to next location in loop } } foreach ( Item::getByLocation( $post->ID, true ) as $item ) { - $item_terms = wp_get_post_terms( $item->ID, \CommonsBooking\Wordpress\CustomPostType\Item::$postType . 's_category' @@ -98,13 +95,12 @@ function ( $item ) { */ if ( $preset_categories ) { - //check if preset category is in items + // check if preset category is in items if ( ! has_term( $preset_categories, 'cb_items_category', $item->ID ) ) { - continue; //skip to next item in loop + continue; // skip to next item in loop } } - $timeframesData = []; $timeframes = Timeframe::getBookableForCurrentUser( [ $post->ID ], @@ -119,12 +115,12 @@ function ( $item ) { $endDate = $timeframe->getEndDate() ?: date( 'Y-m-d', strtotime( '2999-01-01' ) ); $timeframesData[] = [ 'date_start' => $startDate, - 'date_end' => $endDate + 'date_end' => $endDate, ]; } $thumbnailID = get_post_thumbnail_id( $item->ID ); - //this thumbnail is kept for backwards compatibility + // this thumbnail is kept for backwards compatibility $thumbnail = wp_get_attachment_image_url( $thumbnailID, 'thumbnail' ); $images = [ 'thumbnail' => wp_get_attachment_image_src( $thumbnailID, 'thumbnail' ), @@ -135,13 +131,13 @@ function ( $item ) { $items[] = [ 'id' => $item->ID, 'name' => $item->post_title, - 'short_desc' => has_excerpt( $item->ID ) ? wp_strip_all_tags( get_the_excerpt( $item->ID ) ) : "", + 'short_desc' => has_excerpt( $item->ID ) ? wp_strip_all_tags( get_the_excerpt( $item->ID ) ) : '', 'status' => $item->post_status, 'terms' => $item_terms, 'link' => add_query_arg( 'cb-location', $post->ID, get_permalink( $item->ID ) ), 'thumbnail' => $thumbnail ?: null, 'images' => $images, - 'timeframes' => $timeframesData + 'timeframes' => $timeframesData, ]; } @@ -180,13 +176,13 @@ function ( $item ) { public static function cleanup_location_data_entry( $value, $linebreak_replacement ) { if ( is_string( $value ) ) { - $value = wp_strip_all_tags( $value ); //strip all tags - $value = preg_replace( '/(\r\n)|\n|\r/', $linebreak_replacement, $value ); //replace linebreaks + $value = wp_strip_all_tags( $value ); // strip all tags + $value = preg_replace( '/(\r\n)|\n|\r/', $linebreak_replacement, $value ); // replace linebreaks } if ( is_array( $value ) ) { foreach ( $value as &$child_value ) { - //recursive call + // recursive call $child_value = self::cleanup_location_data_entry( $child_value, $linebreak_replacement ); } } @@ -209,5 +205,4 @@ public static function cleanup_location_data( $locations, $linebreak_replacement return $locations; } - -} \ No newline at end of file +} diff --git a/src/Model/MessageRecipient.php b/src/Model/MessageRecipient.php index a7f07c9f5..f4c3a3329 100644 --- a/src/Model/MessageRecipient.php +++ b/src/Model/MessageRecipient.php @@ -14,11 +14,13 @@ class MessageRecipient { /** * The email address of the recipient + * * @var string */ private string $email; /** * The human-readable name in the "To" field of the email + * * @var string */ private string $niceName; @@ -52,4 +54,4 @@ public function getEmail(): string { public function getNiceName(): string { return $this->niceName; } -} \ No newline at end of file +} diff --git a/src/Model/Restriction.php b/src/Model/Restriction.php index ad1fa630e..3d4032fba 100644 --- a/src/Model/Restriction.php +++ b/src/Model/Restriction.php @@ -11,7 +11,7 @@ /** * Timeframe for restricting access to an item. * This is the logical wrapper for the restriction custom post type. - * + * * Retrieve restrictions from the database using the @see \CommonsBooking\Repository\Restriction class. * Additionally, all the public functions in this class can be called using Template Tags. * @@ -29,7 +29,6 @@ class Restriction extends CustomPost { /** * This means, that the item is still bookable, but that users will be notified about the restriction. * This is used for example when the item is only available in a limited manner. - * */ const TYPE_HINT = 'hint'; @@ -85,7 +84,7 @@ class Restriction extends CustomPost { /** * Returns post id, for array_unique. - * + * * @return string */ public function __toString(): string { @@ -125,7 +124,7 @@ public function getStartDate(): int { * Returns true if the restriction has an enddate. * * As far as I know, this is never used. - * + * * @return bool */ public function hasEnddate() { @@ -134,7 +133,7 @@ public function hasEnddate() { /** * Returns end timestamp. Of no end-date is set it returns a date far in the future. - * + * * @return int Timestamp */ public function getEndDate(): int { @@ -146,7 +145,7 @@ public function getEndDate(): int { /** * Returns true if restriction isn't active. - * + * * @return bool */ public function isOverBookable(): bool { @@ -180,7 +179,7 @@ public function isLocked(): bool { /** * Returns restriction hint. * The restriction hint is the little message explaining why the item is restricted. - * + * * @return mixed */ public function getHint() { @@ -189,7 +188,7 @@ public function getHint() { /** * Returns nicely formatted start datetime. - * + * * @return string, if META_START is not null. */ public function getFormattedStartDateTime() { @@ -212,7 +211,7 @@ public function getStartTimeDateTime(): DateTime { /** * Returns nicely formatted end datetime. - * + * * @return string, if META_END is not null. */ public function getFormattedEndDateTime() { @@ -235,7 +234,7 @@ public function getEndDateDateTime(): DateTime { /** * Returns item name for the item that is restricted. - * + * * @return string */ public function getItemName(): string { @@ -250,7 +249,7 @@ public function getItemName(): string { /** * Returns itemId for the item that is restricted. - * + * * @return mixed */ public function getItemId() { @@ -259,7 +258,7 @@ public function getItemId() { /** * Returns location name for the location that the restricted item is in. - * + * * @return string */ public function getLocationName(): string { @@ -274,7 +273,7 @@ public function getLocationName(): string { /** * Returns location id for the location that the restricted item is in. - * + * * @return mixed */ public function getLocationId() { @@ -290,15 +289,14 @@ public function apply() { if ( $this->isActive() ) { $bookings = \CommonsBooking\Repository\Booking::getByRestriction( $this ); if ( $bookings ) { - // send restriction mails to all affected bookings - $this->sendRestrictionMails( $bookings ); + // send restriction mails to all affected bookings + $this->sendRestrictionMails( $bookings ); $userDisabledBookingCancellationOnTotalBreakdown = \CommonsBooking\Settings\Settings::getOption( 'commonsbooking_options_restrictions', 'restrictions-no-cancel-on-total-breakdown' ) == 'on'; - // cancel all affected booking + // cancel all affected booking if ( ! $userDisabledBookingCancellationOnTotalBreakdown && $this->isActive() && $this->getType() == self::TYPE_REPAIR ) { $this->cancelBookings( $bookings ); } - } } @@ -346,19 +344,19 @@ protected function sendRestrictionMails( $bookings ) { // get User ID from booking $userId = $booking->getUserData()->ID; - //checks if this is the first booking that is processed + // checks if this is the first booking that is processed $firstMessage = ( $key === array_key_first( $bookings ) ); - // send restriction message for each booking - $hintMail = new RestrictionMessage( $this, get_userdata( $userId ), $booking, $this->getType(),$firstMessage); - $hintMail->triggerMail(); - } - } + // send restriction message for each booking + $hintMail = new RestrictionMessage( $this, get_userdata( $userId ), $booking, $this->getType(), $firstMessage ); + $hintMail->triggerMail(); + } + } /** - * Returns true if a restriction status in cancelled. + * Returns true if a restriction status in cancelled. * Maybe it would make more sense to create an isActive() method and use that instead. - * + * * @return bool */ public function isCancelled(): bool { @@ -368,5 +366,4 @@ public function isCancelled(): bool { return $this->canceled; } - } diff --git a/src/Model/Timeframe.php b/src/Model/Timeframe.php index 80ecc5e4a..f4c9dec4e 100644 --- a/src/Model/Timeframe.php +++ b/src/Model/Timeframe.php @@ -5,7 +5,6 @@ use CommonsBooking\Exception\OverlappingException; use CommonsBooking\Exception\TimeframeInvalidException; use CommonsBooking\Helper\Wordpress; -use CommonsBooking\Tests\Repository\TimeframeTest; use DateTime; use Exception; @@ -77,11 +76,13 @@ class Timeframe extends CustomPost { /** * null means the data is not fetched yet + * * @var int|null */ private ?int $repetitionStart = null; /** * null means the data is not fetched yet, 0 means there is no end date + * * @var int|null */ private ?int $repetitionEnd = null; @@ -94,7 +95,7 @@ class Timeframe extends CustomPost { * @return string */ public function formattedBookableDate(): string { - return self::formatBookableDate( $this->getStartDate() , $this->getEndDate() ); + return self::formatBookableDate( $this->getStartDate(), $this->getEndDate() ); } /** @@ -149,8 +150,7 @@ public function getTimeframeEndDate() { if ( ! $endDate ) { $this->repetitionEnd = 0; - } - else { + } else { $this->repetitionEnd = $endDate; } @@ -188,7 +188,7 @@ public function getEndDate() { * * @return bool */ - public function isUserPrivileged(\WP_User $user = null): bool { + public function isUserPrivileged( \WP_User $user = null ): bool { if ( ! $user ) { $user = wp_get_current_user(); } @@ -196,16 +196,16 @@ public function isUserPrivileged(\WP_User $user = null): bool { return false; } - //these roles are always allowed to book + // these roles are always allowed to book $privilegedRoles = [ 'administrator' ]; apply_filters( 'commonsbooking_privileged_roles', $privilegedRoles ); - if (! empty( array_intersect($privilegedRoles, $user->roles) ) ) { + if ( ! empty( array_intersect( $privilegedRoles, $user->roles ) ) ) { return true; } - $itemAdmin = commonsbooking_isUserAllowedToEdit($this->getItem(),$user); - $locationAdmin = commonsbooking_isUserAllowedToEdit($this->getLocation(),$user); - return ($itemAdmin || $locationAdmin); + $itemAdmin = commonsbooking_isUserAllowedToEdit( $this->getItem(), $user ); + $locationAdmin = commonsbooking_isUserAllowedToEdit( $this->getLocation(), $user ); + return ( $itemAdmin || $locationAdmin ); } /** @@ -222,15 +222,14 @@ public function getLatestPossibleBookingDateTimestamp() { $calculationBase = time(); // if meta-value not set we define a default value far in the future so that we count all possibly relevant timeframes - $advanceBookingDays = $this->getMeta( Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS ) ?: 365; + $advanceBookingDays = $this->getMeta( self::META_TIMEFRAME_ADVANCE_BOOKING_DAYS ) ?: 365; // we subtract one day to reflect the current day in calculation - $advanceBookingDays --; + --$advanceBookingDays; $advanceBookingTime = strtotime( '+ ' . $advanceBookingDays . ' days', $calculationBase ); return $advanceBookingTime; - } /** @@ -238,8 +237,8 @@ public function getLatestPossibleBookingDateTimestamp() { * This is used to display the end date of the timeframe in the frontend. * This is mainly in use by the [cb_items] shortcode. * - * @param int $startDate - * @param int $endDate + * @param int $startDate + * @param int $endDate * * @return string */ @@ -260,9 +259,9 @@ public static function formatBookableDate( int $startDate, int $endDate ): strin if ( $startDate > $today ) { // start is in the future $availableString = sprintf( /* translators: %s = date in WordPress defined format */ - commonsbooking_sanitizeHTML( __( 'from %s', 'commonsbooking' ) ), - $startDateFormatted - ); + commonsbooking_sanitizeHTML( __( 'from %s', 'commonsbooking' ) ), + $startDateFormatted + ); } else { // start has passed, no end date, probably a fixed location $availableString = commonsbooking_sanitizeHTML( __( 'permanently', 'commonsbooking' ) ); } @@ -270,16 +269,16 @@ public static function formatBookableDate( int $startDate, int $endDate ): strin if ( $startDate > $today ) { // start is in the future, with an end date $availableString = sprintf( /* translators: %1$s = startdate, second %2$s = enddate in WordPress defined format */ - commonsbooking_sanitizeHTML( __( 'from %1$s until %2$s', 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( __( 'from %1$s until %2$s', 'commonsbooking' ) ), $startDateFormatted, - $endDateFormatted - ); + $endDateFormatted + ); } else { // start has passed, with an end date $availableString = sprintf( /* translators: %s = enddate in WordPress defined format */ - commonsbooking_sanitizeHTML( __( 'until %s', 'commonsbooking' ) ), - $endDateFormatted - ); + commonsbooking_sanitizeHTML( __( 'until %s', 'commonsbooking' ) ), + $endDateFormatted + ); } } @@ -298,8 +297,9 @@ public static function getDateFormat(): string { /** * Returns end (repetition) date and does not respect advance booking days setting. * Use the getEndDate() function if you want to get the end date that respects the advance booking days setting. - * - * TODO this or getTimeFrameEndDate can be deprecated + * + * TODO this or getTimeFrameEndDate can be deprecated + * * @return false|int */ public function getRawEndDate() { @@ -308,10 +308,10 @@ public function getRawEndDate() { /** * Returns true, if the start date is earlier and the end date later than the latest possible booking date. - * + * * @return bool */ - public function isBookable() :bool { + public function isBookable(): bool { $startDateTimestamp = $this->getStartDate(); $latestPossibleBookingDateTimestamp = $this->getLatestPossibleBookingDateTimestamp(); @@ -329,15 +329,16 @@ public function getTimeFormat(): string { /** * Validates if there can be booking codes created for this timeframe. - * + * * TODO: #507 + * * @return bool */ public function bookingCodesApplicable(): bool { try { return $this->getLocation() && $this->getItem() && - $this->getStartDate() && $this->usesBookingCodes() && - $this->getType() === \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID; + $this->getStartDate() && $this->usesBookingCodes() && + $this->getType() === \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID; } catch ( Exception $e ) { return false; } @@ -369,6 +370,7 @@ public function getLocation(): ?Location { * Returns the corresponding single location id for a timeframe. * This will solely rely on the location id stored in the timeframe. * If the location is deleted, this function will still return the old location id. + * * @deprecated 2.9.0 This should not be used for Timeframes of type HOLIDAYS_ID. * * @return int|null @@ -376,7 +378,7 @@ public function getLocation(): ?Location { public function getLocationID(): ?int { $locationId = $this->getMeta( self::META_LOCATION_ID ); if ( $locationId ) { - return intval($locationId); + return intval( $locationId ); } return null; @@ -400,8 +402,7 @@ public function getLocations(): ?array { } return $locations; - } - else { + } else { return []; } } @@ -416,14 +417,12 @@ public function getLocations(): ?array { public function getLocationIDs(): array { $locationIds = $this->getMeta( self::META_LOCATION_ID_LIST ); if ( $locationIds ) { - return array_map('intval', $locationIds); - } - else { + return array_map( 'intval', $locationIds ); + } else { $locationId = $this->getLocationID(); if ( $locationId ) { return [ $locationId ]; - } - else { + } else { return []; } } @@ -461,7 +460,7 @@ public function getItem(): ?Item { public function getItemID(): ?int { $itemId = $this->getMeta( self::META_ITEM_ID ); if ( $itemId ) { - return intval($itemId); + return intval( $itemId ); } return null; @@ -485,8 +484,7 @@ public function getItems(): ?array { } return $items; - } - else { + } else { return []; } } @@ -501,14 +499,12 @@ public function getItems(): ?array { public function getItemIDs(): array { $itemIds = $this->getMeta( self::META_ITEM_ID_LIST ); if ( $itemIds ) { - return array_map('intval', $itemIds); - } - else { + return array_map( 'intval', $itemIds ); + } else { $itemId = $this->getItemID(); if ( $itemId ) { return [ $itemId ]; - } - else { + } else { return []; } } @@ -524,10 +520,10 @@ public function getItemIDs(): array { * Timeframe::REPAIR_ID * Timeframe::BOOKING_ID * Timeframe::BOOKING_CANCELLED_ID - * + * * @return mixed */ - public function getType() : int { + public function getType(): int { return intval( $this->getMeta( 'type' ) ); } @@ -539,60 +535,66 @@ public function getType() : int { * Will check if the start- and end-date are set. * Will check if there is no timeframe with the same item and location that overlaps with this timeframe. * - *Will throw a TimeframeInvalidException with error message - * - * @return true if valid - * @throws \CommonsBooking\Exception\TimeframeInvalidException - */ + * Will throw a TimeframeInvalidException with error message + * + * @return true if valid + * @throws \CommonsBooking\Exception\TimeframeInvalidException + */ public function isValid(): bool { if ( $this->getType() === \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID ) { try { - $item = $this->getItem(); + $item = $this->getItem(); $location = $this->getLocation(); - } - catch ( \Exception $e ) { - throw new TimeframeInvalidException(__( + } catch ( \Exception $e ) { + throw new TimeframeInvalidException( + __( 'Could not get item or location. Please set a valid item and location.', - 'commonsbooking') + 'commonsbooking' + ) ); } if ( ! $item || ! $location ) { // if location or item is missing - throw new TimeframeInvalidException(__( + throw new TimeframeInvalidException( + __( 'Item or location is missing. Please set item and location.', - 'commonsbooking' ) + 'commonsbooking' + ) ); } - //a timeframe with a manual repetition does not need a start date. - //start- and enddate are automatically set upon saving the post - if ($this->getRepetition() == 'manual') { + // a timeframe with a manual repetition does not need a start date. + // start- and enddate are automatically set upon saving the post + if ( $this->getRepetition() == 'manual' ) { $manual_selection_dates = $this->getManualSelectionDates(); - if ( empty( $manual_selection_dates ) ){ - throw new TimeframeInvalidException(__( + if ( empty( $manual_selection_dates ) ) { + throw new TimeframeInvalidException( + __( 'No dates selected. Please select at least one date.', - 'commonsbooking' ) + 'commonsbooking' + ) ); } - //make sure that there are no duplicate dates - $unique_dates = array_unique($manual_selection_dates); - if ( count($unique_dates) != count($manual_selection_dates) ){ - throw new TimeframeInvalidException(__( + // make sure that there are no duplicate dates + $unique_dates = array_unique( $manual_selection_dates ); + if ( count( $unique_dates ) != count( $manual_selection_dates ) ) { + throw new TimeframeInvalidException( + __( 'The same date was selected multiple times. Please select each date only once.', - 'commonsbooking' ) + 'commonsbooking' + ) ); } - } - else { - if ( ! $this->getStartDate() ) { + } elseif ( ! $this->getStartDate() ) { // If there is at least one mandatory parameter missing, we cannot save/publish timeframe. - throw new TimeframeInvalidException( __( + throw new TimeframeInvalidException( + __( 'Startdate is missing. Please enter a start date to publish this timeframe.', - 'commonsbooking' ) + 'commonsbooking' + ) ); - } } if ( @@ -601,25 +603,31 @@ public function isValid(): bool { $postId = $this->ID; if ( $this->getStartTime() && ! $this->getEndTime() && ! $this->isFullDay() ) { - throw new TimeframeInvalidException( __( + throw new TimeframeInvalidException( + __( 'A pickup time but no return time has been set. Please set the return time.', - 'commonsbooking' ) + 'commonsbooking' + ) ); } - //check if end date is before start date - if (($this->getStartDate() && $this->getEndDate()) && ($this->getStartDate() > $this->getTimeframeEndDate())){ - throw new TimeframeInvalidException( __( + // check if end date is before start date + if ( ( $this->getStartDate() && $this->getEndDate() ) && ( $this->getStartDate() > $this->getTimeframeEndDate() ) ) { + throw new TimeframeInvalidException( + __( 'End date is before start date. Please set a valid end date.', - 'commonsbooking' ) + 'commonsbooking' + ) ); } - //check if start-time and end-time are the same - if (($this->getStartTime() && $this->getEndTime()) && ($this->getStartTime() == $this->getEndTime())){ - throw new TimeframeInvalidException( __( + // check if start-time and end-time are the same + if ( ( $this->getStartTime() && $this->getEndTime() ) && ( $this->getStartTime() == $this->getEndTime() ) ) { + throw new TimeframeInvalidException( + __( 'The start- and end-time of the timeframe can not be the same. Please check the full-day checkbox if you want users to be able to book the full day.', - 'commonsbooking' ) + 'commonsbooking' + ) ); } @@ -635,9 +643,8 @@ public function isValid(): bool { // check if timeframes of other locations overlap in date and return error message if true foreach ( $sameItemTimeframes as $sameItemTimeframe ) { - if ( $location != $sameItemTimeframe->getLocation() - && $this->hasTimeframeDateOverlap( $sameItemTimeframe ) + && $this->hasTimeframeDateOverlap( $sameItemTimeframe ) ) { throw new TimeframeInvalidException( /* translators: %1$s = timeframe-ID, %2$s is timeframe post_title */ @@ -676,12 +683,12 @@ function ( $timeframe ) use ( $postId ) { } catch ( OverlappingException $e ) { throw new TimeframeInvalidException( $e->getMessage() . - sprintf( - /* translators: first %s = timeframe-ID, second %s is timeframe post_title */ - __('See overlapping timeframe ID: %1$s %2$s', 'commonsbooking'), - '' . $otherTimeframe->ID . '', - '' . $otherTimeframe->post_title . '' - ) + sprintf( + /* translators: first %s = timeframe-ID, second %s is timeframe post_title */ + __( 'See overlapping timeframe ID: %1$s %2$s', 'commonsbooking' ), + '' . $otherTimeframe->ID . '', + '' . $otherTimeframe->post_title . '' + ) ); } } @@ -692,7 +699,7 @@ function ( $timeframe ) use ( $postId ) { /** * Returns start time for day-slots. - * + * * @return mixed */ public function getStartTime() { @@ -701,6 +708,7 @@ public function getStartTime() { /** * Returns end time for day-slots. + * * @return mixed */ public function getEndTime() { @@ -710,9 +718,10 @@ public function getEndTime() { /** * Returns true if timeframe is spanning over the whole day. * This means that this is not an hourly timeframe or a slot timeframe. + * * @return bool */ - public function isFullDay() : bool { + public function isFullDay(): bool { return $this->getMeta( 'full-day' ) === 'on'; } @@ -725,32 +734,32 @@ public function isFullDay() : bool { */ public function hasTimeframeDateOverlap( Timeframe $otherTimeframe ): bool { - // Check if both timeframes have no end date or if both are ongoing - if ( ! $this->getTimeframeEndDate() && ! $otherTimeframe->getTimeframeEndDate() ) { - return true; - } - - // Check if only one timeframe has an end date - if ( $this->getTimeframeEndDate() && ! $otherTimeframe->getTimeframeEndDate() ) { - return ( $otherTimeframe->getStartDate() <= $this->getTimeframeEndDate() && $otherTimeframe->getStartDate() >= $this->getStartDate() ); - } - - if ( ! $this->getTimeframeEndDate() && $otherTimeframe->getTimeframeEndDate() ) { - return ( $otherTimeframe->getTimeframeEndDate() > $this->getStartDate() ); - } - - // Check if both timeframes have an end date - if ( $this->getTimeframeEndDate() && $otherTimeframe->getTimeframeEndDate() ) { - return ( - // Check if the end date of the first timeframe is within the second timeframe - ( $this->getTimeframeEndDate() >= $otherTimeframe->getStartDate() && $this->getTimeframeEndDate() <= $otherTimeframe->getTimeframeEndDate() ) || - // Check if the end date of the second timeframe is within the first timeframe - ( $otherTimeframe->getTimeframeEndDate() >= $this->getStartDate() && $otherTimeframe->getTimeframeEndDate() <= $this->getTimeframeEndDate() ) - ); - } + // Check if both timeframes have no end date or if both are ongoing + if ( ! $this->getTimeframeEndDate() && ! $otherTimeframe->getTimeframeEndDate() ) { + return true; + } + + // Check if only one timeframe has an end date + if ( $this->getTimeframeEndDate() && ! $otherTimeframe->getTimeframeEndDate() ) { + return ( $otherTimeframe->getStartDate() <= $this->getTimeframeEndDate() && $otherTimeframe->getStartDate() >= $this->getStartDate() ); + } + + if ( ! $this->getTimeframeEndDate() && $otherTimeframe->getTimeframeEndDate() ) { + return ( $otherTimeframe->getTimeframeEndDate() > $this->getStartDate() ); + } + + // Check if both timeframes have an end date + if ( $this->getTimeframeEndDate() && $otherTimeframe->getTimeframeEndDate() ) { + return ( + // Check if the end date of the first timeframe is within the second timeframe + ( $this->getTimeframeEndDate() >= $otherTimeframe->getStartDate() && $this->getTimeframeEndDate() <= $otherTimeframe->getTimeframeEndDate() ) || + // Check if the end date of the second timeframe is within the first timeframe + ( $otherTimeframe->getTimeframeEndDate() >= $this->getStartDate() && $otherTimeframe->getTimeframeEndDate() <= $this->getTimeframeEndDate() ) + ); + } // If none of the above conditions are true, there is no overlap - //TODO: When does this condition ever apply? + // TODO: When does this condition ever apply? return false; } @@ -760,15 +769,15 @@ public function hasTimeframeDateOverlap( Timeframe $otherTimeframe ): bool { * * TODO: Refactor to return true if timeframes overlap and false if not. Throw exception in calling function. * - * @uses Timeframe::hasTimeframeDateOverlap() + * @uses Timeframe::hasTimeframeDateOverlap() * @uses Timeframe::hasTimeframeTimeOverlap() - * + * * @param Timeframe $otherTimeframe * * @return false * @throws OverlappingException */ - public function overlaps (Timeframe $otherTimeframe) : bool { + public function overlaps( Timeframe $otherTimeframe ): bool { if ( $this->hasTimeframeDateOverlap( $otherTimeframe ) ) { @@ -779,23 +788,23 @@ public function overlaps (Timeframe $otherTimeframe) : bool { ); } - //timeframes that don't overlap in time range are not overlapping - if (! $this->hasTimeframeTimeOverlap( $otherTimeframe) ) { + // timeframes that don't overlap in time range are not overlapping + if ( ! $this->hasTimeframeTimeOverlap( $otherTimeframe ) ) { return false; } $otherTimeframeRepetition = $otherTimeframe->getRepetition(); $repetition = $this->getRepetition(); - //One of the timeframes takes up the full day and therefore none of the dates can overlap - //at this stage there is already overlap in the date range and time range, therefore we must check if the repetitions create an overlap + // One of the timeframes takes up the full day and therefore none of the dates can overlap + // at this stage there is already overlap in the date range and time range, therefore we must check if the repetitions create an overlap if ( $repetition === 'd' || $otherTimeframeRepetition === 'd' ) { throw new OverlappingException( __( 'Daily repeated time periods are not allowed to overlap.', 'commonsbooking' ) ); } - //we concatenate the repetitions to make the switch statement more readable + // we concatenate the repetitions to make the switch statement more readable switch ( $repetition . '|' . $otherTimeframeRepetition ) { case 'w|w': if ( $this->getWeekDays() && $otherTimeframe->getWeekDays() ) { @@ -842,6 +851,7 @@ public function overlaps (Timeframe $otherTimeframe) : bool { /** * Checks if timeframes are overlapping in weekly slot and slot with manual repetition. + * * @param $weeklyTimeframe * @param $manualTimeframe * @@ -854,12 +864,12 @@ private static function hasWeeklyManualOverlap( $weeklyTimeframe, $manualTimefra $manualTimeframe->getManualSelectionDates() ) ); - //we have to make the sunday a 7 instead of 0 in order to detect overlaps with our other array correctly + // we have to make the sunday a 7 instead of 0 in order to detect overlaps with our other array correctly $manualSelectionWeekdays = array_map( fn ( $weekday ) => $weekday == 0 ? 7 : $weekday, $manualSelectionWeekdays ); - $weekDaysOverlap = array_intersect( $weeklyTimeframe->getWeekDays(), $manualSelectionWeekdays ) ; + $weekDaysOverlap = array_intersect( $weeklyTimeframe->getWeekDays(), $manualSelectionWeekdays ); if ( ! empty( $weekDaysOverlap ) ) { return true; } @@ -872,12 +882,12 @@ private static function hasWeeklyManualOverlap( $weeklyTimeframe, $manualTimefra * * @return void */ - public function updatePostMetaStartAndEndDate() : void { - if ($this->getRepetition() == 'manual') { - $timestamps = array_map('strtotime', $this->getManualSelectionDates()); - asort($timestamps); - update_post_meta( $this->ID, \CommonsBooking\Model\Timeframe::REPETITION_START, reset($timestamps) ); - update_post_meta( $this->ID, \CommonsBooking\Model\Timeframe::REPETITION_END, end($timestamps) ); + public function updatePostMetaStartAndEndDate(): void { + if ( $this->getRepetition() == 'manual' ) { + $timestamps = array_map( 'strtotime', $this->getManualSelectionDates() ); + asort( $timestamps ); + update_post_meta( $this->ID, self::REPETITION_START, reset( $timestamps ) ); + update_post_meta( $this->ID, self::REPETITION_END, end( $timestamps ) ); } } @@ -887,67 +897,66 @@ public function updatePostMetaStartAndEndDate() : void { * The timeframe grid describes if either the full slot is bookable or if the timeframe is bookable hourly. * 0 = slot * 1 = hourly - * + * * @return mixed */ public function getGrid(): int { - return intval($this->getMeta( 'grid' )); + return intval( $this->getMeta( 'grid' ) ); } /** * Checks if timeframes are overlapping in time ranges or daily slots. - * + * * Use {@see Timeframe::overlaps()} if you want to compute full-overlap between two timeframes. - * + * * @param Timeframe $otherTimeframe * * @return bool If start-time and end-time overlaps, regardless of overlapping start-date and end-date. */ + public function hasTimeframeTimeOverlap( Timeframe $otherTimeframe ) { + // Check if both timeframes have an end time, if not, there is no overlap + if ( ! strtotime( $this->getEndTime() ) && ! strtotime( $otherTimeframe->getEndTime() ) ) { + return true; + } + + // Check if only timeframe1 has an end time and if it overlaps with the other timeframe + if ( strtotime( $this->getEndTime() ) && ! strtotime( $otherTimeframe->getEndTime() ) + && strtotime( $otherTimeframe->getStartTime() ) <= strtotime( $this->getEndTime() ) + && strtotime( $otherTimeframe->getStartTime() ) >= strtotime( $this->getStartTime() ) ) { + return true; + } - public function hasTimeframeTimeOverlap( Timeframe $otherTimeframe ) { - // Check if both timeframes have an end time, if not, there is no overlap - if ( ! strtotime( $this->getEndTime() ) && ! strtotime( $otherTimeframe->getEndTime() ) ) { - return true; - } - - // Check if only timeframe1 has an end time and if it overlaps with the other timeframe - if ( strtotime( $this->getEndTime() ) && ! strtotime( $otherTimeframe->getEndTime() ) - && strtotime( $otherTimeframe->getStartTime() ) <= strtotime( $this->getEndTime() ) - && strtotime( $otherTimeframe->getStartTime() ) >= strtotime( $this->getStartTime() ) ) { - return true; - } - - // Check if only timeframe2 has an end time and if it overlaps with the other timeframe - if ( ! strtotime( $this->getEndTime() ) && strtotime( $otherTimeframe->getEndTime() ) - && strtotime( $otherTimeframe->getEndTime() ) > strtotime( $this->getStartTime() ) ) { - return true; - } - - // Check if both timeframes have an end time and if they overlap - if ( strtotime( $this->getEndTime() ) && strtotime( $otherTimeframe->getEndTime() ) - && ( ( strtotime( $this->getEndTime() ) > strtotime( $otherTimeframe->getStartTime() ) - && strtotime( $this->getEndTime() ) < strtotime( $otherTimeframe->getEndTime() ) ) - || ( strtotime( $otherTimeframe->getEndTime() ) > strtotime( $this->getStartTime() ) - && strtotime( $otherTimeframe->getEndTime() ) < strtotime( $this->getEndTime() ) ) ) ) { - return true; - } - - //Check if both timeframes have the same start and end time - if ( strtotime( $this->getEndTime() ) && strtotime( $otherTimeframe->getEndTime() ) + // Check if only timeframe2 has an end time and if it overlaps with the other timeframe + if ( ! strtotime( $this->getEndTime() ) && strtotime( $otherTimeframe->getEndTime() ) + && strtotime( $otherTimeframe->getEndTime() ) > strtotime( $this->getStartTime() ) ) { + return true; + } + + // Check if both timeframes have an end time and if they overlap + if ( strtotime( $this->getEndTime() ) && strtotime( $otherTimeframe->getEndTime() ) + && ( ( strtotime( $this->getEndTime() ) > strtotime( $otherTimeframe->getStartTime() ) + && strtotime( $this->getEndTime() ) < strtotime( $otherTimeframe->getEndTime() ) ) + || ( strtotime( $otherTimeframe->getEndTime() ) > strtotime( $this->getStartTime() ) + && strtotime( $otherTimeframe->getEndTime() ) < strtotime( $this->getEndTime() ) ) ) ) { + return true; + } + + // Check if both timeframes have the same start and end time + if ( strtotime( $this->getEndTime() ) && strtotime( $otherTimeframe->getEndTime() ) && strtotime( $this->getEndTime() ) === strtotime( $otherTimeframe->getEndTime() ) && strtotime( $this->getStartTime() ) === strtotime( $otherTimeframe->getStartTime() ) ) { return true; } - // If none of the above conditions are true, there is no overlap - return false; - } + // If none of the above conditions are true, there is no overlap + return false; + } /** * Returns weekdays array. * This means what weekdays are selected for this timeframe. * This only makes sense when the grid is repeating weekly. - * + * * @return mixed */ public function getWeekDays() { @@ -958,20 +967,20 @@ public function getWeekDays() { * Returns grid size in hours. * This means the length of the individual bookable slots. * For example if the grid is 2, the bookable slots are 2 hours long. - * + * * @return int|null */ public function getGridSize(): ?int { if ( $this->isFullDay() ) { return 24; } elseif ( $this->getGrid() === 0 ) { - //this is for slot timeframes + // this is for slot timeframes $startTime = strtotime( $this->getMeta( 'start-time' ) ); $endTime = strtotime( $this->getMeta( 'end-time' ) ); return intval( round( abs( $endTime - $startTime ) / 3600, 2 ) ); } else { - //this is for hourly timeframes, the grid will be 1, because each hour is bookable + // this is for hourly timeframes, the grid will be 1, because each hour is bookable return intval( $this->getGrid() ); } } @@ -979,6 +988,7 @@ public function getGridSize(): ?int { /** * Gets an array of dates that were manually selected by the user. * The dates are in the format YYYY-MM-DD + * * @return String[] */ public function getManualSelectionDates(): array { @@ -994,11 +1004,10 @@ public function getManualSelectionDates(): array { /** * Returns true if booking codes shall be shown in frontend. - * + * * @return bool */ - public function showBookingCodes() : bool - { + public function showBookingCodes(): bool { return $this->getMeta( self::META_SHOW_BOOKING_CODES ) === 'on'; } @@ -1068,7 +1077,7 @@ public function getStartTimeDateTime(): ?DateTime { if ( ! $startDateString ) { return null; } - $startDate = Wordpress::getUTCDateTimeByTimestamp( $startDateString ); + $startDate = Wordpress::getUTCDateTimeByTimestamp( $startDateString ); if ( $startTimeString ) { $startTime = Wordpress::getUTCDateTimeByTimestamp( strtotime( $startTimeString ) ); $startDate->setTime( $startTime->format( 'H' ), $startTime->format( 'i' ) ); @@ -1088,7 +1097,7 @@ public function getStartTimeDateTime(): ?DateTime { */ public function getEndDateDateTime(): ?DateTime { $endDateString = intval( $this->getMeta( self::REPETITION_END ) ); - if (! $endDateString ){ + if ( ! $endDateString ) { return null; } return Wordpress::getUTCDateTimeByTimestamp( $endDateString ); @@ -1100,12 +1109,13 @@ public function getEndDateDateTime(): ?DateTime { * We need to do this weird conversion because the end date is stored as a local timestamp. * * TODO: Can throw uncaught exception. + * * @return DateTime * @throws Exception */ public function getUTCEndDateDateTime(): ?DateTime { $endDateString = intval( $this->getMeta( self::REPETITION_END ) ); - if (! $endDateString ){ + if ( ! $endDateString ) { return null; } if ( $this->isFullDay() ) { @@ -1170,25 +1180,25 @@ public function isLocked(): bool { */ public function getAdmins(): array { $location = $this->getLocation(); - if (! empty($location)) { + if ( ! empty( $location ) ) { $locationAdminIds = $location->getAdmins(); } $item = $this->getItem(); - if (! empty($item)) { + if ( ! empty( $item ) ) { $itemAdminIds = $item->getAdmins(); } - if ( empty($locationAdminIds) && empty($itemAdminIds) ) { + if ( empty( $locationAdminIds ) && empty( $itemAdminIds ) ) { return []; } - if ( empty($locationAdminIds) ) { + if ( empty( $locationAdminIds ) ) { return $itemAdminIds; } - if ( empty($itemAdminIds) ) { + if ( empty( $itemAdminIds ) ) { return $locationAdminIds; } - return array_unique( array_merge ($locationAdminIds,$itemAdminIds) ); + return array_unique( array_merge( $locationAdminIds, $itemAdminIds ) ); } /** @@ -1200,26 +1210,25 @@ public function getAdmins(): array { * y = yearly * manual = manual selection of dates * norep = no repetition - * + * * @return mixed */ public function getRepetition() { return $this->getMeta( self::META_REPETITION ); } - /** - * Returns first bookable day based on the defined booking startday offset in timeframe - * - * @return string date format Y-m-d - */ - public function getFirstBookableDay() { - $offset = $this->getFieldValue( Timeframe::META_BOOKING_START_DAY_OFFSET ) ?: 0; - $today = current_datetime()->format('Y-m-d'); - return date( 'Y-m-d', strtotime( $today . ' + ' . $offset . ' days' ) ); - - } + /** + * Returns first bookable day based on the defined booking startday offset in timeframe + * + * @return string date format Y-m-d + */ + public function getFirstBookableDay() { + $offset = $this->getFieldValue( self::META_BOOKING_START_DAY_OFFSET ) ?: 0; + $today = current_datetime()->format( 'Y-m-d' ); + return date( 'Y-m-d', strtotime( $today . ' + ' . $offset . ' days' ) ); + } - public function getMaxDays():int{ - return $this->getMeta(self::META_MAX_DAYS); + public function getMaxDays(): int { + return $this->getMeta( self::META_MAX_DAYS ); } } diff --git a/src/Model/Week.php b/src/Model/Week.php index 05eb814d5..8c38bb445 100644 --- a/src/Model/Week.php +++ b/src/Model/Week.php @@ -15,13 +15,14 @@ class Week { /** - * @var integer + * @var int */ protected $year; /** * Day in the year to start the week from (0-365) - * @var integer + * + * @var int */ protected $dayOfYear; @@ -50,9 +51,9 @@ class Week { * * @param $year * @param $dayOfYear - * @param array $locations - * @param array $items - * @param array $types + * @param array $locations + * @param array $items + * @param array $types * @param Timeframe[] $possibleTimeframes Timeframes that might be relevant for this week, need to be filtered. */ public function __construct( $year, $dayOfYear, array $locations = [], array $items = [], array $types = [], array $possibleTimeframes = [] ) { @@ -93,7 +94,7 @@ public function getDays() { $dto = Wordpress::getUTCDateTimeByTimestamp( $timestamp ); $days = array(); - for ( $i = 0; $i < 7; $i ++ ) { + for ( $i = 0; $i < 7; $i++ ) { $dayDate = $dto->format( 'Y-m-d' ); $days[] = new Day( $dayDate, $this->locations, $this->items, $this->types, $this->timeframes ?: [] ); $dayOfWeek = $dto->format( 'w' ); @@ -113,6 +114,7 @@ public function getDays() { /** * Will return the timestamp of the first second of the given week. + * * @return int */ public function getStartTimestamp(): int { @@ -124,6 +126,7 @@ public function getStartTimestamp(): int { /** * Will return the timestamp of the last second of the given week. + * * @return int */ public function getEndTimestamp(): int { @@ -140,5 +143,4 @@ public function getEndTimestamp(): int { private function getYearTimestamp() { return mktime( 0, 0, 0, 1, 1, $this->year ); } - } diff --git a/src/Plugin.php b/src/Plugin.php index 50dc971c1..b9839abfc 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -39,7 +39,7 @@ class Plugin { /** * CB-Manager id. - * + * * @var string */ public static $CB_MANAGER_ID = 'cb_manager'; @@ -82,17 +82,18 @@ public static function deactivation() { * This is why we now assign the CB-Manager the capabilities of the admin, the supposedly correct behaviour is commented out below. * * Therefore, this function does not work differently, it just has the same behaviour when plugin is activated through wp-cli or through the admin interface. + * * @return void */ public static function addCPTRoleCaps() { - //admins are allowed to see all custom post types - $adminAllowedCPT = self::getCustomPostTypes(); + // admins are allowed to see all custom post types + $adminAllowedCPT = self::getCustomPostTypes(); $CBManagerAllowedCPT = self::getCBManagerCustomPostTypes(); // Add capabilities for user roles foreach ( $adminAllowedCPT as $customPostType ) { self::addRoleCaps( $customPostType::$postType, 'administrator' ); - //assign all capabilities of admin to CB-Manager (see comment above) - //We deliberately don't use the getManagerRoles from the UserRepository here, because the custom roles should be able to define their own permissions + // assign all capabilities of admin to CB-Manager (see comment above) + // We deliberately don't use the getManagerRoles from the UserRepository here, because the custom roles should be able to define their own permissions self::addRoleCaps( $customPostType::$postType, self::$CB_MANAGER_ID ); } /* @@ -104,13 +105,13 @@ public static function addCPTRoleCaps() { /** * Returns needed roles and caps for specific roles - * + * * @return \bool[][] */ - public static function getRoleCapMapping( $roleName = null) { + public static function getRoleCapMapping( $roleName = null ) { if ( $roleName === null ) { return [ - //We deliberately don't use the getManagerRoles from the UserRepository here, because the custom roles should be able to define their own permissions + // We deliberately don't use the getManagerRoles from the UserRepository here, because the custom roles should be able to define their own permissions self::$CB_MANAGER_ID => [ 'read' => true, 'manage_' . COMMONSBOOKING_PLUGIN_SLUG => true, @@ -121,11 +122,10 @@ public static function getRoleCapMapping( $roleName = null) { 'manage_' . COMMONSBOOKING_PLUGIN_SLUG => true, ], ]; - } - else { + } else { $roleCapMapping = self::getRoleCapMapping(); return [ - $roleName => $roleCapMapping[$roleName] + $roleName => $roleCapMapping[ $roleName ], ]; } } @@ -139,7 +139,7 @@ public static function addCustomUserRoles() { if ( ! $role ) { $role = add_role( $roleName, - // TODO we should set a translatable role display name - for now its not defined at any place + // TODO we should set a translatable role display name - for now its not defined at any place $roleName ); } @@ -156,6 +156,7 @@ public static function addCustomUserRoles() { * All CustomPostType classes extend the CustomPostType class and must be registered in this method. * When defining a CustomPostType, you must also define a model for it, which extends the CustomPost class. * The existence of a model is checked in the @see PluginTest::testGetCustomPostTypes() test. + * * @return CustomPostType[] */ public static function getCustomPostTypes(): array { @@ -171,13 +172,14 @@ public static function getCustomPostTypes(): array { /** * Tests if a given post belongs to our CPTs + * * @param $post int|\WP_Post - post id or post object * * @return bool */ - public static function isPostCustomPostType($post): bool { - if (is_int($post)) { - $post = get_post($post); + public static function isPostCustomPostType( $post ): bool { + if ( is_int( $post ) ) { + $post = get_post( $post ); } if ( empty( $post ) ) { @@ -185,12 +187,12 @@ public static function isPostCustomPostType($post): bool { } $validPostTypes = self::getCustomPostTypesLabels(); - return in_array($post->post_type,$validPostTypes); + return in_array( $post->post_type, $validPostTypes ); } /** * Returns only custom post types, which are allowed for cb manager - * + * * @return array */ public static function getCBManagerCustomPostTypes(): array { @@ -253,11 +255,11 @@ public static function admin_init() { // Check if we need to run post options updated actions if ( get_transient( 'commonsbooking_options_saved' ) == 1 ) { - AdminOptions::SetOptionsDefaultValues(); + AdminOptions::setOptionsDefaultValues(); flush_rewrite_rules(); - //checks if all the booking rules are in the correct format, complain if not + // checks if all the booking rules are in the correct format, complain if not BookingRuleApplied::validateRules(); set_transient( 'commonsbooking_options_saved', 0 ); } @@ -323,7 +325,7 @@ public static function addMenuPages() { '' ); - //Add menu item for mass operations + // Add menu item for mass operations add_submenu_page( 'cb-dashboard', esc_html__( 'Mass Operations', 'commonsbooking' ), @@ -338,20 +340,20 @@ public static function addMenuPages() { /** * Handles the validation of booking forms. We customize the transient so that only the user that is supposed to see the transient will * actually see it. + * * @return void */ public static function handleBookingForms(): void { try { \CommonsBooking\Wordpress\CustomPostType\Booking::handleFormRequest(); - } - catch ( BookingDeniedException $e ) { + } catch ( BookingDeniedException $e ) { set_transient( \CommonsBooking\Wordpress\CustomPostType\Booking::ERROR_TYPE . '-' . get_current_user_id(), $e->getMessage(), - 30 //Expires very quickly, so that outdated messsages will not be shown to the user + 30 // Expires very quickly, so that outdated messsages will not be shown to the user ); $targetUrl = $e->getRedirectUrl(); - if ( $targetUrl) { + if ( $targetUrl ) { header( 'Location: ' . $targetUrl ); exit(); } @@ -398,7 +400,7 @@ public static function filterAdminBodyClass( $classes ) { public static function registerCustomPostTypes() { foreach ( self::getCustomPostTypes() as $customPostType ) { $cptArgs = $customPostType->getArgs(); - //make export possible when using WP_DEBUG, this allows us to use the export feature for creating new E2E tests + // make export possible when using WP_DEBUG, this allows us to use the export feature for creating new E2E tests if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { $cptArgs['can_export'] = true; } @@ -417,18 +419,18 @@ public static function registerPostStates() { } } - /** + /** * Registers category taxonomy for Custom Post Type Item - * - * TODO: This can probably be re-factored to the more generic CustomPostType - * + * + * TODO: This can probably be re-factored to the more generic CustomPostType + * * @return void */ public static function registerItemTaxonomy() { $customPostType = Item::getPostType(); - $taxonomy = $customPostType . 's_category'; + $taxonomy = $customPostType . 's_category'; - $result = register_taxonomy( + $result = register_taxonomy( $taxonomy, $customPostType, array( @@ -437,7 +439,7 @@ public static function registerItemTaxonomy() { 'hierarchical' => true, 'show_in_rest' => true, 'public' => true, - 'show_admin_column' => true + 'show_admin_column' => true, ) ); @@ -446,16 +448,17 @@ public static function registerItemTaxonomy() { wp_die( $result->get_error_message() ); } - //hook the term updates to the item post type function. This only runs when a term is updated but that is enough. When a term is added, the post is saved and therefore the other hook is triggered which also runs the same function. + // hook the term updates to the item post type function. This only runs when a term is updated but that is enough. When a term is added, the post is saved and therefore the other hook is triggered which also runs the same function. add_action( 'saved_' . $taxonomy, array( 'CommonsBooking\Wordpress\CustomPostType\Item', 'termChange' ), 10, 3 ); add_action( 'delete_' . $taxonomy, array( 'CommonsBooking\Wordpress\CustomPostType\Item', 'termChange' ), 10, 3 ); - //hook this for later, if we run it now, it would fail + // hook this for later, if we run it now, it would fail add_action( 'cmb2_admin_init', array( self::class, 'registerItemTaxonomyMetaboxes' ) ); } /** * Add custom label for item categories that will be displayed in the map filter groups. + * * @return void */ public static function registerItemTaxonomyMetaboxes() { @@ -483,14 +486,14 @@ public static function registerItemTaxonomyMetaboxes() { /** * Registers category taxonomy for Custom Post Type Location - * + * * @return void */ public static function registerLocationTaxonomy() { $customPostType = Location::getPostType(); - $taxonomy = $customPostType . 's_category'; + $taxonomy = $customPostType . 's_category'; - $result = register_taxonomy( + $result = register_taxonomy( $taxonomy, $customPostType, array( @@ -498,7 +501,7 @@ public static function registerLocationTaxonomy() { 'rewrite' => array( 'slug' => $customPostType . '-cat' ), 'hierarchical' => true, 'show_in_rest' => true, - 'show_admin_column' => true + 'show_admin_column' => true, ) ); @@ -507,7 +510,7 @@ public static function registerLocationTaxonomy() { wp_die( $result->get_error_message() ); } - //hook the term updates to the location post type function. This only runs when a term is updated but that is enough. When a term is added, the post is saved and therefore the other hook is triggered which also runs the same function. + // hook the term updates to the location post type function. This only runs when a term is updated but that is enough. When a term is added, the post is saved and therefore the other hook is triggered which also runs the same function. add_action( 'saved_' . $taxonomy, array( 'CommonsBooking\Wordpress\CustomPostType\Location', 'termChange' ), 10, 3 ); add_action( 'delete_' . $taxonomy, array( 'CommonsBooking\Wordpress\CustomPostType\Location', 'termChange' ), 10, 3 ); } @@ -522,7 +525,7 @@ public static function renderError() { Model\Timeframe::ORPHANED_TYPE, BookingCode::ERROR_TYPE, OptionsTab::ERROR_TYPE, - Model\Booking::ERROR_TYPE, + Model\Booking::ERROR_TYPE, ]; foreach ( $errorTypes as $errorType ) { @@ -578,25 +581,25 @@ public static function registerAdminOptions() { public static function registerScriptsAndStyles() { $base = COMMONSBOOKING_PLUGIN_ASSETS_URL . 'packaged/'; - $version_file_path = COMMONSBOOKING_PLUGIN_DIR . 'assets/packaged/dist.json'; - $version_file_content = file_get_contents($version_file_path); - $versions = json_decode($version_file_content, true); - if (JSON_ERROR_NONE !== json_last_error()) { - trigger_error("Unable to parse commonsbooking asset version file in $version_file_path."); + $version_file_path = COMMONSBOOKING_PLUGIN_DIR . 'assets/packaged/dist.json'; + $version_file_content = file_get_contents( $version_file_path ); + $versions = json_decode( $version_file_content, true ); + if ( JSON_ERROR_NONE !== json_last_error() ) { + trigger_error( "Unable to parse commonsbooking asset version file in $version_file_path." ); } // spin.js - wp_register_script('cb-spin', $base . 'spin-js/spin.min.js', [], $versions['spin.js']); + wp_register_script( 'cb-spin', $base . 'spin-js/spin.min.js', [], $versions['spin.js'] ); // leaflet - wp_register_script('cb-leaflet', $base . 'leaflet/leaflet.js',[], $versions['leaflet']); - wp_register_style('cb-leaflet', $base . 'leaflet/leaflet.css', [], $versions['leaflet']); + wp_register_script( 'cb-leaflet', $base . 'leaflet/leaflet.js', [], $versions['leaflet'] ); + wp_register_style( 'cb-leaflet', $base . 'leaflet/leaflet.css', [], $versions['leaflet'] ); // leaflet markercluster wp_register_script( 'cb-leaflet-markercluster', $base . 'leaflet-markercluster/leaflet.markercluster.js', - ['cb-leaflet'], + [ 'cb-leaflet' ], $versions['leaflet.markercluster'] ); wp_register_style( @@ -608,7 +611,7 @@ public static function registerScriptsAndStyles() { wp_register_style( 'cb-leaflet-markercluster', $base . 'leaflet-markercluster/MarkerCluster.Default.css', - ['cb-leaflet-markercluster-base'], + [ 'cb-leaflet-markercluster-base' ], $versions['leaflet.markercluster'] ); @@ -616,13 +619,13 @@ public static function registerScriptsAndStyles() { wp_register_script( 'cb-leaflet-easybutton', $base . 'leaflet-easybutton/easy-button.js', - ['cb-leaflet'], + [ 'cb-leaflet' ], $versions['leaflet-easybutton'] ); wp_register_style( 'cb-leaflet-easybutton', $base . 'leaflet-easybutton/easy-button.css', - ['cb-leaflet'], + [ 'cb-leaflet' ], $versions['leaflet-easybutton'] ); @@ -630,7 +633,7 @@ public static function registerScriptsAndStyles() { wp_register_script( 'cb-leaflet-spin', $base . 'leaflet-spin/leaflet.spin.min.js', - ['cb-leaflet', 'cb-spin'], + [ 'cb-leaflet', 'cb-spin' ], $versions['leaflet-spin'] ); @@ -638,13 +641,13 @@ public static function registerScriptsAndStyles() { wp_register_script( 'cb-leaflet-messagebox', COMMONSBOOKING_MAP_ASSETS_URL . 'leaflet-messagebox/leaflet-messagebox.js', - ['cb-leaflet'], + [ 'cb-leaflet' ], '1.1', ); wp_register_style( 'cb-leaflet-messagebox', COMMONSBOOKING_MAP_ASSETS_URL . 'leaflet-messagebox/leaflet-messagebox.css', - ['cb-leaflet'], + [ 'cb-leaflet' ], '1.1' ); @@ -652,43 +655,44 @@ public static function registerScriptsAndStyles() { wp_register_script( 'cb-jquery-overscroll', COMMONSBOOKING_MAP_ASSETS_URL . 'overscroll/jquery.overscroll.min.js', - ['jquery'], + [ 'jquery' ], '1.7.7' ); - //cb_map shortcode - wp_register_script( 'cb-map-filters', + // cb_map shortcode + wp_register_script( + 'cb-map-filters', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-filters.js', - ['jquery'], + [ 'jquery' ], COMMONSBOOKING_MAP_PLUGIN_DATA['Version'] ); wp_register_script( 'cb-map-shortcode', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-shortcode.js', - ['jquery', 'cb-jquery-overscroll', 'cb-leaflet', 'cb-leaflet-easybutton', 'cb-leaflet-markercluster', 'cb-leaflet-messagebox', 'cb-leaflet-spin', 'cb-map-filters'], + [ 'jquery', 'cb-jquery-overscroll', 'cb-leaflet', 'cb-leaflet-easybutton', 'cb-leaflet-markercluster', 'cb-leaflet-messagebox', 'cb-leaflet-spin', 'cb-map-filters' ], COMMONSBOOKING_MAP_PLUGIN_DATA['Version'] ); wp_register_style( 'cb-map-shortcode', COMMONSBOOKING_MAP_ASSETS_URL . 'css/cb-map-shortcode.css', - ['dashicons', 'cb-leaflet', 'cb-leaflet-easybutton', 'cb-leaflet-markercluster', 'cb-leaflet-messagebox'], + [ 'dashicons', 'cb-leaflet', 'cb-leaflet-easybutton', 'cb-leaflet-markercluster', 'cb-leaflet-messagebox' ], COMMONSBOOKING_MAP_PLUGIN_DATA['Version'] ); // vue - wp_register_script('cb-vue', $base . 'vue/vue.runtime.global.prod.js', [], $versions['vue']); + wp_register_script( 'cb-vue', $base . 'vue/vue.runtime.global.prod.js', [], $versions['vue'] ); // commons-search wp_register_script( 'cb-commons-search', $base . 'commons-search/commons-search.umd.js', - ['cb-leaflet', 'cb-leaflet-markercluster', 'cb-vue'], + [ 'cb-leaflet', 'cb-leaflet-markercluster', 'cb-vue' ], $versions['@commonsbooking/frontend'] ); wp_register_style( 'cb-commons-search', $base . 'commons-search/style.css', - ['cb-leaflet', 'cb-leaflet-markercluster'], + [ 'cb-leaflet', 'cb-leaflet-markercluster' ], $versions['@commonsbooking/frontend'] ); } @@ -698,14 +702,14 @@ public function registerShortcodes() { } /** - * Registers all user data exporters ({@link https://developer.wordpress.org/plugins/privacy/adding-the-personal-data-exporter-to-your-plugin/}). - * - * @param array $exporters - * - * @return mixed - */ + * Registers all user data exporters ({@link https://developer.wordpress.org/plugins/privacy/adding-the-personal-data-exporter-to-your-plugin/}). + * + * @param array $exporters + * + * @return mixed + */ public static function registerUserDataExporters( $exporters ) { - $exporters[COMMONSBOOKING_PLUGIN_SLUG] = array( + $exporters[ COMMONSBOOKING_PLUGIN_SLUG ] = array( 'exporter_friendly_name' => __( 'CommonsBooking Bookings', 'commonsbooking' ), 'callback' => array( \CommonsBooking\Wordpress\CustomPostType\Booking::class, 'exportUserBookingsByEmail' ), ); @@ -720,9 +724,9 @@ public static function registerUserDataExporters( $exporters ) { * @return mixed */ public static function registerUserDataErasers( $erasers ) { - $erasers[COMMONSBOOKING_PLUGIN_SLUG] = array( + $erasers[ COMMONSBOOKING_PLUGIN_SLUG ] = array( 'eraser_friendly_name' => __( 'CommonsBooking Bookings', 'commonsbooking' ), - 'callback' => array( \CommonsBooking\Wordpress\CustomPostType\Booking::class, 'removeUserBookingsByEmail'), + 'callback' => array( \CommonsBooking\Wordpress\CustomPostType\Booking::class, 'removeUserBookingsByEmail' ), ); return $erasers; } @@ -747,13 +751,13 @@ public function init() { add_action( 'init', array( self::class, 'registerLocationTaxonomy' ), 30 ); // register admin options page - add_action('init', array(self::class, 'registerAdminOptions'), 40); + add_action( 'init', array( self::class, 'registerAdminOptions' ), 40 ); - //loads the Scheduler - add_action( 'init', array( Scheduler::class, 'initHooks' ) , 40); + // loads the Scheduler + add_action( 'init', array( Scheduler::class, 'initHooks' ), 40 ); - //handle the booking forms, needs to happen after taxonomy registration so that we can access the taxonomy - add_action('init', array(self::class, 'handleBookingForms'), 50); + // handle the booking forms, needs to happen after taxonomy registration so that we can access the taxonomy + add_action( 'init', array( self::class, 'handleBookingForms' ), 50 ); // admin init tasks add_action( 'admin_init', array( self::class, 'admin_init' ), 30 ); @@ -768,20 +772,20 @@ public function init() { add_filter( 'parent_file', array( $this, 'setParentFile' ) ); // register scripts - add_action('init', array($this, 'registerScriptsAndStyles')); + add_action( 'init', array( $this, 'registerScriptsAndStyles' ) ); // register shortcodes - add_action('init', array($this, 'registerShortcodes')); + add_action( 'init', array( $this, 'registerShortcodes' ) ); // Remove cache items on save. add_action( 'wp_insert_post', array( $this, 'savePostActions' ), 10, 3 ); - add_action( 'wp_enqueue_scripts', array( Plugin::class, 'addWarmupAjaxToOutput' ) ); - add_action( 'admin_enqueue_scripts', array( Plugin::class, 'addWarmupAjaxToOutput' ) ); + add_action( 'wp_enqueue_scripts', array( self::class, 'addWarmupAjaxToOutput' ) ); + add_action( 'admin_enqueue_scripts', array( self::class, 'addWarmupAjaxToOutput' ) ); - //Add custom hook to clear cache from cronjob + // Add custom hook to clear cache from cronjob add_action( self::$clearCacheHook, array( $this, 'clearCache' ) ); - add_action('plugins_loaded', array($this, 'commonsbooking_load_textdomain'), 20); + add_action( 'plugins_loaded', array( $this, 'commonsbooking_load_textdomain' ), 20 ); $map_admin = new LocationMapAdmin(); add_action( 'plugins_loaded', array( $map_admin, 'load_location_map_admin' ) ); @@ -797,31 +801,33 @@ public function init() { // renders custom update notice on plugin listing add_action( - 'in_plugin_update_message-' . COMMONSBOOKING_PLUGIN_BASE, - function ( $plugin_data ) { - $upgrade = new Upgrade(COMMONSBOOKING_VERSION, $plugin_data['new_version']); - $upgrade->updateNotice(); - } - ); - - // add ajax search for cmb2 fields (e.g. user search etc.) - add_filter('cmb2_field_ajax_search_url', function(){ - return (COMMONSBOOKING_PLUGIN_URL . '/vendor/ed-itsolutions/cmb2-field-ajax-search/'); - }); - - //hook into WordPress personal data exporter + 'in_plugin_update_message-' . COMMONSBOOKING_PLUGIN_BASE, + function ( $plugin_data ) { + $upgrade = new Upgrade( COMMONSBOOKING_VERSION, $plugin_data['new_version'] ); + $upgrade->updateNotice(); + } + ); + + // add ajax search for cmb2 fields (e.g. user search etc.) + add_filter( + 'cmb2_field_ajax_search_url', + function () { + return ( COMMONSBOOKING_PLUGIN_URL . '/vendor/ed-itsolutions/cmb2-field-ajax-search/' ); + } + ); + + // hook into WordPress personal data exporter add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'registerUserDataExporters' ) ); - //hook into WordPress personal data eraser + // hook into WordPress personal data eraser add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'registerUserDataErasers' ) ); - // iCal rewrite + // iCal rewrite iCalendar::initRewrite(); - } /** - * Loads text domain for (from local file or wordpress plugin-dir) + * Loads text domain for (from local file or WordPress plugin-dir) * * @return void */ @@ -844,7 +850,7 @@ public function commonsbooking_load_textdomain() { /** * Removes cache item in connection to post_type. - * + * * @TODO: Add test if cache is cleared correctly. * * @param $post_id @@ -919,13 +925,14 @@ function () { * Adds bookingcode actions. * They: * - Hook appropriate function to button that downloads the booking codes in the backend. + * * @see \CommonsBooking\View\BookingCodes::renderTable() * - Hook appropriate function to button that sends out emails with booking codes to the station. * @see \CommonsBooking\View\BookingCodes::renderDirectEmailRow() */ public function initBookingcodes() { add_action( 'admin_action_cb_download-bookingscodes-csv', array( View\BookingCodes::class, 'renderCSV' ), 10, 0 ); - add_action( 'admin_action_cb_email-bookingcodes', array(View\BookingCodes::class, 'emailCodes'), 10, 0); + add_action( 'admin_action_cb_email-bookingcodes', array( View\BookingCodes::class, 'emailCodes' ), 10, 0 ); } /** @@ -951,12 +958,12 @@ public function setParentFile( $parent_file ): string { if ( in_array( $current_screen->base, array( 'edit-tags' ) ) ) { if ( $current_screen->taxonomy && in_array( - $current_screen->taxonomy, - [ + $current_screen->taxonomy, + [ Location::$postType . 's_category', Item::$postType . 's_category', - ] - ) + ] + ) ) { return 'cb-dashboard'; } @@ -1011,4 +1018,4 @@ function AddImageSizes() { $crop ); } -} \ No newline at end of file +} diff --git a/src/Repository/ApiShares.php b/src/Repository/ApiShares.php index 5f9630a10..d5ce68a42 100644 --- a/src/Repository/ApiShares.php +++ b/src/Repository/ApiShares.php @@ -50,5 +50,4 @@ public static function getByKey( $key ) { } } } - } diff --git a/src/Repository/BookablePost.php b/src/Repository/BookablePost.php index da5722275..ed50d9302 100644 --- a/src/Repository/BookablePost.php +++ b/src/Repository/BookablePost.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Repository; - use CommonsBooking\Helper\Wordpress; use CommonsBooking\Plugin; use CommonsBooking\Wordpress\CustomPostType\Timeframe; @@ -17,11 +16,12 @@ abstract class BookablePost extends PostRepository { /** * Types which can be connected to each other via a Timeframe + * * @var string[] */ private static $relationalTypes = [ 'item', - 'location' + 'location', ]; /** @@ -47,7 +47,7 @@ public static function getByCurrentUser( bool $publishedOnly = false ): array { $args = array( 'post_type' => static::getPostType(), 'author' => $current_user->ID, - 'nopaging' => true + 'nopaging' => true, ); if ( $publishedOnly ) { $args['post_status'] = 'publish'; @@ -62,7 +62,7 @@ public static function getByCurrentUser( bool $publishedOnly = false ): array { // if user has admin-role get all available items $args = array( 'post_type' => static::getPostType(), - 'nopaging' => true + 'nopaging' => true, ); } else { // get all items where current user is assigned as admin @@ -78,9 +78,9 @@ public static function getByCurrentUser( bool $publishedOnly = false ): array { 'key' => '_' . static::getPostType() . '_admins', 'value' => '"' . $current_user->ID . '"', 'compare' => 'like', - ) + ), ), - 'nopaging' => true + 'nopaging' => true, ); } @@ -91,19 +91,21 @@ public static function getByCurrentUser( bool $publishedOnly = false ): array { $query = new WP_Query( $args ); if ( $query->have_posts() ) { $items = array_merge( $items, $query->get_posts() ); - usort( $items, function ( $a, $b ) { - $comparison = strcmp( strtolower( $a->post_title ), strtolower( $b->post_title ) ); - - if ( $comparison < 0 ) { - return - 1; - } - if ( $comparison > 0 ) { - return 1; - } + usort( + $items, + function ( $a, $b ) { + $comparison = strcmp( strtolower( $a->post_title ), strtolower( $b->post_title ) ); - return $comparison; - } ); + if ( $comparison < 0 ) { + return - 1; + } + if ( $comparison > 0 ) { + return 1; + } + return $comparison; + } + ); } $tags = Wordpress::getPostIdArray( $items ); $tags[] = 'misc'; @@ -116,13 +118,16 @@ public static function getByCurrentUser( bool $publishedOnly = false ): array { /** * Gets all the defined terms for locations / items. * Will return an empty array if there are no terms or an error occurred. + * * @return int[]|string|string[]|\WP_Error|\WP_Term[] */ public static function getTerms() { - $terms = get_terms( array( - 'taxonomy' => static::getPostType() . 's_category', - 'hide_empty' => false, - ) ); + $terms = get_terms( + array( + 'taxonomy' => static::getPostType() . 's_category', + 'hide_empty' => false, + ) + ); if ( is_wp_error( $terms ) ) { return []; @@ -141,7 +146,7 @@ abstract protected static function getPostType(); * THIS METHOD DOES NOT SEEM TO BE USED ANYWHERE. * * @param $userId - * @param false $asModel - Wether the posts should be returned as their respective model class or as WP_Post + * @param false $asModel - Wether the posts should be returned as their respective model class or as WP_Post * * @return array */ @@ -196,6 +201,7 @@ public static function getByUserId( $userId, bool $asModel = false ): array { /** * Will get the class name of the model class that belongs to this post type. + * * @return mixed */ abstract protected static function getModelClass(); @@ -203,17 +209,16 @@ abstract protected static function getModelClass(); /** * Returns an array of CB item post objects * - * * @param array $args WP Post args - * @param bool $bookable + * @param bool $bookable * * @return array */ public static function get( array $args = array(), bool $bookable = false ) { $posts = []; $args['post_type'] = static::getPostType(); - $args['nopaging'] = true; - + $args['nopaging'] = true; + // Add custom taxonomy filter if ( array_key_exists( 'category_slug', $args ) ) { $args['taxonomy'] = static::getPostType() . 's_category'; @@ -261,7 +266,7 @@ public static function get( array $args = array(), bool $bookable = false ) { * @param $postId * @param $originType * @param $relatedType - * @param bool $bookable + * @param bool $bookable * * @return int[] Array of post ids * @throws Exception @@ -360,5 +365,4 @@ protected static function getRelatedPosts( $postId, $originType, $relatedType ): return $relatedPosts; } } - } diff --git a/src/Repository/Booking.php b/src/Repository/Booking.php index 4b3842fd9..c3439e97d 100644 --- a/src/Repository/Booking.php +++ b/src/Repository/Booking.php @@ -37,7 +37,7 @@ protected static function getEndTimestamp( $startTimestamp ) { /** * Returns bookings ending at day of timestamp. * - * @param int $timestamp + * @param int $timestamp * @param array $customArgs * * @return array|int[]|WP_Post[] @@ -83,7 +83,7 @@ public static function getEndingBookingsByDate( int $timestamp, array $customArg /** * Returns bookings beginning at day of timestamp. * - * @param int $timestamp + * @param int $timestamp * @param array $customArgs * * @return array|int[]|WP_Post[] @@ -213,8 +213,8 @@ function ( $post ) { * @param $endDate int * @param $locationId * @param $itemId - * @param array $customArgs - * @param array $postStatus + * @param array $customArgs + * @param array $postStatus * * @return \CommonsBooking\Model\Booking[] * @throws Exception @@ -351,12 +351,12 @@ public static function getForCurrentUser( * Returns bookings. This uses the CommonsBooking\Repository\Timeframe::get() method which * is not based on the WP_Query class but will perform its own SQL query. * - * @param array $locations - * @param array $items - * @param string|null $date Date-String in format YYYY-mm-dd - * @param bool $returnAsModel + * @param array $locations + * @param array $items + * @param string|null $date Date-String in format YYYY-mm-dd + * @param bool $returnAsModel * @param $minTimestamp - * @param array $postStatus + * @param array $postStatus * * @return array * @throws Exception @@ -386,9 +386,9 @@ public static function get( * this function will use the WP_Query class to perform the query allowing us to use the pagination features of WP_Query. * * @param \WP_User $user The user for which to get the bookings. - * @param int $page The current page that is processed. - * @param int $perPage The number of bookings per page. A lower number will result in faster queries. - * @param array $customArgs Valid WP_Query args array. + * @param int $page The current page that is processed. + * @param int $perPage The number of bookings per page. A lower number will result in faster queries. + * @param array $customArgs Valid WP_Query args array. * * @return Booking[] An array of Booking models. */ @@ -424,7 +424,6 @@ public static function getForUserPaginated( /** * Gets all bookings that are affected by the given restriction. * - * * @param \CommonsBooking\Model\Restriction $restriction * * @return \WP_Post[]|null @@ -450,7 +449,7 @@ public static function getByRestriction( \CommonsBooking\Model\Restriction $rest * @param $locationId * @param $startDate * @param $endDate - * @param null $postId + * @param null $postId * * @return \CommonsBooking\Model\Booking[]|null */ @@ -474,7 +473,6 @@ public static function getExistingBookings( $itemId, $locationId, $startDate, $e } return $existingBookingsInRange; - } /** @@ -516,8 +514,8 @@ function ( $post ) use ( $args ) { * and therefore do not have a valid timeframe anymore. * * @param int|null $startdate - * @param int[] $items - * @param int[] $locations + * @param int[] $items + * @param int[] $locations * * @return \CommonsBooking\Model\Booking[]|null * @throws Exception @@ -527,22 +525,23 @@ public static function getOrphaned( array $items = [], array $locations = [] ): ?array { - $startdate = $startdate ? $startdate : time(); //set startdate to now when no startdate is defined + $startdate = $startdate ? $startdate : time(); // set startdate to now when no startdate is defined $bookings = self::get( $locations, $items, null, true, $startdate, [ 'confirmed' ] ); - //check for bookings where location does not exist anymore + // check for bookings where location does not exist anymore - $bookings = array_filter( $bookings, function ( $booking ) { - if ( $booking->getBookableTimeFrame() ) { - return false; - } else { - return true; + $bookings = array_filter( + $bookings, + function ( $booking ) { + if ( $booking->getBookableTimeFrame() ) { + return false; + } else { + return true; + } } - - } ); + ); return $bookings; } - } diff --git a/src/Repository/BookingCodes.php b/src/Repository/BookingCodes.php index a1ce9cf18..f2bf13b1c 100644 --- a/src/Repository/BookingCodes.php +++ b/src/Repository/BookingCodes.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Repository; - use CommonsBooking\Exception\BookingCodeException; use CommonsBooking\Helper\Wordpress; use CommonsBooking\Model\BookingCode; @@ -22,12 +21,14 @@ class BookingCodes { /** * Table name of booking codes. + * * @var string */ public static string $tablename = 'cb_bookingcodes'; /** * Days to advance generation of booking codes. + * * @var int */ public const ADVANCE_GENERATION_DAYS = 365; @@ -35,10 +36,10 @@ class BookingCodes { /** * Returns booking codes for timeframe to display in backend Timeframe window. * - * @param int $timeframeId - ID of timeframe to get codes for + * @param int $timeframeId - ID of timeframe to get codes for * @param int|null $startDate - Where to get booking codes from (timestamp) * @param int|null $endDate - Where to get booking codes to (timestamp) - * @param int $advanceGenerationDays - Open-ended timeframes: If 0, generate code(s) until today. If >0, generate additional codes after today + * @param int $advanceGenerationDays - Open-ended timeframes: If 0, generate code(s) until today. If >0, generate additional codes after today * * @return array * @throws BookingCodeException @@ -53,7 +54,7 @@ public static function getCodes( int $timeframeId, int $startDate = null, int $e $timeframeEndDate = $timeframe->getRawEndDate(); // If timeframe does not qualify for booking codes, return empty array - if ( ! $timeframe->bookingCodesApplicable() ){ + if ( ! $timeframe->bookingCodesApplicable() ) { return []; } @@ -61,11 +62,11 @@ public static function getCodes( int $timeframeId, int $startDate = null, int $e $startDate = $timeframeStartDate; } - if ($timeframeEndDate && (! $endDate || $endDate > $timeframeEndDate ) ) { + if ( $timeframeEndDate && ( ! $endDate || $endDate > $timeframeEndDate ) ) { $endDate = $timeframeEndDate; } - //when we still don't have an end-date, we will just get the coming ADVANCE_GENERATION_DAYS (should default to 365 days) - if (! $endDate ) { + // when we still don't have an end-date, we will just get the coming ADVANCE_GENERATION_DAYS (should default to 365 days) + if ( ! $endDate ) { $endDate = strtotime( '+' . $advanceGenerationDays . ' days', null ); // null means date and time now // a code will be generated for $endDate because time generally > 00:00:00 (due to initialitaion with current date and time) } @@ -73,19 +74,20 @@ public static function getCodes( int $timeframeId, int $startDate = null, int $e $startDate = date( 'Y-m-d', $startDate ); $endDate = date( 'Y-m-d', $endDate ); - //check, if we have enough codes for the timeframe or if we need to generate more - //we only need to check, if we have an open-ended timeframe + // check, if we have enough codes for the timeframe or if we need to generate more + // we only need to check, if we have an open-ended timeframe // NOTE: there used to be a check if generation is necessary by checking the date of the last code. However, // as the codes are never deleted anymore, it is possible that they get fragmented with date gaps and the // check is not trivial anymore. Is is easier and safer to always try to generate codes. It is no serious // performance issue as getCodes() is only used in admin pages on particular admin actions. if ( ! $timeframe->getRawEndDate() ) { $startGenerationPeriod = new \DateTime( $startDate ); - $endGenerationPeriod = new \DateTime( $endDate ); + $endGenerationPeriod = new \DateTime( $endDate ); // set $endGenerationPeriod's time > 00:00:00 such that $endDate is included in DatePeriod iteration // and code is generated for $endDate - $endGenerationPeriod->setTime(0, 0, 1); - static::generatePeriod( $timeframe, + $endGenerationPeriod->setTime( 0, 0, 1 ); + static::generatePeriod( + $timeframe, new DatePeriod( $startGenerationPeriod, new DateInterval( 'P1D' ), @@ -97,7 +99,7 @@ public static function getCodes( int $timeframeId, int $startDate = null, int $e global $wpdb; $table_name = $wpdb->prefix . self::$tablename; - $sql = $wpdb->prepare( + $sql = $wpdb->prepare( "SELECT * FROM $table_name WHERE item = %d AND date BETWEEN %s AND %s @@ -107,7 +109,7 @@ public static function getCodes( int $timeframeId, int $startDate = null, int $e $startDate, $endDate ); - $bookingCodes = $wpdb->get_results($sql); + $bookingCodes = $wpdb->get_results( $sql ); self::backwardCompatibilityFilter( $bookingCodes, $timeframeId, $timeframe->getLocation()->ID ); // for backward compatibility: delete line in future cb @@ -121,7 +123,7 @@ public static function getCodes( int $timeframeId, int $startDate = null, int $e $codes[] = $bookingCodeObject; } - Plugin::setCacheItem( $codes, [$timeframeId] ); + Plugin::setCacheItem( $codes, [ $timeframeId ] ); return $codes; } @@ -135,39 +137,42 @@ public static function getCodes( int $timeframeId, int $startDate = null, int $e * The filtering can be omitted in future cb versions when backward compatibility with old cb is dropped. * * @param array &$bookingCodes reference of array of BookingCode|s. It is assumed that they all have the same itemId. - * @param int $preferredTimeframeId timeframeId to prefer when filtering - * @param int $preferredLocationId locationId to prefer when filtering + * @param int $preferredTimeframeId timeframeId to prefer when filtering + * @param int $preferredLocationId locationId to prefer when filtering * * @return void works by reference on param $bookingCodes */ - private static function backwardCompatibilityFilter(&$bookingCodes, $preferredTimeframeId, $preferredLocationId) { + private static function backwardCompatibilityFilter( &$bookingCodes, $preferredTimeframeId, $preferredLocationId ) { $filteredCodes = []; - $codesByDate = []; + $codesByDate = []; // Group booking codes by date foreach ( $bookingCodes as $code ) { $date = $code->date; - if (! isset($codesByDate[$date]) ) { - $codesByDate[$date] = []; + if ( ! isset( $codesByDate[ $date ] ) ) { + $codesByDate[ $date ] = []; } - $codesByDate[$date][] = $code; + $codesByDate[ $date ][] = $code; } // For each date, filter out codes to ensure only one entry per date foreach ( $codesByDate as $date => $codes ) { - if ( count($codes) > 1 ) { + if ( count( $codes ) > 1 ) { // Keep entries matching $preferredTimeframeId and $preferredLocationId - $preferredCodes = array_filter( $codes, function($code) use ($preferredTimeframeId, $preferredLocationId ) { - return $code->timeframe == $preferredTimeframeId && $code->location == $preferredLocationId; - }); + $preferredCodes = array_filter( + $codes, + function ( $code ) use ( $preferredTimeframeId, $preferredLocationId ) { + return $code->timeframe == $preferredTimeframeId && $code->location == $preferredLocationId; + } + ); // If there are preferred codes, use them. Otherwise, use all codes. - $finalCodes = !empty($preferredCodes) ? $preferredCodes : $codes; + $finalCodes = ! empty( $preferredCodes ) ? $preferredCodes : $codes; // Pick the first code if there are still multiple entries - $filteredCodes[] = reset($finalCodes); + $filteredCodes[] = reset( $finalCodes ); } else { - $filteredCodes[] = reset($codes); + $filteredCodes[] = reset( $codes ); } } @@ -177,14 +182,14 @@ private static function backwardCompatibilityFilter(&$bookingCodes, $preferredTi /** * Gets a specific booking code by item ID and date. * - * @param int $itemId - ID of item attached to timeframe + * @param int $itemId - ID of item attached to timeframe * @param string $date - Date in format Y-m-d - * @param int $preferredTimeframeId only for compatibility with database entries created by old cb version. delete in future - * @param int $preferredLocationId see $preferredTimeframeId + * @param int $preferredTimeframeId only for compatibility with database entries created by old cb version. delete in future + * @param int $preferredLocationId see $preferredTimeframeId * * @return BookingCode|null */ - private static function lookupCode(int $itemId, string $date, int $preferredTimeframeId = 0, int $preferredLocationId = 0): ?BookingCode { + private static function lookupCode( int $itemId, string $date, int $preferredTimeframeId = 0, int $preferredLocationId = 0 ): ?BookingCode { global $wpdb; $table_name = $wpdb->prefix . self::$tablename; @@ -198,11 +203,11 @@ private static function lookupCode(int $itemId, string $date, int $preferredTime $date ); - $bookingCodes = $wpdb->get_results($sql); + $bookingCodes = $wpdb->get_results( $sql ); self::backwardCompatibilityFilter( $bookingCodes, $preferredTimeframeId, $preferredLocationId ); // for backward compatibility: delete line in future cb - if (count($bookingCodes)) { + if ( count( $bookingCodes ) ) { return new BookingCode( $bookingCodes[0]->date, $bookingCodes[0]->item, @@ -217,15 +222,15 @@ private static function lookupCode(int $itemId, string $date, int $preferredTime * Returns booking code by timeframe, location, item and date. If no code exist yet and timeframe does not have end-date, generate it. * * @param Timeframe $timeframe - Timeframe object to get code for - * @param int $itemId - ID of item attached to timeframe - * @param int $locationId - ID of location attached to timeframe (DEPRECATED, has no effect) - * @param string $date - Date in format Y-m-d - * @param int $advanceGenerationDays - Open-ended timeframes: If 0, generates code(s) until $date. If >0, generate additional codes after $date. + * @param int $itemId - ID of item attached to timeframe + * @param int $locationId - ID of location attached to timeframe (DEPRECATED, has no effect) + * @param string $date - Date in format Y-m-d + * @param int $advanceGenerationDays - Open-ended timeframes: If 0, generates code(s) until $date. If >0, generate additional codes after $date. * * @return BookingCode|null * @throws BookingCodeException */ - public static function getCode( Timeframe $timeframe, int $itemId, int $locationId, string $date, int $advanceGenerationDays = self::ADVANCE_GENERATION_DAYS ) : ?BookingCode { + public static function getCode( Timeframe $timeframe, int $itemId, int $locationId, string $date, int $advanceGenerationDays = self::ADVANCE_GENERATION_DAYS ): ?BookingCode { $cacheItem = Plugin::getCacheItem(); if ( $cacheItem ) { return $cacheItem; @@ -234,22 +239,22 @@ public static function getCode( Timeframe $timeframe, int $itemId, int $location $bookingCodeObject = static::lookupCode( $itemId, $date, $timeframe->ID, $locationId ); if ( ! $bookingCodeObject ) { - //when we have a timeframe without end-date we generate as many codes as we need - if (! $timeframe->getRawEndDate() && $timeframe->bookingCodesApplicable() ) { - $begin = $timeframe->getUTCStartDateDateTime(); - $endDate = new \DateTime($date); - $endDate->modify('+' . $advanceGenerationDays . ' days'); + // when we have a timeframe without end-date we generate as many codes as we need + if ( ! $timeframe->getRawEndDate() && $timeframe->bookingCodesApplicable() ) { + $begin = $timeframe->getUTCStartDateDateTime(); + $endDate = new \DateTime( $date ); + $endDate->modify( '+' . $advanceGenerationDays . ' days' ); // set $endDate's time > 00:00:00 so it will included in DatePeriod iteration and a code will be // generated for $endDate - $endDate->setTime(0, 0, 1); + $endDate->setTime( 0, 0, 1 ); $interval = DateInterval::createFromDateString( '1 day' ); - $period = new DatePeriod( $begin, $interval, $endDate ); - static::generatePeriod($timeframe,$period); + $period = new DatePeriod( $begin, $interval, $endDate ); + static::generatePeriod( $timeframe, $period ); $bookingCodeObject = static::lookupCode( $itemId, $date, $timeframe->ID, $locationId ); } } - Plugin::setCacheItem( $bookingCodeObject, [$timeframe->ID] ); + Plugin::setCacheItem( $bookingCodeObject, [ $timeframe->ID ] ); return $bookingCodeObject; } @@ -258,7 +263,7 @@ public static function getCode( Timeframe $timeframe, int $itemId, int $location /** * Creates booking-codes table; */ - public static function initBookingCodesTable() :void { + public static function initBookingCodesTable(): void { global $wpdb; global $cb_db_version; @@ -276,38 +281,37 @@ public static function initBookingCodesTable() :void { ) $charset_collate;"; // Include dbDelta since it's not part of autoloaded modules - require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); add_option( COMMONSBOOKING_PLUGIN_SLUG . '_bookingcodes_db_version', $cb_db_version ); } - /** - * Generates booking codes for timeframe. - * - * @param Timeframe $timeframe - * @param int $advanceGenerationDays - Open-ended timeframes: If 0, generate code(s) until today. If >0, generate additional codes after today. + /** + * Generates booking codes for timeframe. + * + * @param Timeframe $timeframe + * @param int $advanceGenerationDays - Open-ended timeframes: If 0, generate code(s) until today. If >0, generate additional codes after today. * - * @return bool - * @return bool - * @throws BookingCodeException - */ + * @return bool + * @return bool + * @throws BookingCodeException + */ public static function generate( Timeframe $timeframe, int $advanceGenerationDays = self::ADVANCE_GENERATION_DAYS ): bool { - if (! $timeframe->bookingCodesApplicable() ){ + if ( ! $timeframe->bookingCodesApplicable() ) { return false; } $begin = Wordpress::getUTCDateTime(); $begin->setTimestamp( $timeframe->getStartDate() ); - if ($timeframe->getRawEndDate()){ + if ( $timeframe->getRawEndDate() ) { $end = Wordpress::getUTCDateTime(); $end->setTimestamp( $timeframe->getRawEndDate() ); // set $end's time > 00:00:00 such that DatePeriod-iteration will include $end: - $end->setTime(0, 0, 1); - } - else { + $end->setTime( 0, 0, 1 ); + } else { $end = new \DateTime(); - $end->modify( '+' . $advanceGenerationDays . 'days'); + $end->modify( '+' . $advanceGenerationDays . 'days' ); // a code will be generated for the date in $end because its time generally > 00:00:00 (due to initialitaion with current date and time) } @@ -319,51 +323,54 @@ public static function generate( Timeframe $timeframe, int $advanceGenerationDay /** * Generate booking codes for a given period - * @param Timeframe $timeframe + * + * @param Timeframe $timeframe * @param DatePeriod $period * * @return true * @throws BookingCodeException */ - private static function generatePeriod( Timeframe $timeframe, DatePeriod $period): bool { + private static function generatePeriod( Timeframe $timeframe, DatePeriod $period ): bool { $bookingCodesArray = static::getCodesArray(); - if (! $bookingCodesArray ){ - throw new BookingCodeException( __( "No booking codes could be created because there were no booking codes to choose from. Please set some booking codes in the CommonsBooking settings.", 'commonsbooking' ) ); + if ( ! $bookingCodesArray ) { + throw new BookingCodeException( __( 'No booking codes could be created because there were no booking codes to choose from. Please set some booking codes in the CommonsBooking settings.', 'commonsbooking' ) ); } try { - //TODO #507 + // TODO #507 $location = $timeframe->getLocation(); } catch ( \Exception $e ) { - throw new BookingCodeException( __( "No booking codes could be created because the location of the timeframe could not be found.", 'commonsbooking' ) ); + throw new BookingCodeException( __( 'No booking codes could be created because the location of the timeframe could not be found.', 'commonsbooking' ) ); } try { - //TODO #507 + // TODO #507 $item = $timeframe->getItem(); } catch ( \Exception $e ) { - throw new BookingCodeException( __( "No booking codes could be created because the item of the timeframe could not be found.", 'commonsbooking' ) ); + throw new BookingCodeException( __( 'No booking codes could be created because the item of the timeframe could not be found.', 'commonsbooking' ) ); } - $todayMidnight = new \DateTime('today midnight', $period->getStartDate()->getTimezone()); + $todayMidnight = new \DateTime( 'today midnight', $period->getStartDate()->getTimezone() ); foreach ( $period as $dt ) { // do not generate any codes for past days - if ($dt < $todayMidnight) continue; + if ( $dt < $todayMidnight ) { + continue; + } $day = new Day( $dt->format( 'Y-m-d' ) ); if ( $day->isInTimeframe( $timeframe ) ) { // Check if a code already exists, if so DO NOT generate new // timeframeid and locationid are only for backward compatibility with database entries from old cb - if ( static::lookupCode($item->ID, $dt->format( 'Y-m-d' ), $timeframe->ID, $location->ID) ) { + if ( static::lookupCode( $item->ID, $dt->format( 'Y-m-d' ), $timeframe->ID, $location->ID ) ) { continue; } $bookingCode = new BookingCode( $dt->format( 'Y-m-d' ), $item->ID, - $bookingCodesArray[ random_int(0, count($bookingCodesArray) - 1) ] + $bookingCodesArray[ random_int( 0, count( $bookingCodesArray ) - 1 ) ] ); self::persist( $bookingCode, @@ -378,7 +385,8 @@ private static function generatePeriod( Timeframe $timeframe, DatePeriod $period /** * Stores a booking code in database without checking if code already exists (please check before) - * @param BookingCode $bookingCode + * + * @param BookingCode $bookingCode * @param timeframeId deprecated (only necessary to make database compatible to former versions of cb) * @param locationId deprecated (only necessary to make database compatible to former versions of cb) * @@ -395,7 +403,7 @@ public static function persist( BookingCode $bookingCode, $timeframeId = 0, $loc 'date' => $bookingCode->getDate(), 'location' => $locationId, // deprecated field, only for backward compatibility 'item' => $bookingCode->getItem(), - 'code' => $bookingCode->getCode() + 'code' => $bookingCode->getCode(), ) ); @@ -408,14 +416,16 @@ public static function persist( BookingCode $bookingCode, $timeframeId = 0, $loc * @return array - Array of booking codes, empty array if no booking codes are configured. */ private static function getCodesArray(): array { - $bookingCodes = Settings::getOption( 'commonsbooking_options_bookingcodes', 'bookingcodes' ); + $bookingCodes = Settings::getOption( 'commonsbooking_options_bookingcodes', 'bookingcodes' ); if ( ! $bookingCodes ) { return array(); } $bookingCodesArray = array_filter( explode( ',', trim( $bookingCodes ) ) ); - return array_map( function ( $item ) { - return preg_replace( "/\r|\n/", "", $item ); - }, $bookingCodesArray ); + return array_map( + function ( $item ) { + return preg_replace( "/\r|\n/", '', $item ); + }, + $bookingCodesArray + ); } - } diff --git a/src/Repository/CB1.php b/src/Repository/CB1.php index 3eb2f402c..0b519ada2 100644 --- a/src/Repository/CB1.php +++ b/src/Repository/CB1.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Repository; - use WP_Query; /** @@ -45,7 +44,7 @@ class CB1 { */ public static function isInstalled() { // we check for pages, since they have to be set up for the plugin to function. - $option_set_by_cb1 = esc_html(get_option('commons-booking-settings-pages')); + $option_set_by_cb1 = esc_html( get_option( 'commons-booking-settings-pages' ) ); if ( $option_set_by_cb1 ) { return true; @@ -56,6 +55,7 @@ public static function isInstalled() { /** * Get the old CB1 location post type posts + * * @return array */ public static function getLocations() { @@ -72,7 +72,7 @@ protected static function get( $postType ) { $args = array( 'post_type' => $postType, 'post_status' => 'any', - 'nopaging' => true + 'nopaging' => true, ); $query = new WP_Query( $args ); if ( $query->have_posts() ) { @@ -84,6 +84,7 @@ protected static function get( $postType ) { /** * Get the old CB1 item post type posts + * * @return array */ public static function getItems() { @@ -92,6 +93,7 @@ public static function getItems() { /** * Get the old CB1 bookings + * * @return mixed */ public static function getBookings() { @@ -103,6 +105,7 @@ public static function getBookings() { /** * Get the old CB1 timeframes + * * @return mixed */ public static function getTimeframes() { @@ -114,6 +117,7 @@ public static function getTimeframes() { /** * Get the old CB1 bookingcodes + * * @return mixed */ public static function getBookingCodes() { @@ -148,7 +152,7 @@ public static function getBookingCode( $id ): ?string { global $wpdb; $table_bookingcodes = $wpdb->prefix . self::$BOOKINGCODES_TABLE; - $sql = $wpdb->prepare( "SELECT bookingcode FROM $table_bookingcodes WHERE id = %d", $id); + $sql = $wpdb->prepare( "SELECT bookingcode FROM $table_bookingcodes WHERE id = %d", $id ); $result = $wpdb->get_results( $sql, ARRAY_A ); if ( $result && count( $result ) > 0 ) { @@ -169,7 +173,7 @@ public static function getCB2LocationId( int $locationId ) { } /** - * @param int $id + * @param int $id * @param string $type * * @return false|int @@ -179,7 +183,7 @@ protected static function getCB2PostIdByType( int $id, string $type ) { $table_postmeta = $wpdb->prefix . 'postmeta'; $table_posts = $wpdb->prefix . 'posts'; - $sql = $wpdb->prepare( + $sql = $wpdb->prepare( "SELECT post_id FROM $table_postmeta WHERE meta_key = '_cb_cb1_post_post_ID' AND @@ -189,7 +193,7 @@ protected static function getCB2PostIdByType( int $id, string $type ) { $id, $type ); - $result = $wpdb->get_results($sql); + $result = $wpdb->get_results( $sql ); if ( $result && count( $result ) > 0 ) { return $result[0]->post_id; @@ -229,7 +233,7 @@ public static function getCB2PostIdByCB1Id( $id ): ?int { global $wpdb; $table_postmeta = $wpdb->prefix . 'postmeta'; - $sql = $wpdb->prepare( + $sql = $wpdb->prepare( "SELECT meta_value as cb1_id, post_id as cb2_id FROM $table_postmeta WHERE @@ -249,6 +253,7 @@ public static function getCB2PostIdByCB1Id( $id ): ?int { /** * Returns CB1 taxonomies. + * * @return mixed */ public static function getCB1Taxonomies() { @@ -278,5 +283,4 @@ public static function getCB1Taxonomies() { " ); } - } diff --git a/src/Repository/Item.php b/src/Repository/Item.php index 1571a66b0..3a80cc660 100644 --- a/src/Repository/Item.php +++ b/src/Repository/Item.php @@ -11,13 +11,13 @@ class Item extends BookablePost { * * @param $locationId * - * @param bool $bookable + * @param bool $bookable * * @return array * @throws Exception */ public static function getByLocation( $locationId, bool $bookable = false ): array { - return self::getByRelatedPost($locationId, 'location', 'item', $bookable); + return self::getByRelatedPost( $locationId, 'location', 'item', $bookable ); } /** @@ -30,10 +30,10 @@ protected static function getPostType(): string { /** * This is the model class that belongs to the post type. * With the model class, you are able to perform additional functions on the post type. + * * @return string */ protected static function getModelClass(): string { return \CommonsBooking\Model\Item::class; } - } diff --git a/src/Repository/Location.php b/src/Repository/Location.php index 75af3e889..52bf03236 100644 --- a/src/Repository/Location.php +++ b/src/Repository/Location.php @@ -11,13 +11,13 @@ class Location extends BookablePost { * * @param $itemId * - * @param bool $bookable + * @param bool $bookable * * @return array * @throws Exception */ public static function getByItem( $itemId, bool $bookable = false ): array { - return self::getByRelatedPost($itemId, 'item', 'location', $bookable); + return self::getByRelatedPost( $itemId, 'item', 'location', $bookable ); } /** @@ -30,10 +30,10 @@ protected static function getPostType(): string { /** * This is the model class that belongs to the post type. * With the model class, you are able to perform additional functions on the post type. + * * @return string */ protected static function getModelClass(): string { return \CommonsBooking\Model\Location::class; } - } diff --git a/src/Repository/PostRepository.php b/src/Repository/PostRepository.php index b5686286d..95da650da 100644 --- a/src/Repository/PostRepository.php +++ b/src/Repository/PostRepository.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Repository; - use CommonsBooking\Plugin; use Exception; use WP_Post; @@ -31,9 +30,9 @@ public static function getPostById( $postId ) { if ( $post->post_type == \CommonsBooking\Wordpress\CustomPostType\Timeframe::getPostType() ) { $type = get_post_meta( $post->ID, 'type', true ); switch ( $type ) { - case \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_ID: //booking + case \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_ID: // booking return new \CommonsBooking\Model\Booking( $post ); - case \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_CANCELED_ID: //booking canceled + case \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_CANCELED_ID: // booking canceled return new \CommonsBooking\Model\Booking( $post ); } } @@ -54,10 +53,9 @@ public static function getPostById( $postId ) { return new \CommonsBooking\Model\Booking( $post ); } } - Plugin::setCacheItem( $post, [$postId] ); + Plugin::setCacheItem( $post, [ $postId ] ); return $post; } } - } diff --git a/src/Repository/Restriction.php b/src/Repository/Restriction.php index 0f018f2c8..161079c56 100644 --- a/src/Repository/Restriction.php +++ b/src/Repository/Restriction.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Repository; - use CommonsBooking\Helper\Wordpress; use CommonsBooking\Plugin; use Exception; @@ -12,6 +11,7 @@ class Restriction extends PostRepository { /** * Returns active restrictions. + * * @return \CommonsBooking\Model\Restriction[] * @throws Exception */ @@ -29,7 +29,6 @@ public static function get( if ( $cacheItem ) { return $cacheItem; } else { - $posts = self::queryPosts( $date, $minTimestamp, $postStatus ); if ( $posts && count( $posts ) ) { @@ -41,14 +40,14 @@ public static function get( $posts = self::filterPosts( $posts, $locations, $items ); } - // if returnAsModel == TRUE the result is a timeframe model instead of a wordpress object + // if returnAsModel == TRUE the result is a timeframe model instead of a WordPress object if ( $returnAsModel ) { $posts = self::castPostsToRestrictions( $posts ); } } $posts = $posts ?: []; - Plugin::setCacheItem( $posts, Wordpress::getTags($posts, $items, $locations), $customCacheKey ); + Plugin::setCacheItem( $posts, Wordpress::getTags( $posts, $items, $locations ), $customCacheKey ); return $posts; } @@ -85,15 +84,15 @@ private static function queryPosts( $date, $minTimestamp, $postStatus ) { // Complete query $query = " SELECT DISTINCT pm1.* from $table_posts pm1 - " . $dateQuery . " - " . self::getActiveQuery() . " + " . $dateQuery . ' + ' . self::getActiveQuery() . " WHERE pm1.post_type = '" . \CommonsBooking\Wordpress\CustomPostType\Restriction::getPostType() . "' AND pm1.post_status IN ('" . implode( "','", $postStatus ) . "') "; $posts = $wpdb->get_results( $query ); - Plugin::setCacheItem( $posts, Wordpress::getTags($posts) ); + Plugin::setCacheItem( $posts, Wordpress::getTags( $posts ) ); return $posts; } @@ -110,7 +109,8 @@ private static function getMinTimestampQuery( $minTimestamp ): string { global $wpdb; $table_postmeta = $wpdb->prefix . 'postmeta'; - return $wpdb->prepare( " + return $wpdb->prepare( + " INNER JOIN $table_postmeta pm4 ON pm4.post_id = pm1.id AND ( ( @@ -142,7 +142,7 @@ private static function getDateQuery( $date ): string { $table_postmeta = $wpdb->prefix . 'postmeta'; return $wpdb->prepare( - "INNER JOIN $table_postmeta pm4 ON + "INNER JOIN $table_postmeta pm4 ON pm4.post_id = pm1.id AND pm4.meta_key = '" . \CommonsBooking\Model\Restriction::META_START . "' AND pm4.meta_value BETWEEN 0 AND %d @@ -168,6 +168,7 @@ private static function getDateQuery( $date ): string { /** * Returns query to filter only active restrictions. + * * @return string */ private static function getActiveQuery(): string { @@ -194,47 +195,49 @@ private static function getActiveQuery(): string { * @return array */ private static function filterPosts( array $posts, array $locations, array $items ): array { - return array_filter( $posts, function ( $post ) use ( $locations, $items ) { - // Check if restriction is in relation to item and/or location - $location = intval( get_post_meta( $post->ID, \CommonsBooking\Model\Restriction::META_LOCATION_ID, true ) ); - $restrictionHasLocation = $location !== 0; - $restrictedLocationInLocations = $restrictionHasLocation && in_array( $location, $locations ); - - $item = intval( get_post_meta( $post->ID, \CommonsBooking\Model\Restriction::META_ITEM_ID, true ) ); - $restrictionHasItem = $item !== 0; - $restrictedItemInItems = $restrictionHasItem && in_array( $item, $items ); - - // No item or location for restriction set - $noLocationNoItem = ( ! $restrictionHasLocation && ! $restrictionHasItem ); - - // No location, item matching - $noLocationItemMatches = ( + return array_filter( + $posts, + function ( $post ) use ( $locations, $items ) { + // Check if restriction is in relation to item and/or location + $location = intval( get_post_meta( $post->ID, \CommonsBooking\Model\Restriction::META_LOCATION_ID, true ) ); + $restrictionHasLocation = $location !== 0; + $restrictedLocationInLocations = $restrictionHasLocation && in_array( $location, $locations ); + + $item = intval( get_post_meta( $post->ID, \CommonsBooking\Model\Restriction::META_ITEM_ID, true ) ); + $restrictionHasItem = $item !== 0; + $restrictedItemInItems = $restrictionHasItem && in_array( $item, $items ); + + // No item or location for restriction set + $noLocationNoItem = ( ! $restrictionHasLocation && ! $restrictionHasItem ); + + // No location, item matching + $noLocationItemMatches = ( ! $restrictionHasLocation && $restrictionHasItem && $restrictedItemInItems - ); + ); - // No item, location matching - $noItemLocationMatches = ( + // No item, location matching + $noItemLocationMatches = ( ! $restrictionHasItem && $restrictionHasLocation && $restrictedLocationInLocations - ); + ); - // Item and location matching - $itemAndLocationMatches = ( + // Item and location matching + $itemAndLocationMatches = ( $restrictionHasLocation && $restrictedLocationInLocations && $restrictionHasItem && $restrictedItemInItems - ); + ); - return - $noLocationNoItem || + return $noLocationNoItem || $noLocationItemMatches || $noItemLocationMatches || $itemAndLocationMatches; - } ); + } + ); } /** @@ -252,5 +255,4 @@ private static function castPostsToRestrictions( $posts ) { return $posts; } - -} \ No newline at end of file +} diff --git a/src/Repository/Timeframe.php b/src/Repository/Timeframe.php index 4905cb1d6..48843aa06 100644 --- a/src/Repository/Timeframe.php +++ b/src/Repository/Timeframe.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Repository; - use CommonsBooking\Helper\Helper; use CommonsBooking\Helper\Wordpress; use CommonsBooking\Model\Day; @@ -20,12 +19,12 @@ class Timeframe extends PostRepository { /** * Returns only bookable timeframes. * - * @param array $locations - * @param array $items - * @param string|null $date - * @param bool $returnAsModel + * @param array $locations + * @param array $items + * @param string|null $date + * @param bool $returnAsModel * @param $minTimestamp - * @param array $postStatus + * @param array $postStatus * * @return array * @throws Exception @@ -52,12 +51,12 @@ public static function getBookable( /** * Returns only bookable timeframes for current user. * - * @param array $locations - * @param array $items - * @param string|null $date - * @param bool $returnAsModel + * @param array $locations + * @param array $items + * @param string|null $date + * @param bool $returnAsModel * @param $minTimestamp - * @param array $postStatus + * @param array $postStatus * * @return array * @throws Exception @@ -80,7 +79,7 @@ public static function getBookableForCurrentUser( $postStatus ); - $bookableTimeframes = self::filterTimeframesForCurrentUser($bookableTimeframes); + $bookableTimeframes = self::filterTimeframesForCurrentUser( $bookableTimeframes ); return $bookableTimeframes; } @@ -94,13 +93,13 @@ public static function getBookableForCurrentUser( * TODO: Investigate * This function is not based on the WP_Query class, probably because of performance reasons. * - * @param array $locations - * @param array $items - * @param array $types + * @param array $locations + * @param array $items + * @param array $types * @param string|null $date Date-String in format YYYY-mm-dd - * @param bool $returnAsModel - * @param int|null $minTimestamp - * @param string[] $postStatus + * @param bool $returnAsModel + * @param int|null $minTimestamp + * @param string[] $postStatus * * @return array * @throws Exception @@ -125,12 +124,11 @@ public static function get( ]; } - $customId = md5( serialize( $types ) ); + $customId = md5( serialize( $types ) ); $cacheItem = Plugin::getCacheItem( $customId ); if ( $cacheItem ) { return $cacheItem; } else { - $posts = []; // Get Post-IDs considering types, items and locations @@ -150,14 +148,14 @@ public static function get( $posts = self::filterTimeframes( $posts, $date ); } - // if returnAsModel == TRUE the result is a timeframe model instead of a wordpress object + // if returnAsModel == TRUE the result is a timeframe model instead of a WordPress object if ( $returnAsModel ) { self::castPostsToModels( $posts ); } Plugin::setCacheItem( $posts, - Wordpress::getTags($posts, $items, $locations), + Wordpress::getTags( $posts, $items, $locations ), $customId ); return $posts; @@ -167,8 +165,8 @@ public static function get( /** * Will get all timeframes in the database to perform mass operations on (like migrations). * - * @param int $page - * @param int $perPage + * @param int $page + * @param int $perPage * @param array $customArgs * * @return \stdClass Properties: array posts, int totalPosts, int totalPages, bool done @@ -198,7 +196,7 @@ public static function getAllPaginated( 'posts' => $posts, 'totalPosts' => $query->found_posts, 'totalPages' => $query->max_num_pages, - 'done' => $page >= $query->max_num_pages + 'done' => $page >= $query->max_num_pages, ] ); } @@ -208,7 +206,7 @@ public static function getAllPaginated( 'posts' => [], 'totalPosts' => 0, 'totalPages' => 0, - 'done' => true + 'done' => true, ] ); } @@ -220,17 +218,17 @@ public static function getAllPaginated( * We need this for the Timeframe Export, so that it does not time out on large datasets. * This function is in general slower than the getInRange function. But it can be used in AJAX requests. * - * @param int $minTimestamp + * @param int $minTimestamp * @param int|null $maxTimestamp - * @param int $page - * @param int $perPage - * @param array $types - * @param bool $asModel - * @param array $customArgs + * @param int $page + * @param int $perPage + * @param array $types + * @param bool $asModel + * @param array $customArgs * * @return array An array with the keys 'posts', 'totalPages' and 'done' (bool) to indicate if there are more posts to fetch */ - public static function getInRangePaginated ( + public static function getInRangePaginated( int $minTimestamp, int $maxTimestamp = null, int $page = 1, @@ -249,16 +247,16 @@ public static function getInRangePaginated ( $args = array( 'post_type' => [ \CommonsBooking\Wordpress\CustomPostType\Booking::$postType, - \CommonsBooking\Wordpress\CustomPostType\Timeframe::$postType + \CommonsBooking\Wordpress\CustomPostType\Timeframe::$postType, ], - //get posts within the range and also posts that do not have a repetition end + // get posts within the range and also posts that do not have a repetition end 'meta_query' => array( 'relation' => 'AND', array( 'key' => \CommonsBooking\Model\Timeframe::REPETITION_START, 'value' => $maxTimestamp, 'compare' => '<=', - 'type' => 'numeric' + 'type' => 'numeric', ), array( 'relation' => 'OR', @@ -266,7 +264,7 @@ public static function getInRangePaginated ( 'key' => \CommonsBooking\Model\Timeframe::REPETITION_END, 'value' => $minTimestamp, 'compare' => '>=', - 'type' => 'numeric' + 'type' => 'numeric', ), array( 'key' => \CommonsBooking\Model\Timeframe::REPETITION_END, @@ -293,7 +291,7 @@ public static function getInRangePaginated ( if ( $query->have_posts() ) { $posts = $query->get_posts(); - if (! isset($args['fields']) || $args['fields'] !== 'ids') { + if ( ! isset( $args['fields'] ) || $args['fields'] !== 'ids' ) { $posts = array_filter( $posts, function ( $post ) use ( $args ) { @@ -309,14 +307,14 @@ function ( $post ) use ( $args ) { 'posts' => $posts, 'totalPages' => $query->max_num_pages, 'totalPosts' => $query->found_posts, - 'done' => $page >= $query->max_num_pages + 'done' => $page >= $query->max_num_pages, ]; } return [ 'posts' => [], 'totalPages' => 0, 'totalPosts' => 0, - 'done' => true + 'done' => true, ]; } @@ -328,8 +326,8 @@ function ( $post ) use ( $args ) { * @param array $types the types of timeframes to return, will return default set when not set * @param array $items the items that the timeframes should be applicable to, will return all if not set * @param array $locations the locations that the timeframes should be applicable to, will return all if not set - * - * @since 2.9.0 Supports now single and multi selection for items and locations + * + * @since 2.9.0 Supports now single and multi selection for items and locations * * @return mixed * @throws \Psr\Cache\InvalidArgumentException @@ -338,15 +336,15 @@ public static function getPostIdsByType( array $types = [], array $items = [], a if ( ! count( $types ) ) { $types = [ - \CommonsBooking\Wordpress\CustomPostType\Timeframe::HOLIDAYS_ID, - \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID, - \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_ID, - \CommonsBooking\Wordpress\CustomPostType\Timeframe::REPAIR_ID, - \CommonsBooking\Wordpress\CustomPostType\Timeframe::OFF_HOLIDAYS_ID, - ]; + \CommonsBooking\Wordpress\CustomPostType\Timeframe::HOLIDAYS_ID, + \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID, + \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_ID, + \CommonsBooking\Wordpress\CustomPostType\Timeframe::REPAIR_ID, + \CommonsBooking\Wordpress\CustomPostType\Timeframe::OFF_HOLIDAYS_ID, + ]; } - $customId = md5( serialize( $types ) ); + $customId = md5( serialize( $types ) ); $cacheItem = Plugin::getCacheItem( $customId ); if ( $cacheItem ) { return $cacheItem; @@ -357,15 +355,15 @@ public static function getPostIdsByType( array $types = [], array $items = [], a $items = array_filter( $items ); $locations = array_filter( $locations ); - // additional sanitizing. Allow only integer - $items = commonsbooking_sanitizeArrayorString( $items, 'intval' ); - $locations = commonsbooking_sanitizeArrayorString( $locations, 'intval' ); - $types = commonsbooking_sanitizeArrayorString( $types, 'intval' ); + // additional sanitizing. Allow only integer + $items = commonsbooking_sanitizeArrayorString( $items, 'intval' ); + $locations = commonsbooking_sanitizeArrayorString( $locations, 'intval' ); + $types = commonsbooking_sanitizeArrayorString( $types, 'intval' ); - $itemQuery = ""; + $itemQuery = ''; if ( count( $items ) > 0 ) { $itemQuery = self::getEntityQuery( - "pm2", + 'pm2', $table_postmeta, $items, \CommonsBooking\Model\Timeframe::META_ITEM_ID, @@ -373,10 +371,10 @@ public static function getPostIdsByType( array $types = [], array $items = [], a ); } - $locationQuery = ""; + $locationQuery = ''; if ( count( $locations ) > 0 ) { $locationQuery = self::getEntityQuery( - "pm3", + 'pm3', $table_postmeta, $locations, \CommonsBooking\Model\Timeframe::META_LOCATION_ID, @@ -388,13 +386,13 @@ public static function getPostIdsByType( array $types = [], array $items = [], a $query = " SELECT DISTINCT pm1.post_id from $table_postmeta pm1 " . - $itemQuery . - $locationQuery . - " + $itemQuery . + $locationQuery . + " WHERE pm1.meta_key = 'type' AND - pm1.meta_value IN (" . implode( ',', $types ) . ") - "; + pm1.meta_value IN (" . implode( ',', $types ) . ') + '; // Run query $postIds = $wpdb->get_results( $query, ARRAY_N ); @@ -405,13 +403,16 @@ public static function getPostIdsByType( array $types = [], array $items = [], a } // Get Posts - $posts = array_map(function($post) { - return get_post($post); - }, $postIds); + $posts = array_map( + function ( $post ) { + return get_post( $post ); + }, + $postIds + ); Plugin::setCacheItem( $postIds, - Wordpress::getTags($posts, $items, $locations), + Wordpress::getTags( $posts, $items, $locations ), $customId ); @@ -420,36 +421,36 @@ public static function getPostIdsByType( array $types = [], array $items = [], a } /** - * Returns entity query as join statement, which considers single and multi selection. - * - * @since 2.9.0 Supports now single and multi selection for items and locations - * - * @return string join statement - */ + * Returns entity query as join statement, which considers single and multi selection. + * + * @since 2.9.0 Supports now single and multi selection for items and locations + * + * @return string join statement + */ private static function getEntityQuery( string $joinAlias, string $table_postmeta, array $entities, string $singleEntityKey, string $multiEntityKey ): string { $locationQueryParts = []; // Single select - $singleLocationQuery = "( + $singleLocationQuery = "( $joinAlias.meta_key = '" . $singleEntityKey . "' AND - $joinAlias.meta_value IN (" . implode( ',', $entities ) . ") - )"; + $joinAlias.meta_value IN (" . implode( ',', $entities ) . ') + )'; $locationQueryParts[] = $singleLocationQuery; // Multi select $multiLocationQueries = []; - foreach( $entities as $entityId ) { + foreach ( $entities as $entityId ) { $multiLocationQueries[] = "$joinAlias.meta_value LIKE '%:\"$entityId\";%'"; } - $multiLocationQuery = "( + $multiLocationQuery = "( $joinAlias.meta_key = '" . $multiEntityKey . "' AND - (" . implode( ' OR ', $multiLocationQueries ) . ") - )"; + (" . implode( ' OR ', $multiLocationQueries ) . ') + )'; $locationQueryParts[] = $multiLocationQuery; return "INNER JOIN $table_postmeta $joinAlias ON $joinAlias.post_id = pm1.post_id AND - (" . implode( ' OR ', $locationQueryParts ) . ")"; + (" . implode( ' OR ', $locationQueryParts ) . ')'; } /** @@ -457,10 +458,10 @@ private static function getEntityQuery( string $joinAlias, string $table_postmet * Why? This kind of filtering is needed nearly everywhere in commonsbooking. * * @param string|null $date - * @param int|null $minTimestamp - * @param int|null $maxTimestamp - * @param array $postIds - * @param array $postStatus + * @param int|null $minTimestamp + * @param int|null $maxTimestamp + * @param array $postIds + * @param array $postStatus * * @return array */ @@ -472,7 +473,7 @@ private static function getPostsByBaseParams( ?string $date, ?int $minTimestamp, global $wpdb; $table_postmeta = $wpdb->prefix . 'postmeta'; $table_posts = $wpdb->prefix . 'posts'; - $dateQuery = ""; + $dateQuery = ''; // Filter by date if ( $date && ! $minTimestamp ) { @@ -492,9 +493,9 @@ private static function getPostsByBaseParams( ?string $date, ?int $minTimestamp, // Complete query $query = "SELECT DISTINCT pm1.* from $table_posts pm1 - " . $dateQuery . " + " . $dateQuery . ' WHERE - pm1.id in (" . implode( ",", $postIds ) . ") AND + pm1.id in (' . implode( ',', $postIds ) . ") AND pm1.post_type IN ('" . implode( "','", \CommonsBooking\Wordpress\CustomPostType\Timeframe::getSimilarPostTypes() ) . "') AND pm1.post_status IN ('" . implode( "','", $postStatus ) . "') "; @@ -504,7 +505,7 @@ private static function getPostsByBaseParams( ?string $date, ?int $minTimestamp, Plugin::setCacheItem( $posts, - Wordpress::getTags($posts, $postIds) + Wordpress::getTags( $posts, $postIds ) ); return $posts; @@ -554,13 +555,13 @@ private static function getFilterByDateQuery( string $table_postmeta, string $da * Returns query to get posts which end after $minTimestamp. * * @param string $table_postmeta - * @param int $minTimestamp + * @param int $minTimestamp * * @return string */ private static function getFilterFromDateQuery( string $table_postmeta, int $minTimestamp ): string { global $wpdb; - $minTimestamp = Helper::getLastFullDayTimestamp($minTimestamp); + $minTimestamp = Helper::getLastFullDayTimestamp( $minTimestamp ); return $wpdb->prepare( "INNER JOIN $table_postmeta pm4 ON @@ -584,8 +585,8 @@ private static function getFilterFromDateQuery( string $table_postmeta, int $min /** * @param string $table_postmeta - * @param int $minTimestamp - * @param int $maxTimestamp + * @param int $minTimestamp + * @param int $maxTimestamp * * @return string */ @@ -623,7 +624,7 @@ private static function getTimerangeQuery( string $table_postmeta, int $minTimes /** * Wrapper function for all filters. * - * @param array $posts + * @param array $posts * @param string|null $date * * @return array @@ -641,7 +642,7 @@ private static function filterTimeframes( array $posts, ?string $date ): array { * Why? Because you can define days for your timeframe. Here's the point where we make sure, that only these days * are taken into account. * - * @param array $posts + * @param array $posts * @param string|null $date string format: YYYY-mm-dd * * @return array @@ -653,18 +654,20 @@ private static function filterTimeframesByConfiguredDays( array $posts, ?string return $cacheItem; } else { if ( $date ) { - $posts = array_filter( $posts, function ( $post ) use ( $date ) { - try { - $timeframe = new \CommonsBooking\Model\Timeframe( $post ); - $day = new Day( $date ); - - return $day->isInTimeframe( $timeframe ); - } catch ( Exception $e ) { - //this was also default behaviour before #802 (before #802 the function would just check the weekly repetition and if it was active on the given day return true) - //When none were set, it would return true for all days. - return true; + $posts = array_filter( + $posts, + function ( $post ) use ( $date ) { + try { + $timeframe = new \CommonsBooking\Model\Timeframe( $post ); + $day = new Day( $date ); + + return $day->isInTimeframe( $timeframe ); + } catch ( Exception $e ) { + // this was also default behaviour before #802 (before #802 the function would just check the weekly repetition and if it was active on the given day return true) + // When none were set, it would return true for all days. + return true; + } } - } ); } @@ -683,21 +686,24 @@ private static function filterTimeframesByConfiguredDays( array $posts, ?string * @return array */ private static function filterTimeframesByMaxBookingDays( $posts ): array { - return array_filter( $posts, function ( $post ) { - if ( $post->post_type == \CommonsBooking\Wordpress\CustomPostType\Timeframe::getPostType() ) { - try { - $timeframe = new \CommonsBooking\Model\Timeframe( $post ); + return array_filter( + $posts, + function ( $post ) { + if ( $post->post_type == \CommonsBooking\Wordpress\CustomPostType\Timeframe::getPostType() ) { + try { + $timeframe = new \CommonsBooking\Model\Timeframe( $post ); - return $timeframe->isBookable(); - } catch ( Exception $e ) { - error_log( $e->getMessage() ); + return $timeframe->isBookable(); + } catch ( Exception $e ) { + error_log( $e->getMessage() ); - return false; + return false; + } } - } - return true; - } ); + return true; + } + ); } /** @@ -709,44 +715,50 @@ private static function filterTimeframesByMaxBookingDays( $posts ): array { * @return array */ private static function filterTimeframesForCurrentUser( $posts ): array { - return array_filter( $posts, function ( $post ) { - try { - return commonsbooking_isCurrentUserAllowedToBook( $post->ID ); - } catch ( Exception $e ) { - error_log( $e->getMessage() ); + return array_filter( + $posts, + function ( $post ) { + try { + return commonsbooking_isCurrentUserAllowedToBook( $post->ID ); + } catch ( Exception $e ) { + error_log( $e->getMessage() ); - return false; + return false; + } } - } ); + ); } /** * Will filter out all timeframes that are not in the given timerange. * * @param \CommonsBooking\Model\Timeframe[] $timeframes - * @param int $startTimestamp - * @param int $endTimestamp + * @param int $startTimestamp + * @param int $endTimestamp * * @return \CommonsBooking\Model\Timeframe[] * @throws Exception */ public static function filterTimeframesForTimerange( array $timeframes, int $startTimestamp, int $endTimestamp ): array { - return array_filter( $timeframes, function ( $timeframe ) use ( $startTimestamp, $endTimestamp ) { - //filter out anything in the future - if ( $timeframe->getStartDate() > $endTimestamp ) { - return false; - } - //always include infinite timeframes - if ( ! $timeframe->getEndDate() ) { + return array_filter( + $timeframes, + function ( $timeframe ) use ( $startTimestamp, $endTimestamp ) { + // filter out anything in the future + if ( $timeframe->getStartDate() > $endTimestamp ) { + return false; + } + // always include infinite timeframes + if ( ! $timeframe->getEndDate() ) { + return true; + } + // filter out anything in the past + if ( $timeframe->getEndDate() < $startTimestamp ) { + return false; + } + return true; } - //filter out anything in the past - if ( $timeframe->getEndDate() < $startTimestamp ) { - return false; - } - - return true; - } ); + ); } /** @@ -788,7 +800,7 @@ public static function getByLocationItemTimestamp( int $locationId, int $itemId, if ( $cacheItem ) { return $cacheItem; } else { - $time_format = esc_html(get_option( 'time_format' )); + $time_format = esc_html( get_option( 'time_format' ) ); $startTimestampTime = date( $time_format, $timestamp ); $endTimestampTime = date( $time_format, $timestamp + 1 ); @@ -796,7 +808,7 @@ public static function getByLocationItemTimestamp( int $locationId, int $itemId, [ $locationId ], [ $itemId ], [ \CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID ], - date('Y-m-d', $timestamp), + date( 'Y-m-d', $timestamp ), true ); @@ -806,7 +818,7 @@ public static function getByLocationItemTimestamp( int $locationId, int $itemId, date( $time_format, strtotime( $timeframe->getStartTime() ) ) == $startTimestampTime || date( $time_format, strtotime( $timeframe->getEndTime() ) ) == $endTimestampTime ) { - Plugin::setCacheItem( $timeframe, [$timeframe->ID, $itemId, $locationId] ); + Plugin::setCacheItem( $timeframe, [ $timeframe->ID, $itemId, $locationId ] ); return $timeframe; } @@ -823,11 +835,11 @@ public static function getByLocationItemTimestamp( int $locationId, int $itemId, * * @param $minTimestamp * @param $maxTimestamp - * @param array $locations - * @param array $items - * @param array $types - * @param false $returnAsModel - * @param string[] $postStatus + * @param array $locations + * @param array $items + * @param array $types + * @param false $returnAsModel + * @param string[] $postStatus * * @return array * @throws Exception @@ -851,7 +863,7 @@ public static function getInRange( ]; } - $customId = md5( serialize( $types ) ); + $customId = md5( serialize( $types ) ); $cacheItem = Plugin::getCacheItem( $customId ); if ( $cacheItem ) { return $cacheItem; @@ -880,7 +892,7 @@ public static function getInRange( Plugin::setCacheItem( $posts, - Wordpress::getTags($posts, $locations, $items), + Wordpress::getTags( $posts, $locations, $items ), $customId ); @@ -893,17 +905,16 @@ public static function getInRange( * * @param $minTimestamp * @param $maxTimestamp - * @param array $locations - * @param array $items - * @param array $types - * @param false $returnAsModel - * @param string[] $postStatus + * @param array $locations + * @param array $items + * @param array $types + * @param false $returnAsModel + * @param string[] $postStatus * * @return array * @throws Exception */ - - public static function getInRangeForCurrentUser( + public static function getInRangeForCurrentUser( $minTimestamp, $maxTimestamp, array $locations = [], @@ -912,9 +923,9 @@ public static function getInRangeForCurrentUser( bool $returnAsModel = false, array $postStatus = [ 'confirmed', 'unconfirmed', 'publish', 'inherit' ] ): array { - $bookableTimeframes = self::getInRange($minTimestamp,$maxTimestamp,$locations,$items,$types,$returnAsModel,$postStatus); + $bookableTimeframes = self::getInRange( $minTimestamp, $maxTimestamp, $locations, $items, $types, $returnAsModel, $postStatus ); - $bookableTimeframes = self::filterTimeframesForCurrentUser($bookableTimeframes); + $bookableTimeframes = self::filterTimeframesForCurrentUser( $bookableTimeframes ); return $bookableTimeframes; } } diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index a2e3df960..539d5035a 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Repository; - use CommonsBooking\Plugin; use WP_Query; @@ -11,26 +10,29 @@ class UserRepository { /** * Returns all users with role that can be assigned to item / location. + * * @return mixed */ public static function getSelectableCBManagers() { - return get_users( ['role__in' => self::getManagerRoles()] ); + return get_users( [ 'role__in' => self::getManagerRoles() ] ); } - public static function getManagerRoles() : array { - return apply_filters("commonsbooking_manager_roles",[Plugin::$CB_MANAGER_ID]); + public static function getManagerRoles(): array { + return apply_filters( 'commonsbooking_manager_roles', [ Plugin::$CB_MANAGER_ID ] ); } /** * Will get all roles that are considered by CommonsBooking as "Administrator" roles + * * @return array */ - public static function getAdminRoles() : array { - return apply_filters('commonsbooking_admin_roles', ['administrator']); + public static function getAdminRoles(): array { + return apply_filters( 'commonsbooking_admin_roles', [ 'administrator' ] ); } /** * Returns all users with items/locations. + * * @return array */ public static function getOwners(): array { @@ -40,7 +42,7 @@ public static function getOwners(): array { 'post_type' => array( \CommonsBooking\Wordpress\CustomPostType\Item::$postType, \CommonsBooking\Wordpress\CustomPostType\Location::$postType, - ) + ), ); $query = new WP_Query( $args ); if ( $query->have_posts() ) { @@ -70,13 +72,13 @@ public static function getOwners(): array { */ public static function getUserRoles(): array { global $wp_roles; - if ( $wp_roles === null ){ + if ( $wp_roles === null ) { return []; } $rolesArray = $wp_roles->roles; $roles = []; foreach ( $rolesArray as $roleID => $value ) { - if ($roleID == 'administrator') { + if ( $roleID == 'administrator' ) { continue; } $roles[ $roleID ] = translate_user_role( $value['name'] ); @@ -91,11 +93,11 @@ public static function getUserRoles(): array { * * @since 2.9.0 * - * @param int $userID + * @param int $userID * @param string|array $roles * @return bool */ - public static function userHasRoles(int $userID, $roles): bool { + public static function userHasRoles( int $userID, $roles ): bool { $user = get_userdata( $userID ); if ( is_array( $roles ) ) { return ! empty( array_intersect( $roles, $user->roles ) ); @@ -103,5 +105,4 @@ public static function userHasRoles(int $userID, $roles): bool { return in_array( $roles, $user->roles ); } } - } diff --git a/src/Service/Booking.php b/src/Service/Booking.php index bcdff1f7a..40c64c31b 100644 --- a/src/Service/Booking.php +++ b/src/Service/Booking.php @@ -14,6 +14,7 @@ class Booking { /** * Removes all unconfirmed bookings older than 10 minutes * is triggered in Service\Scheduler initHooks() + * * @return void */ public static function cleanupBookings() { @@ -39,7 +40,7 @@ public static function cleanupBookings() { } } - private static function sendMessagesForDay ( int $tsDate, bool $onStartDate, Message $message ) { + private static function sendMessagesForDay( int $tsDate, bool $onStartDate, Message $message ) { if ( $onStartDate ) { $bookings = \CommonsBooking\Repository\Booking::getBeginningBookingsByDate( $tsDate ); } else { @@ -58,30 +59,32 @@ private static function sendMessagesForDay ( int $tsDate, bool $onStartDate, Mes /** * Send reminder mail, x days before start of booking. - * is triggered in Service\Scheduler initHooks() + * is triggered in Service\Scheduler initHooks() + * * @throws \Exception */ public static function sendReminderMessage() { - if (Settings::getOption('commonsbooking_options_reminder', 'pre-booking-reminder-activate') != 'on') { - return; - } + if ( Settings::getOption( 'commonsbooking_options_reminder', 'pre-booking-reminder-activate' ) != 'on' ) { + return; + } - $message = new BookingReminderMessage( 0, 'pre-booking-reminder' ); + $message = new BookingReminderMessage( 0, 'pre-booking-reminder' ); $daysBeforeStart = Settings::getOption( 'commonsbooking_options_reminder', 'pre-booking-days-before' ); self::sendMessagesForDay( strtotime( '+' . $daysBeforeStart . ' days midnight' ), true, $message ); } /** * Send feedback mal on same day or the day after end of booking. - * is triggered in Service\Scheduler initHooks() + * is triggered in Service\Scheduler initHooks() + * * @throws \Exception */ public static function sendFeedbackMessage() { - if (Settings::getOption('commonsbooking_options_reminder', 'post-booking-notice-activate') != 'on') { - return; - } + if ( Settings::getOption( 'commonsbooking_options_reminder', 'post-booking-notice-activate' ) != 'on' ) { + return; + } // Yesterday at 23:59 $endDate = strtotime( 'midnight', time() ) - 1; @@ -90,24 +93,24 @@ public static function sendFeedbackMessage() { } public static function sendBookingStartLocationReminderMessage() { - self::sendLocationBookingReminderMessage('start'); + self::sendLocationBookingReminderMessage( 'start' ); } public static function sendBookingEndLocationReminderMessage() { - self::sendLocationBookingReminderMessage('end'); + self::sendLocationBookingReminderMessage( 'end' ); } - protected static function sendLocationBookingReminderMessage(string $type) { + protected static function sendLocationBookingReminderMessage( string $type ) { - if (Settings::getOption('commonsbooking_options_reminder', 'booking-'.$type.'-location-reminder-activate') != 'on') { + if ( Settings::getOption( 'commonsbooking_options_reminder', 'booking-' . $type . '-location-reminder-activate' ) != 'on' ) { return; } // current day is saved in options as 1, this is because 0 is an unset value. Subtract 1 to get the correct day - $daysBeforeStart = (int) Settings::getOption( 'commonsbooking_options_reminder', 'booking-'.$type.'-location-reminder-day' ) - 1; - $startDate = strtotime( '+' . $daysBeforeStart . ' days midnight' ); + $daysBeforeStart = (int) Settings::getOption( 'commonsbooking_options_reminder', 'booking-' . $type . '-location-reminder-day' ) - 1; + $startDate = strtotime( '+' . $daysBeforeStart . ' days midnight' ); - $message = new LocationBookingReminderMessage( 0, 'booking-'.$type.'-location-reminder' ); + $message = new LocationBookingReminderMessage( 0, 'booking-' . $type . '-location-reminder' ); self::sendMessagesForDay( $startDate, $type === 'start', $message ); } -} \ No newline at end of file +} diff --git a/src/Service/BookingCodes.php b/src/Service/BookingCodes.php index 2726e5b57..66f3a8aa5 100644 --- a/src/Service/BookingCodes.php +++ b/src/Service/BookingCodes.php @@ -13,42 +13,43 @@ class BookingCodes { /** * Send booking codes by E-mail. - * is triggered in Service\Scheduler initHooks() - * + * is triggered in Service\Scheduler initHooks() */ public static function sendBookingCodesMessage(): void { - $query = new WP_Query( [ - 'post_type' => Timeframe::$postType, - 'meta_query' => array( + $query = new WP_Query( + [ + 'post_type' => Timeframe::$postType, + 'meta_query' => array( array( 'key' => \CommonsBooking\View\BookingCodes::NEXT_CRON_EMAIL, - 'value' => strtotime("today"), + 'value' => strtotime( 'today' ), 'type' => 'numeric', - 'compare' => '<=' + 'compare' => '<=', ), ), - ] ); + ] + ); - if($query->have_posts()){ - foreach( $query->posts as $post ) { - $params=self::getCronParams($post->ID); - if($params === false) continue; + if ( $query->have_posts() ) { + foreach ( $query->posts as $post ) { + $params = self::getCronParams( $post->ID ); + if ( $params === false ) { + continue; + } - $booking_msg = new BookingCodesMessage($post->ID, "codes",$params['from'],$params['to'] ); - if(!$booking_msg->sendMessage()) { + $booking_msg = new BookingCodesMessage( $post->ID, 'codes', $params['from'], $params['to'] ); + if ( ! $booking_msg->sendMessage() ) { set_transient( BookingCode::ERROR_TYPE, commonsbooking_sanitizeHTML( - __( "Error sending booking codes by E-mail for Timeframe ", 'commonsbooking' ) . get_the_title($post) . " ({$post->ID})" + __( 'Error sending booking codes by E-mail for Timeframe ', 'commonsbooking' ) . get_the_title( $post ) . " ({$post->ID})" ), 0 ); + } else { + update_post_meta( $post->ID, \CommonsBooking\View\BookingCodes::NEXT_CRON_EMAIL, $params['nextCronEventTs'] ); } - else { - update_post_meta( $post->ID, \CommonsBooking\View\BookingCodes::NEXT_CRON_EMAIL, $params['nextCronEventTs'] ); - } - - } + } } } @@ -56,35 +57,36 @@ public static function sendBookingCodesMessage(): void { * Retrieves Parameters of the next booking codes by Email Cron event. * * @param int $timeframeId - * - * @return array Parameters. + * + * @return array Parameters. */ - public static function getCronParams($timeframeId): array { - $tsCurrentCronEvent=get_post_meta( $timeframeId, \CommonsBooking\View\BookingCodes::NEXT_CRON_EMAIL, true ); - if(empty($tsCurrentCronEvent)) return false; - - $cronEmailCodes=get_post_meta( $timeframeId, \CommonsBooking\View\BookingCodes::CRON_EMAIL_CODES, true); - if(!is_numeric($cronEmailCodes['cron-email-booking-code-nummonth']) || empty(@$cronEmailCodes['cron-booking-codes-enabled'])) - return false; - - $dtCurrentCronEvent=new DateTimeImmutable("@" . $tsCurrentCronEvent); - $dtFrom=$dtCurrentCronEvent->modify("midnight first day of next month"); - $dtTo=$dtCurrentCronEvent->modify("midnight last day of next month +" . ($cronEmailCodes['cron-email-booking-code-nummonth'] - 1) . " month"); + public static function getCronParams( $timeframeId ): array { + $tsCurrentCronEvent = get_post_meta( $timeframeId, \CommonsBooking\View\BookingCodes::NEXT_CRON_EMAIL, true ); + if ( empty( $tsCurrentCronEvent ) ) { + return false; + } - $dtInitial=new DateTimeImmutable("@" . $cronEmailCodes['cron-email-booking-code-start']); - $daydiff=$dtTo->format("j") - $dtInitial->format("j"); - if($daydiff > 0 ) { - $dtNextCronEvent=$dtTo->modify("-" . $daydiff . " days"); - } - else - $dtNextCronEvent=$dtTo; + $cronEmailCodes = get_post_meta( $timeframeId, \CommonsBooking\View\BookingCodes::CRON_EMAIL_CODES, true ); + if ( ! is_numeric( $cronEmailCodes['cron-email-booking-code-nummonth'] ) || empty( @$cronEmailCodes['cron-booking-codes-enabled'] ) ) { + return false; + } - return array( - "from" => $dtFrom->getTimestamp(), - "to" => $dtTo->getTimestamp(), - "nextCronEventTs" => $dtNextCronEvent->getTimestamp(), - ); - } + $dtCurrentCronEvent = new DateTimeImmutable( '@' . $tsCurrentCronEvent ); + $dtFrom = $dtCurrentCronEvent->modify( 'midnight first day of next month' ); + $dtTo = $dtCurrentCronEvent->modify( 'midnight last day of next month +' . ( $cronEmailCodes['cron-email-booking-code-nummonth'] - 1 ) . ' month' ); + $dtInitial = new DateTimeImmutable( '@' . $cronEmailCodes['cron-email-booking-code-start'] ); + $daydiff = $dtTo->format( 'j' ) - $dtInitial->format( 'j' ); + if ( $daydiff > 0 ) { + $dtNextCronEvent = $dtTo->modify( '-' . $daydiff . ' days' ); + } else { + $dtNextCronEvent = $dtTo; + } -} \ No newline at end of file + return array( + 'from' => $dtFrom->getTimestamp(), + 'to' => $dtTo->getTimestamp(), + 'nextCronEventTs' => $dtNextCronEvent->getTimestamp(), + ); + } +} diff --git a/src/Service/BookingRule.php b/src/Service/BookingRule.php index 7ff167443..e29bd71dd 100644 --- a/src/Service/BookingRule.php +++ b/src/Service/BookingRule.php @@ -24,43 +24,51 @@ class BookingRule { /** * The name of the rule, needs to be unique and is used to identify the rule in the code + * * @var String */ protected string $name; /** * The title of the rule, will be shown to the configuration admin + * * @var String */ protected string $title; /** * A detailed description of the rule, will be shown to the configuration admin + * * @var String */ protected string $description; /** * The static error message that will be shown to the booking user if the rule is not met + * * @var String */ protected string $errorMessage; /** * Allows to set a custom error message that can be based on parameters (i.e. "You can only book for %s days") + * * @var ?Closure */ protected ?Closure $errorFromArgs; /** * Array of associative arrays in which the key "title" is the title of the parameter and "description" is the description of the parameter. * These parameters are text fields that can be used to configure the rule. We can currently only support 2 parameters + * * @var array */ protected array $params = []; /** * Array where first element is the description of the select field and the second element is an associative array of the select options + * * @var array */ protected array $selectParam; /** * The function that will be called to validate the rule. This is a closure that takes a Booking object, the passed args and an array of the selected terms as arguments * and returns either null if the rule is met or an array of bookings that are in conflict with the current booking. + * * @var Closure */ protected Closure $validationFunction; @@ -68,21 +76,20 @@ class BookingRule { /** * The constructor for BookingRules before they are applied * - * @param String $name The name of the rule, needs to be unique and is used to identify the rule in the code - * @param String $title The title of the rule, will be shown to the configuration admin - * @param String $description A detailed description of the rule, will be shown to the configuration admin - * @param String $errorMessage The static error message that will be shown to the booking user if the rule is not met + * @param String $name The name of the rule, needs to be unique and is used to identify the rule in the code + * @param String $title The title of the rule, will be shown to the configuration admin + * @param String $description A detailed description of the rule, will be shown to the configuration admin + * @param String $errorMessage The static error message that will be shown to the booking user if the rule is not met * @param Closure $validationFunction The function that will be called to validate the rule. This is a closure that takes a Booking object, the passed args and an array of the selected terms as arguments - * @param array $params Array of associative arrays in which the key "title" is the title of the parameter and "description" is the description of the parameter. Only 2 parameters are currently supported. They have to be integer values. - * @param array $selectParam Array where first element is the description of the select field and the second element is an associative array of the select options + * @param array $params Array of associative arrays in which the key "title" is the title of the parameter and "description" is the description of the parameter. Only 2 parameters are currently supported. They have to be integer values. + * @param array $selectParam Array where first element is the description of the select field and the second element is an associative array of the select options * * @throws BookingRuleException */ public function __construct( string $name, string $title, string $description, string $errorMessage, Closure $validationFunction, array $params = [], array $selectParam = [], ?Closure $errorFromArgs = null ) { if ( ! empty( $params ) ) { - if ( count( $params ) > 2 ) { - throw new BookingRuleException( "No more than 2 parameters are currently supported" ); + throw new BookingRuleException( 'No more than 2 parameters are currently supported' ); } $this->params = $params; @@ -98,6 +105,7 @@ public function __construct( string $name, string $title, string $description, s /** * Gets the sanitized version of the BookingRule title + * * @return string */ public function getTitle(): string { @@ -106,6 +114,7 @@ public function getTitle(): string { /** * Gets the sanitized version of the BookingRule description + * * @return string */ public function getDescription(): string { @@ -114,14 +123,15 @@ public function getDescription(): string { /** * Gets the sanitized version of the BookingRule error message + * * @return string */ public function getErrorMessage( $args = [] ): string { $errorMessage = commonsbooking_sanitizeHTML( $this->errorMessage ); if ( $this->errorFromArgs !== null ) { $errorMessageFunction = $this->errorFromArgs; - $errorMessage .= PHP_EOL; - $errorMessage .= $errorMessageFunction( $args ); + $errorMessage .= PHP_EOL; + $errorMessage .= $errorMessageFunction( $args ); } return $errorMessage; @@ -150,6 +160,7 @@ public function getValidationFunction(): Closure { /** * Create associative array for CMB2 select + * * @return array */ public static function getRulesForSelect(): array { @@ -188,10 +199,12 @@ public static function getRulesJSON(): string { array_map( function ( $rule ) { return get_object_vars( $rule ); - }, $ruleObjects ) + }, + $ruleObjects + ) ); } else { - return ""; + return ''; } } @@ -199,119 +212,120 @@ function ( $rule ) { * Returns an array with the default ruleset applied, can be filtered using a filter hook * * Closure::fromCallable can be replaced with First Class Callable Syntax in PHP8.1 + * * @return BookingRule[] * @throws BookingRuleException */ public static function init(): array { - $weekDays = __( 'Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday', 'cmb2' ); - $weekDaysSelect = array_combine( range( 1, 7 ), explode( ', ', $weekDays ) ); + $weekDays = __( 'Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday', 'cmb2' ); + $weekDaysSelect = array_combine( range( 1, 7 ), explode( ', ', $weekDays ) ); $monthDaysSelect = array_combine( range( 1, 31 ), range( 1, 31 ) ); - $defaultRuleSet = [ + $defaultRuleSet = [ new BookingRule( - "noSimultaneousBooking", - __( "Forbid simultaneous Bookings", 'commonsbooking' ), - __( "Users can no longer book two items on the same day.", 'commonsbooking' ), - __( "You can not book more than one item at a time.", 'commonsbooking' ), + 'noSimultaneousBooking', + __( 'Forbid simultaneous Bookings', 'commonsbooking' ), + __( 'Users can no longer book two items on the same day.', 'commonsbooking' ), + __( 'You can not book more than one item at a time.', 'commonsbooking' ), Closure::fromCallable( array( self::class, 'checkSimultaneousBookings' ) ) ), new BookingRule( - "prohibitChainBooking", - __( "Prohibit chain-bookings", 'commonsbooking' ), - __( "Users can no longer work around the maximum booking limit by chaining two bookings directly after one another.", 'commonsbooking' ), - __( "You have reached your booking limit. Please leave some time in between bookings.", 'commonsbooking' ), + 'prohibitChainBooking', + __( 'Prohibit chain-bookings', 'commonsbooking' ), + __( 'Users can no longer work around the maximum booking limit by chaining two bookings directly after one another.', 'commonsbooking' ), + __( 'You have reached your booking limit. Please leave some time in between bookings.', 'commonsbooking' ), Closure::fromCallable( array( self::class, 'checkChainBooking' ) ) ), new BookingRule( - "maxBookingDaysPerWeek", - __( "Maximum booked days per week", 'commonsbooking' ), - __( "Users are only allowed to book a limited amount of days per week.", 'commonsbooking' ), - __( "You have reached your booking limit. Please leave some time in between bookings.", 'commonsbooking' ), + 'maxBookingDaysPerWeek', + __( 'Maximum booked days per week', 'commonsbooking' ), + __( 'Users are only allowed to book a limited amount of days per week.', 'commonsbooking' ), + __( 'You have reached your booking limit. Please leave some time in between bookings.', 'commonsbooking' ), Closure::fromCallable( array( self::class, 'checkMaxBookingDaysPerWeek' ) ), array( array( - "title" => __( "Maximum booked days per week", 'commonsbooking' ), - "description" => __( "Number of days each user is allowed to book per week", 'commonsbooking' ), - ) + 'title' => __( 'Maximum booked days per week', 'commonsbooking' ), + 'description' => __( 'Number of days each user is allowed to book per week', 'commonsbooking' ), + ), ), array( - __( "At what day of the week should the counter be reset?", 'commonsbooking' ), - $weekDaysSelect + __( 'At what day of the week should the counter be reset?', 'commonsbooking' ), + $weekDaysSelect, ), Closure::fromCallable( array( self::class, 'maxDaysWeekErrorMessage' ) ) ), new BookingRule( - "maxBookingDaysPerMonth", - __( "Maximum booked days per month", 'commonsbooking' ), - __( "Users are only allowed to book a limited amount of days per month.", 'commonsbooking' ), - __( "You have reached your booking limit. Please leave some time in between bookings.", 'commonsbooking' ), + 'maxBookingDaysPerMonth', + __( 'Maximum booked days per month', 'commonsbooking' ), + __( 'Users are only allowed to book a limited amount of days per month.', 'commonsbooking' ), + __( 'You have reached your booking limit. Please leave some time in between bookings.', 'commonsbooking' ), Closure::fromCallable( array( self::class, 'checkMaxBookingDaysPerMonth' ) ), array( array( - "title" => __( "Maximum booked days per month", 'commonsbooking' ), - "description" => __( "Number of days each user is allowed to book per month", 'commonsbooking' ), - ) + 'title' => __( 'Maximum booked days per month', 'commonsbooking' ), + 'description' => __( 'Number of days each user is allowed to book per month', 'commonsbooking' ), + ), ), array( - __( "At what day of the month should the counter be reset?", 'commonsbooking' ), - $monthDaysSelect + __( 'At what day of the month should the counter be reset?', 'commonsbooking' ), + $monthDaysSelect, ), Closure::fromCallable( array( self::class, 'maxDaysMonthErrorMessage' ) ) ), new BookingRule( - "maxBookingDays", - __( "Maximum of bookable days in time period", 'commonsbooking' ), - __( "Allow x booked days over the period of y days for user.", 'commonsbooking' ), - __( "Booking limit exceeded. ", 'commonsbooking' ), + 'maxBookingDays', + __( 'Maximum of bookable days in time period', 'commonsbooking' ), + __( 'Allow x booked days over the period of y days for user.', 'commonsbooking' ), + __( 'Booking limit exceeded. ', 'commonsbooking' ), Closure::fromCallable( array( self::class, 'checkMaxBookingDays' ) ), array( array( - "title" => __( "Allow x booked days", 'commonsbooking' ), - "description" => __( "How many days are free to book in the given period of days", 'commonsbooking' ), + 'title' => __( 'Allow x booked days', 'commonsbooking' ), + 'description' => __( 'How many days are free to book in the given period of days', 'commonsbooking' ), ), array( - "title" => __( "In the period of y days", 'commonsbooking' ), - "description" => __( "The length of the period for which the booking is limited. This period always lies in the middle, so if you define 30 days, the 15 days before and after will count towards the maximum quota.", 'commonsbooking' ), - ) + 'title' => __( 'In the period of y days', 'commonsbooking' ), + 'description' => __( 'The length of the period for which the booking is limited. This period always lies in the middle, so if you define 30 days, the 15 days before and after will count towards the maximum quota.', 'commonsbooking' ), + ), ), [], Closure::fromCallable( array( self::class, 'maxBookingDaysErrorMessage' ) ) ), new BookingRule( - "maxBookingsWeek", - __( "Maximum number of bookings per week", 'commonsbooking' ), - __( "Users are only allowed to make that many bookings per week (Irrespective of their length).", 'commonsbooking' ), - __( "You have reached your booking limit. Please leave some time in between bookings.", 'commonsbooking' ), + 'maxBookingsWeek', + __( 'Maximum number of bookings per week', 'commonsbooking' ), + __( 'Users are only allowed to make that many bookings per week (Irrespective of their length).', 'commonsbooking' ), + __( 'You have reached your booking limit. Please leave some time in between bookings.', 'commonsbooking' ), Closure::fromCallable( array( self::class, 'checkMaxBookingsWeek' ) ), array( array( - "title" => __( "Maximum number of bookings per week", 'commonsbooking' ), - "description" => __( "Number of bookings each user is allowed to make per week", 'commonsbooking' ), - ) + 'title' => __( 'Maximum number of bookings per week', 'commonsbooking' ), + 'description' => __( 'Number of bookings each user is allowed to make per week', 'commonsbooking' ), + ), ), array( - __( "At what day of the week should the counter be reset?", 'commonsbooking' ), - $weekDaysSelect + __( 'At what day of the week should the counter be reset?', 'commonsbooking' ), + $weekDaysSelect, ), Closure::fromCallable( array( self::class, 'maxBookingsWeekErrorMessage' ) ) ), new BookingRule( - "maxBookingsMonth", - __( "Maximum number of bookings per month", 'commonsbooking' ), - __( "Users are only allowed to make that many bookings per month (Irrespective of their length).", 'commonsbooking' ), - __( "You have reached your booking limit. Please leave some time in between bookings.", 'commonsbooking' ), + 'maxBookingsMonth', + __( 'Maximum number of bookings per month', 'commonsbooking' ), + __( 'Users are only allowed to make that many bookings per month (Irrespective of their length).', 'commonsbooking' ), + __( 'You have reached your booking limit. Please leave some time in between bookings.', 'commonsbooking' ), Closure::fromCallable( array( self::class, 'checkMaxBookingsMonth' ) ), array( array( - "title" => __( "Maximum number of bookings per month", 'commonsbooking' ), - "description" => __( "Number of bookings each user is allowed to make per month", 'commonsbooking' ), - ) + 'title' => __( 'Maximum number of bookings per month', 'commonsbooking' ), + 'description' => __( 'Number of bookings each user is allowed to make per month', 'commonsbooking' ), + ), ), array( - __( "At what day of the month should the counter be reset?", 'commonsbooking' ), - $monthDaysSelect + __( 'At what day of the month should the counter be reset?', 'commonsbooking' ), + $monthDaysSelect, ), Closure::fromCallable( array( self::class, 'maxBookingsMonthErrorMessage' ) ) - ) + ), ]; return apply_filters( COMMONSBOOKING_PLUGIN_SLUG . '_booking-rules', $defaultRuleSet ); @@ -322,9 +336,8 @@ public static function init(): array { * If the user has bookings at the same day it will return an array with conflicting bookings * If there is no booking at the same day, will return null * - * - * @param Booking $booking - * @param array $args + * @param Booking $booking + * @param array $args * @param bool|array $appliedTerms * * @return array|null @@ -337,9 +350,12 @@ public static function checkSimultaneousBookings( Booking $booking, array $args return null; } - return array_filter( $userBookings, function ( $userBooking ) use ( $booking ) { - return $userBooking->hasTimeframeDateOverlap( $booking ); - } ); + return array_filter( + $userBookings, + function ( $userBooking ) use ( $booking ) { + return $userBooking->hasTimeframeDateOverlap( $booking ); + } + ); } /** @@ -347,8 +363,8 @@ public static function checkSimultaneousBookings( Booking $booking, array $args * If the user has chained too many days in that timespan will return the conflicting bookings * If the user bookings are NOT above the limit, will return null * - * @param Booking $booking - * @param array $args + * @param Booking $booking + * @param array $args * @param bool|array $appliedTerms * * @return array|null @@ -373,23 +389,29 @@ public static function checkChainBooking( Booking $booking, array $args = [], $a return null; } $bookingCollection = $booking->getBookingChain( $bookingUser ); - //add our current booking to the collection + // add our current booking to the collection $bookingCollection[] = $booking; - uasort( $bookingCollection, function ( Booking $a, Booking $b ) { - return $a->getStartDate() <=> $b->getStartDate(); - } ); + uasort( + $bookingCollection, + function ( Booking $a, Booking $b ) { + return $a->getStartDate() <=> $b->getStartDate(); + } + ); $collectionStartDate = reset( $bookingCollection )->getStartDateDateTime(); - $collectionEndDate = end( $bookingCollection )->getEndDateDateTime()->modify( "+1 second" ); + $collectionEndDate = end( $bookingCollection )->getEndDateDateTime()->modify( '+1 second' ); $collectionTotalDays = $collectionStartDate->diff( $collectionEndDate )->d; - //checks if the collection of chained bookings ist still in the allowed limit + // checks if the collection of chained bookings ist still in the allowed limit $max_days = $timeframe->getMaxDays(); if ( $collectionTotalDays <= $max_days ) { return null; } else { - //remove the checked unallowed booking from the collection - return array_filter( $bookingCollection, function ( Booking $collectionItem ) use ( $booking ) { - return $collectionItem->ID !== $booking->ID; - } ); + // remove the checked unallowed booking from the collection + return array_filter( + $bookingCollection, + function ( Booking $collectionItem ) use ( $booking ) { + return $collectionItem->ID !== $booking->ID; + } + ); } } @@ -402,8 +424,8 @@ public static function checkChainBooking( Booking $booking, array $args = [], $a * Params: $args[0} = The amount of days the user is allowed to book * $args[1] = The period over which the user is allowed to book * - * @param Booking $booking - * @param array $args + * @param Booking $booking + * @param array $args * @param bool|array $appliedTerms * * @return array @@ -412,7 +434,7 @@ public static function checkChainBooking( Booking $booking, array $args = [], $a public static function checkMaxBookingDays( Booking $booking, array $args, $appliedTerms = false ): ?array { $allowedBookedDays = $args[0]; $periodDays = $args[1]; - //split the period in half, when it is an uneven number, the left side will be one day longer + // split the period in half, when it is an uneven number, the left side will be one day longer $daysHalf = $periodDays / 2; if ( $periodDays % 2 ) { $daysLeft = $daysHalf + 1; @@ -420,8 +442,8 @@ public static function checkMaxBookingDays( Booking $booking, array $args, $appl } else { $daysLeft = $daysRight = $daysHalf; } - $startOfPeriod = $booking->getStartDateDateTime()->modify( "-" . $daysLeft . " days" ); - $endOfPeriod = $booking->getEndDateDateTime()->modify( "+" . $daysRight . " days" ); + $startOfPeriod = $booking->getStartDateDateTime()->modify( '-' . $daysLeft . ' days' ); + $endOfPeriod = $booking->getEndDateDateTime()->modify( '+' . $daysRight . ' days' ); return self::checkBookingRangeForDays( $startOfPeriod, $endOfPeriod, $booking, $appliedTerms, $allowedBookedDays ); } @@ -438,21 +460,20 @@ public static function maxBookingDaysErrorMessage( $args ) { * Will return the conflicting bookings if a user has too many in the week * * Params: $args[0] : The amount of days the user is allowed to book per week - * $args[1] : Unused + * $args[1] : Unused * $args[2]: The day on which the counter is reset, default: 1 = sunday, 2 = monday, ..., 7 = saturday * - * - * @param Booking $booking - * @param array $args + * @param Booking $booking + * @param array $args * @param bool|array $appliedTerms * * @return array|null */ public static function checkMaxBookingDaysPerWeek( Booking $booking, array $args, $appliedTerms = false ): ?array { $allowedBookableDays = $args[0]; - //default is sunday, we could not use 0 because it would be interpreted as an empty value + // default is sunday, we could not use 0 because it would be interpreted as an empty value $resetDay = ( $args[2] < 7 && $args[2] >= 1 ) ? $args[2] : 1; - $range = self::getBookingWeekRange( $booking, $resetDay ); + $range = self::getBookingWeekRange( $booking, $resetDay ); return self::checkBookingRangeForDays( $range[0], $range[1], $booking, $appliedTerms, $allowedBookableDays ); } @@ -468,9 +489,9 @@ public static function maxDaysWeekErrorMessage( array $args ): string { public static function checkMaxBookingsWeek( Booking $booking, array $args, $appliedTerms = false ): ?array { $allowedTotalBookings = $args[0]; - //default is sunday + // default is sunday $resetDay = ( $args[2] < 6 && $args[2] >= 0 ) ? $args[2] : 0; - $range = self::getBookingWeekRange( $booking, $resetDay ); + $range = self::getBookingWeekRange( $booking, $resetDay ); return self::checkBookingAmount( $range[0], $range[1], $booking, $appliedTerms, $allowedTotalBookings ); } @@ -492,9 +513,8 @@ public static function maxBookingsWeekErrorMessage( array $args ): string { * $args[1] : Unused * $args[2]: The day on which the counter is reset, from 0 to max 31. * - * - * @param Booking $booking - * @param array $args + * @param Booking $booking + * @param array $args * @param bool|array $appliedTerms * * @return array|null @@ -505,7 +525,6 @@ public static function checkMaxBookingDaysPerMonth( Booking $booking, array $arg $range = self::getBookingMonthRange( $booking, $resetDay ); return self::checkBookingRangeForDays( $range[0], $range[1], $booking, $appliedTerms, $allowedBookableDays ); - } public static function maxDaysMonthErrorMessage( array $args ): string { @@ -534,12 +553,12 @@ public static function maxBookingsMonthErrorMessage( array $args ): string { * Will get two datetime objects that represent the start and end of the week in which the given booking is in. * * @param Booking $booking - The booking for which the week range should be determined - * @param int $resetDay - The day of the week on which the counter should be reset (1 = sunday, 2 = monday, ..., 7 = saturday) + * @param int $resetDay - The day of the week on which the counter should be reset (1 = sunday, 2 = monday, ..., 7 = saturday) * * @return DateTime[] - [0] = start of the week, [1] = end of the week */ - private static function getBookingWeekRange(Booking $booking, int $resetDay): array { - $resetDay--; // We couldn't use 0 for sunday because it would be interpreted as an empty value, so we subtract 1 here + private static function getBookingWeekRange( Booking $booking, int $resetDay ): array { + --$resetDay; // We couldn't use 0 for sunday because it would be interpreted as an empty value, so we subtract 1 here $resetDayString = strtolower( date( 'l', strtotime( "Sunday +{$resetDay} days" ) ) ); $bookingDate = $booking->getStartDateDateTime(); @@ -554,25 +573,24 @@ private static function getBookingWeekRange(Booking $booking, int $resetDay): ar $startOfWeek->modify( 'last ' . $resetDayString ); $endOfWeek->modify( 'next ' . $resetDayString ); } - return [$startOfWeek, $endOfWeek]; + return [ $startOfWeek, $endOfWeek ]; } /** * Will get two datetime objects that represent the start and end of the month in which the given booking is in. * * @param Booking $booking - The booking for which the month range should be determined - * @param int $resetDay - The day of the month on which the counter should be reset + * @param int $resetDay - The day of the month on which the counter should be reset * * @return DateTime[] - [0] = start of the month, [1] = end of the month */ - private static function getBookingMonthRange(Booking $booking, int $resetDay): array { - $bookingDate = $booking->getStartDateDateTime(); + private static function getBookingMonthRange( Booking $booking, int $resetDay ): array { + $bookingDate = $booking->getStartDateDateTime(); // if the reset day is higher than the current max day of the month, we need to adjust the reset day $maxDayOfMonth = $bookingDate->format( 't' ); $resetDay = ( $resetDay > $maxDayOfMonth ) ? $maxDayOfMonth : $resetDay; - - //get the current month and year + // get the current month and year $day = $bookingDate->format( 'd' ); $month = $bookingDate->format( 'm' ); @@ -586,7 +604,7 @@ private static function getBookingMonthRange(Booking $booking, int $resetDay): a } else { $endDate->modify( '+1 month' ); } - return [$startDate, $endDate]; + return [ $startDate, $endDate ]; } /** @@ -596,14 +614,14 @@ private static function getBookingMonthRange(Booking $booking, int $resetDay): a * Is often used by BookingRule to determine if a booking should be taken into consideration * * @param Booking[] $bookings - * @param \WP_User $user + * @param \WP_User $user * @param $terms * * @return array|null */ private static function filterBookingsForTermsAndUser( array $bookings, \WP_User $user, $terms ): ?array { $filteredTerms = Booking::filterTermsApply( $bookings, $terms ); - if ( ! empty ( $filteredTerms ) ) { + if ( ! empty( $filteredTerms ) ) { return Booking::filterForUser( $bookings, $user ); } else { return null; @@ -613,12 +631,13 @@ private static function filterBookingsForTermsAndUser( array $bookings, \WP_User /** * Check, if the BookingRules settings have been modified from what is defined by default. * Used to check, if the setting has been touched by the user. + * * @return bool */ public static function hasDefaultSettings(): bool { $rulesConfig = Settings::getOption( 'commonsbooking_options_restrictions', 'rules_group' ); - return empty ( $rulesConfig ); + return empty( $rulesConfig ); } /** @@ -640,11 +659,11 @@ private static function filterEmptyBookings( array $bookings ) { * Will return the conflicting bookings if a user has too many in the range. * Will also consider the setting if cancelled bookings should be considered. * - * @param DateTime $startOfRange - * @param DateTime $endOfRange - * @param Booking $booking + * @param DateTime $startOfRange + * @param DateTime $endOfRange + * @param Booking $booking * @param array|false $appliedTerms - * @param int $allowedBookableDays + * @param int $allowedBookableDays * * @return array|null - conflicting bookings in order of post_date * @throws Exception @@ -667,11 +686,11 @@ private static function checkBookingRangeForDays( DateTime $startOfRange, DateTi $countedPostTypes ); $rangeBookingsArray = self::filterBookingsForTermsAndUser( $rangeBookingsArray, $booking->getUserData(), $appliedTerms ); - if ( empty ( $rangeBookingsArray ) ) { + if ( empty( $rangeBookingsArray ) ) { return null; } $rangeBookingsArray = self::filterEmptyBookings( $rangeBookingsArray ); - if ( empty ( $rangeBookingsArray ) ) { + if ( empty( $rangeBookingsArray ) ) { return null; } $totalLength = Booking::getTotalDuration( $rangeBookingsArray ); @@ -691,11 +710,11 @@ private static function checkBookingRangeForDays( DateTime $startOfRange, DateTi * Will return the conflicting bookings if a user has too many in the range. * Cancelled bookings will be considered when they were cancelled after the start of the range. * - * @param DateTime $startOfRange - * @param DateTime $endOfRange - * @param Booking $booking + * @param DateTime $startOfRange + * @param DateTime $endOfRange + * @param Booking $booking * @param $appliedTerms - * @param int $allowedTotalBookings + * @param int $allowedTotalBookings * * @return Booking[]|null * @throws Exception @@ -718,11 +737,11 @@ private static function checkBookingAmount( DateTime $startOfRange, DateTime $en $countedPostTypes ); $rangeBookingsArray = self::filterBookingsForTermsAndUser( $rangeBookingsArray, $booking->getUserData(), $appliedTerms ); - if ( empty ( $rangeBookingsArray ) ) { + if ( empty( $rangeBookingsArray ) ) { return null; } $rangeBookingsArray = self::filterEmptyBookings( $rangeBookingsArray ); - if ( empty ( $rangeBookingsArray ) ) { + if ( empty( $rangeBookingsArray ) ) { return null; } $totalBookings = count( $rangeBookingsArray ); diff --git a/src/Service/BookingRuleApplied.php b/src/Service/BookingRuleApplied.php index ed88e9e27..0c6ccb876 100644 --- a/src/Service/BookingRuleApplied.php +++ b/src/Service/BookingRuleApplied.php @@ -29,11 +29,12 @@ class BookingRuleApplied extends BookingRule { /** * Will construct a BookingRuleApplied object from an existing BookingRule. + * * @param BookingRule $rule * * @throws BookingRuleException */ - public function __construct( BookingRule $rule) { + public function __construct( BookingRule $rule ) { parent::__construct( $rule->name, $rule->title, @@ -49,14 +50,14 @@ public function __construct( BookingRule $rule) { /** * Will set what this Booking Rule applies to, either needs to be all or at least one category * - * @param bool $appliesToAll - * @param array $appliedTerms + * @param bool $appliesToAll + * @param array $appliedTerms * * @throws BookingRuleException */ - public function setAppliesToWhat(bool $appliesToAll, array $appliedTerms = []): void { - if (! $appliesToAll && empty($appliedTerms)){ - throw new BookingRuleException(__("You need to specify a category, if the rule does not apply to all items", 'commonsbooking')); + public function setAppliesToWhat( bool $appliesToAll, array $appliedTerms = [] ): void { + if ( ! $appliesToAll && empty( $appliedTerms ) ) { + throw new BookingRuleException( __( 'You need to specify a category, if the rule does not apply to all items', 'commonsbooking' ) ); } $this->appliesToAll = $appliesToAll; $this->appliedTerms = $appliedTerms; @@ -65,38 +66,36 @@ public function setAppliesToWhat(bool $appliesToAll, array $appliedTerms = []): /** * Will set the necessary params for the BookingRule to work * - * @param array $paramsToSet needs to be numeric - * @param int|string $selectParam needs to be numeric + * @param array $paramsToSet needs to be numeric + * @param int|string $selectParam needs to be numeric * * @throws BookingRuleException - if not enough params were specified for the BookingRule */ public function setAppliedParams( array $paramsToSet, $selectParam ): void { - if (! empty($this->params)){ - if (count($this->params) == count($paramsToSet) ){ + if ( ! empty( $this->params ) ) { + if ( count( $this->params ) == count( $paramsToSet ) ) { $this->appliedParams = $paramsToSet; - } - else { - throw new BookingRuleException(__("Booking rules: Not enough parameters specified.", 'commonsbooking')); + } else { + throw new BookingRuleException( __( 'Booking rules: Not enough parameters specified.', 'commonsbooking' ) ); } foreach ( $paramsToSet as $param ) { if ( ! is_numeric( $param ) ) { - throw new BookingRuleException( __( "Booking rules: Parameters need to be a number.", 'commonsbooking' ) ); + throw new BookingRuleException( __( 'Booking rules: Parameters need to be a number.', 'commonsbooking' ) ); } } } - if (! empty($this->selectParam)){ - if ( empty ( $selectParam ) || ! is_numeric($selectParam)){ - throw new BookingRuleException(__("Booking rules: Select parameter has not been properly set.", 'commonsbooking')); + if ( ! empty( $this->selectParam ) ) { + if ( empty( $selectParam ) || ! is_numeric( $selectParam ) ) { + throw new BookingRuleException( __( 'Booking rules: Select parameter has not been properly set.', 'commonsbooking' ) ); } - $this->appliedSelectParam = $selectParam; + $this->appliedSelectParam = $selectParam; } } /** * Sets the roles that the rule will not apply to * - * @param array $excludedRoles - * + * @param array $excludedRoles */ public function setExcludedRoles( array $excludedRoles ): void { $this->excludedRoles = $excludedRoles; @@ -112,23 +111,23 @@ public function setExcludedRoles( array $excludedRoles ): void { * @return array|null - An array of conflicting bookings or an empty array if the booking complies with all rules */ public function checkBookingCompliance( Booking $booking ): ?array { - if ($booking->isUserPrivileged()){ + if ( $booking->isUserPrivileged() ) { return null; } // Check if a rule is excluded for the user because of their role - if (isset ($this->excludedRoles)){ + if ( isset( $this->excludedRoles ) ) { if ( UserRepository::userHasRoles( $booking->getUserData()->ID, $this->excludedRoles ) - ){ + ) { return null; } } - if (! $this->appliesToAll && ! $booking->termsApply($this->appliedTerms)){ + if ( ! $this->appliesToAll && ! $booking->termsApply( $this->appliedTerms ) ) { return null; } @@ -144,33 +143,31 @@ public function checkBookingCompliance( Booking $booking ): ?array { * @return void * @throws BookingDeniedException */ - public static function bookingConformsToRules( Booking $booking):void { + public static function bookingConformsToRules( Booking $booking ): void { try { $ruleset = self::init(); } catch ( BookingRuleException $e ) { - //booking always conforms to rules if ruleset is not available / invalid + // booking always conforms to rules if ruleset is not available / invalid return; } - if($booking->isUserPrivileged()){ + if ( $booking->isUserPrivileged() ) { return; } foreach ( $ruleset as $rule ) { - - if ( ! ($rule instanceof BookingRuleApplied )) { - continue; //skip invalid rules during booking validation + if ( ! ( $rule instanceof BookingRuleApplied ) ) { + continue; // skip invalid rules during booking validation } $conflictingBookings = $rule->checkBookingCompliance( $booking ); - if ( $conflictingBookings ){ + if ( $conflictingBookings ) { $errorMessage = - $rule->getErrorMessage($rule->getArgs()) . + $rule->getErrorMessage( $rule->getArgs() ) . PHP_EOL . - __( "This affects the following bookings:", 'commonsbooking' ) . - PHP_EOL - ; + __( 'This affects the following bookings:', 'commonsbooking' ) . + PHP_EOL; /** @var Booking $conflictingBooking */ - foreach ($conflictingBookings as $conflictingBooking){ + foreach ( $conflictingBookings as $conflictingBooking ) { $errorMessage .= $conflictingBooking->bookingLink( sprintf( '%1s - %2s | %3s @ %4s', @@ -190,6 +187,7 @@ public static function bookingConformsToRules( Booking $booking):void { * Gets a string of all rule properties, so they can be displayed using CMB2 * * Will ignore errors, so that the settings page can still display the selected values even if they are invalid + * * @return string */ public static function getRulesJSON(): string { @@ -198,13 +196,14 @@ public static function getRulesJSON(): string { if ( isset( $ruleObjects ) ) { return wp_json_encode( array_map( - function( $rule){ - return get_object_vars($rule); - }, $ruleObjects ) + function ( $rule ) { + return get_object_vars( $rule ); + }, + $ruleObjects + ) ); - } - else { - return ""; + } else { + return ''; } } @@ -218,59 +217,58 @@ function( $rule){ * @throws BookingRuleException * @OVERRIDE */ - public static function init( bool $ignoreErrors = false ):array{ - $validRules = parent::init(); - $rulesConfig = Settings::getOption('commonsbooking_options_restrictions', 'rules_group'); + public static function init( bool $ignoreErrors = false ): array { + $validRules = parent::init(); + $rulesConfig = Settings::getOption( 'commonsbooking_options_restrictions', 'rules_group' ); $appliedRules = []; - if (!is_array($rulesConfig)) { - if ($ignoreErrors){ + if ( ! is_array( $rulesConfig ) ) { + if ( $ignoreErrors ) { return []; } - throw new BookingRuleException('No valid booking rules found'); + throw new BookingRuleException( 'No valid booking rules found' ); } - foreach ($rulesConfig as $ruleConfig) { + foreach ( $rulesConfig as $ruleConfig ) { /** @var BookingRule $validRule */ - foreach ($validRules as $validRule){ + foreach ( $validRules as $validRule ) { if ( ! isset( $ruleConfig['rule-type'] ) ) { - if ($ignoreErrors){ - continue; - } + if ( $ignoreErrors ) { + continue; + } throw new BookingRuleException( __( 'Booking rules: No rule type specified.', 'commonsbooking' ) ); } - if ($validRule->name !== $ruleConfig['rule-type']) { + if ( $validRule->name !== $ruleConfig['rule-type'] ) { continue; } $ruleParams = []; - if ( - ! empty($ruleConfig['rule-param1']) && - count($validRule->params) >= 1) - { - $ruleParams[] = $ruleConfig['rule-param1']; - } if ( - ! empty($ruleConfig['rule-param2']) && - count($validRule->params) >= 2 - ) - { + ! empty( $ruleConfig['rule-param1'] ) && + count( $validRule->params ) >= 1 ) { + $ruleParams[] = $ruleConfig['rule-param1']; + } + if ( + ! empty( $ruleConfig['rule-param2'] ) && + count( $validRule->params ) >= 2 + ) { $ruleParams[] = $ruleConfig['rule-param2']; } - if (! empty ( $ruleConfig['rule-select-param'] )) { $selectParam = $ruleConfig['rule-select-param']; } + if ( ! empty( $ruleConfig['rule-select-param'] ) ) { + $selectParam = $ruleConfig['rule-select-param']; } - if (! empty ( $ruleConfig['rule-applies-all'] ) && $ruleConfig['rule-applies-all'] === 'on'){ + if ( ! empty( $ruleConfig['rule-applies-all'] ) && $ruleConfig['rule-applies-all'] === 'on' ) { $appliesToAll = true; } - if ( ! empty ( $ruleConfig['rule-applies-categories'] ) ){ + if ( ! empty( $ruleConfig['rule-applies-categories'] ) ) { $appliedTerms = $ruleConfig['rule-applies-categories']; } - $ruleExemptRoles = empty($ruleConfig['rule-exempt-roles']) ? null : $ruleConfig['rule-exempt-roles']; + $ruleExemptRoles = empty( $ruleConfig['rule-exempt-roles'] ) ? null : $ruleConfig['rule-exempt-roles']; - $bookingRule = new self($validRule); + $bookingRule = new self( $validRule ); try { $bookingRule->setAppliesToWhat( $appliesToAll ?? false, @@ -279,8 +277,7 @@ public static function init( bool $ignoreErrors = false ):array{ } catch ( BookingRuleException $e ) { if ( $ignoreErrors ) { continue; - } - else { + } else { throw $e; } } @@ -292,26 +289,26 @@ public static function init( bool $ignoreErrors = false ):array{ } catch ( BookingRuleException $e ) { if ( $ignoreErrors ) { continue; - } - else { + } else { throw $e; } } $bookingRule->setExcludedRoles( - $ruleExemptRoles ?? []); + $ruleExemptRoles ?? [] + ); $appliedRules[] = $bookingRule; - - } } + } return $appliedRules; } /** * Checks if it can create all the rules, sets an error transient if it can't + * * @return void */ - public static function validateRules():void{ + public static function validateRules(): void { if ( self::hasDefaultSettings() ) { return; @@ -328,15 +325,16 @@ public static function validateRules():void{ /** * Will get the args array that belongs to the rule + * * @return null[] */ private function getArgs(): array { $args = $this->appliedParams ?? [ null, null ]; - //add null value to array to keep the params in the right order + // add null value to array to keep the params in the right order if ( count( $args ) == 1 ) { $args[] = null; } - if ( ! empty ( $this->appliedSelectParam ) ) { + if ( ! empty( $this->appliedSelectParam ) ) { $args[] = $this->appliedSelectParam; } else { $args[] = null; @@ -344,4 +342,4 @@ private function getArgs(): array { return $args; } -} \ No newline at end of file +} diff --git a/src/Service/Cache.php b/src/Service/Cache.php index 840a94053..d0656d092 100644 --- a/src/Service/Cache.php +++ b/src/Service/Cache.php @@ -19,6 +19,7 @@ trait Cache { /** * TODO: Refactor to constant after PHP 8.2 + * * @var string */ private static string $clearCacheHook = COMMONSBOOKING_PLUGIN_SLUG . '_clear_cache'; @@ -43,7 +44,8 @@ public static function getCacheItem( $custom_id = null ) { if ( $cacheItem->isHit() ) { return $cacheItem->get(); } - } catch (\Exception $exception) {} + } catch ( \Exception $exception ) { + } return false; } @@ -56,17 +58,16 @@ public static function getCacheItem( $custom_id = null ) { * @return string * @since 2.7.2 added Plugin_Dir to Namespace to avoid conflicts on multiple instances on same server * @since 2.9.4 added support for multisite caches - * */ public static function getCacheId( $custom_id = null ): string { $backtrace = debug_backtrace()[2]; $backtrace = self::sanitizeArgsArray( $backtrace ); - $namespace = COMMONSBOOKING_PLUGIN_DIR; //To account for multiple instances on same server - $namespace .= '_' . get_current_blog_id(); //To account for WP Multisite - $namespace .= '_' . str_replace( '\\', '_', strtolower( $backtrace['class'] ) ); - $namespace .= '_' . $backtrace['function']; + $namespace = COMMONSBOOKING_PLUGIN_DIR; // To account for multiple instances on same server + $namespace .= '_' . get_current_blog_id(); // To account for WP Multisite + $namespace .= '_' . str_replace( '\\', '_', strtolower( $backtrace['class'] ) ); + $namespace .= '_' . $backtrace['function']; $backtraceArgs = $backtrace['args']; - $namespace .= '_' . serialize( $backtraceArgs ); + $namespace .= '_' . serialize( $backtraceArgs ); if ( $custom_id ) { $namespace .= $custom_id; } @@ -81,8 +82,8 @@ public static function getCacheId( $custom_id = null ): string { */ private static function sanitizeArgsArray( $backtrace ) { if ( array_key_exists( 'args', $backtrace ) && - count( $backtrace['args'] ) && - is_array( $backtrace['args'][0] ) + count( $backtrace['args'] ) && + is_array( $backtrace['args'][0] ) ) { if ( array_key_exists( 'taxonomy', $backtrace['args'][0] ) ) { unset( $backtrace['args'][0]['taxonomy'] ); @@ -100,28 +101,28 @@ private static function sanitizeArgsArray( $backtrace ) { /** * Creates cache based on user settings or defaults. - * + * * At the moment filesystem and redis cache are supported. * - * @param string $namespace - * @param int $defaultLifetime + * @param string $namespace + * @param int $defaultLifetime * @param string|null $directory * * @return TagAwareAdapterInterface */ public static function getCache( string $namespace = '', int $defaultLifetime = 0, string $directory = null ): TagAwareAdapterInterface { - if ( $directory === null ){ + if ( $directory === null ) { $customCachePath = commonsbooking_sanitizeArrayorString( Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'cache_path' ) ); - if ( $customCachePath ){ + if ( $customCachePath ) { $directory = $customCachePath; } - //Since this is the default cache path by Symfony we'd rather set it to null so that Symfony can take over with it's own default value. - else if ( $customCachePath == '/tmp/symfony-cache/' ) { + // Since this is the default cache path by Symfony we'd rather set it to null so that Symfony can take over with it's own default value. + elseif ( $customCachePath == '/tmp/symfony-cache/' ) { $directory = null; } } - if (Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'redis_enabled' ) === 'on'){ + if ( Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'redis_enabled' ) === 'on' ) { try { $adapter = new RedisTagAwareAdapter( RedisAdapter::createConnection( Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'redis_dsn' ) ), @@ -129,8 +130,7 @@ public static function getCache( string $namespace = '', int $defaultLifetime = $defaultLifetime ); return $adapter; - } - catch (Exception $e) { + } catch ( Exception $e ) { commonsbooking_write_log( $e . 'Falling back to Filesystem adapter' ); set_transient( COMMONSBOOKING_PLUGIN_SLUG . '_adapter-error', $e->getMessage() ); } @@ -145,8 +145,8 @@ public static function getCache( string $namespace = '', int $defaultLifetime = * Saves cache item based on calling class, function and args. * * @param $value - * @param array $tags - * @param null $custom_id + * @param array $tags + * @param null $custom_id * @param string|null $expirationString set expiration as timestamp or string 'midnight' to set expiration to 00:00 next day * * @return bool @@ -158,11 +158,11 @@ public static function setCacheItem( $value, array $tags, $custom_id = null, ?st // too much space $expiration = 604800; - $tags = array_map('strval', $tags); - $tags = array_filter($tags); + $tags = array_map( 'strval', $tags ); + $tags = array_filter( $tags ); - if(!count($tags)) { - $tags = ['misc']; + if ( ! count( $tags ) ) { + $tags = [ 'misc' ]; } // if expiration is set to 'midnight' we calculate the duration in seconds until midnight @@ -175,9 +175,9 @@ public static function setCacheItem( $value, array $tags, $custom_id = null, ?st /** @var CacheItem $cacheItem */ $cacheKey = self::getCacheId( $custom_id ); $cacheItem = $cache->getItem( $cacheKey ); - $cacheItem->tag($tags); + $cacheItem->tag( $tags ); $cacheItem->set( $value ); - $cacheItem->expiresAfter(intval( $expiration )); + $cacheItem->expiresAfter( intval( $expiration ) ); return $cache->save( $cacheItem ); } @@ -190,18 +190,18 @@ public static function setCacheItem( $value, array $tags, $custom_id = null, ?st * @throws InvalidArgumentException */ public static function clearCache( array $tags = [] ) { - if(!count($tags)) { + if ( ! count( $tags ) ) { self::getCache()->clear(); } else { - self::getCache()->invalidateTags($tags); + self::getCache()->invalidateTags( $tags ); } // Delete expired cache items (only for Pruneable Interfaces) - if (is_a(self::getCache(),'Symfony\Component\Cache\PruneableInterface')) { + if ( is_a( self::getCache(), 'Symfony\Component\Cache\PruneableInterface' ) ) { self::getCache()->prune(); } - set_transient("clearCacheHasBeenDone", true, 45); + set_transient( 'clearCacheHasBeenDone', true, 45 ); } /** @@ -223,13 +223,14 @@ public static function scheduleClearCache( array $tags = [] ) { /** * Add js to frontend on cache clear. + * * @return void */ public static function addWarmupAjaxToOutput() { - if(get_transient("clearCacheHasBeenDone")) { - delete_transient("clearCacheHasBeenDone"); - wp_register_script( 'cache_warmup', '', array("jquery"), '', true ); - wp_enqueue_script( 'cache_warmup' ); + if ( get_transient( 'clearCacheHasBeenDone' ) ) { + delete_transient( 'clearCacheHasBeenDone' ); + wp_register_script( 'cache_warmup', '', array( 'jquery' ), '', true ); + wp_enqueue_script( 'cache_warmup' ); wp_add_inline_script( 'cache_warmup', ' @@ -251,7 +252,7 @@ public static function warmupCache() { $table_posts = $wpdb->prefix . 'posts'; // First get all pages with cb shortcodes - $sql = "SELECT post_content FROM $table_posts WHERE + $sql = "SELECT post_content FROM $table_posts WHERE post_content LIKE '%[cb_%]%' AND post_type = 'page' AND post_status = 'publish'"; @@ -263,17 +264,17 @@ public static function warmupCache() { // Now extract shortcode calls including attributes and bodies $shortCodeCalls = []; - foreach($pages as $page) { - preg_match_all("/$regex/", $page->post_content, $shortcodeMatches, PREG_SET_ORDER); + foreach ( $pages as $page ) { + preg_match_all("/$regex/", $page->post_content, $shortcodeMatches, PREG_SET_ORDER ); // Process each matched shortcode - foreach ($shortcodeMatches as $match) { + foreach ($shortcodeMatches as $match ) { $shortCode = $match[2]; // shortcode name e.g., "cb_search" $attributesString = isset($match[3]) ? $match[3] : ''; // e.g., " id=123" $shortCodeCalls[] = [ - 'shortcode' => $shortCode, - 'attributes' => self::getShortcodeAndAttributes($shortCode . $attributesString)[1], + 'shortcode' => $shortCode , + 'attributes' => self::getShortcodeAndAttributes($shortCode . $attributesString)[1], 'body' => isset($match[5]) ? trim($match[5]) : '', ]; } @@ -282,42 +283,41 @@ public static function warmupCache() { // Filter duplicate calls $shortCodeCalls = array_unique($shortCodeCalls, SORT_REGULAR); - self::runShortcodeCalls($shortCodeCalls); + self::runShortcodeCalls( $shortCodeCalls ); - wp_send_json("cache successfully warmed up"); - } catch (\Exception $exception) { - wp_send_json("something went wrong with cache warm up"); + wp_send_json( 'cache successfully warmed up' ); + } catch ( \Exception $exception ) { + wp_send_json( 'something went wrong with cache warm up' ); } } /** - * Renders little connections status information for REDIS database - * @param array $field_args + * Renders little connections status information for REDIS database + * + * @param array $field_args * @param CMB2_Field $field */ - public static function renderREDISConnectionStatus( array $field_args, CMB2_Field $field ){ + public static function renderREDISConnectionStatus( array $field_args, CMB2_Field $field ) { ?>
        - -
        + +
        '; - echo __('Successfully connected to REDIS database!', 'commonsbooking'); + echo __( 'Successfully connected to REDIS database!', 'commonsbooking' ); echo '
        '; - } - else { + } else { echo '
        '; - echo get_transient(COMMONSBOOKING_PLUGIN_SLUG . '_adapter-error'); + echo get_transient( COMMONSBOOKING_PLUGIN_SLUG . '_adapter-error' ); echo '
        '; } - } - else { + } else { echo '
        '; - echo __('REDIS database not enabled','commonsbooking'); + echo __( 'REDIS database not enabled', 'commonsbooking' ); echo '
        '; } ?> @@ -326,7 +326,7 @@ public static function renderREDISConnectionStatus( array $field_args, CMB2_Fiel
        @@ -335,20 +335,18 @@ public static function renderFilesystemStatus( array $field_ars, CMB2_Field $fie
        '; - echo sprintf( commonsbooking_sanitizeHTML(__('Directory %s is writeable.', 'commonsbooking') ), $cachePath); + printf( commonsbooking_sanitizeHTML( __( 'Directory %s is writeable.', 'commonsbooking' ) ), $cachePath ); echo '
        '; - } - else { + } else { echo '
        '; - echo sprintf( commonsbooking_sanitizeHTML(__('Directory %s could not be written to.', 'commonsbooking') ), $cachePath); + printf( commonsbooking_sanitizeHTML( __( 'Directory %s could not be written to.', 'commonsbooking' ) ), $cachePath ); echo '
        '; } ?> @@ -365,12 +363,12 @@ public static function renderClearCacheButton( $field_args, $field ) {
        - 1) { + foreach ( $shortCodeParts as $part ) { + $parts = explode( '=', $part ); + $key = $parts[0]; + $value = ''; + if ( count( $parts ) > 1 ) { $value = $parts[1]; - if(preg_match('/^".*"$/', $value)) { - $value = substr($value,1,-1); + if ( preg_match( '/^".*"$/', $value ) ) { + $value = substr( $value, 1, -1 ); } } - $args[$key] = $value; + $args[ $key ] = $value; } - return [$shortCode, $args]; + return [ $shortCode, $args ]; } private static $cbShortCodeFunctions = [ - "cb_items" => array( \CommonsBooking\View\Item::class, 'shortcode' ), + 'cb_items' => array( \CommonsBooking\View\Item::class, 'shortcode' ), 'cb_bookings' => array( \CommonsBooking\View\Booking::class, 'shortcode' ), - "cb_locations" => array( \CommonsBooking\View\Location::class, 'shortcode' ), - "cb_map" => array( MapShortcode::class, 'execute' ), + 'cb_locations' => array( \CommonsBooking\View\Location::class, 'shortcode' ), + 'cb_map' => array( MapShortcode::class, 'execute' ), "cb_search" => array( \CommonsBooking\Map\SearchShortcode::class, 'execute' ), - 'cb_items_table' => array( Calendar::class, 'renderTable' ) + 'cb_items_table' => array( Calendar::class, 'renderTable' ), ]; - } diff --git a/src/Service/Holiday.php b/src/Service/Holiday.php index 58e1220fb..82338030e 100644 --- a/src/Service/Holiday.php +++ b/src/Service/Holiday.php @@ -7,6 +7,7 @@ class Holiday { /** * Will render the fields in the timeframe settings where the user can define the holidays to get for the different German states and years. * The actual holidays will be loaded through feiertagejs. + * * @param $field * @param $value * @param $object_id @@ -18,36 +19,47 @@ class Holiday { public static function renderFields( $field, $value, $object_id, $object_type, $field_type ) { // make sure we specify each part of the value we need. - $value = wp_parse_args( $value, array( - 'holiday_year' => '', - 'holiday_state' => '', - ) ); + $value = wp_parse_args( + $value, + array( + 'holiday_year' => '', + 'holiday_state' => '', + ) + ); ?>
        - select( array( - 'name' => $field_type->_name( '[holiday_year]' ), - 'id' => $field_type->_id( 'holiday_year' ), - 'class' => 'multicheck', - 'desc' => '', - 'options' => self::getYearsOption(), - ) ); ?> + for="_id( 'holiday_year' ); ?>"> + select( + array( + 'name' => $field_type->_name( '[holiday_year]' ), + 'id' => $field_type->_id( 'holiday_year' ), + 'class' => 'multicheck', + 'desc' => '', + 'options' => self::getYearsOption(), + ) + ); + ?>
        - select( array( - 'name' => $field_type->_name( '[holiday_state]' ), - 'id' => $field_type->_id( 'holiday_state' ), - 'desc' => '', - 'type' => 'multicheck', - 'class' => 'cmb2_select', - 'options' => self::getStatesOption(), - ) ); ?> + select( + array( + 'name' => $field_type->_name( '[holiday_state]' ), + 'id' => $field_type->_id( 'holiday_state' ), + 'desc' => '', + 'type' => 'multicheck', + 'class' => 'cmb2_select', + 'options' => self::getStatesOption(), + ) + ); + ?>

        @@ -73,8 +85,8 @@ public static function renderFields( $field, $value, $object_id, $object_type, $ * * @return string */ - public static function getStatesOption( ): string { - $states = [ + public static function getStatesOption(): string { + $states = [ 'BW' => 'BADEN WUERTEMBERG', 'BY' => 'BAYERN', 'BE' => 'BERLIN', @@ -91,11 +103,11 @@ public static function getStatesOption( ): string { 'ST' => 'SACHSEN ANHALT', 'SH' => 'SCHLESWIG HOLSTEIN', 'TH' => 'THUERINGEN', - 'BUND' => 'NATIONAL' + 'BUND' => 'NATIONAL', ]; $stateOptions = ''; foreach ( $states as $abbrev => $state ) { - $stateOptions .= ''; + $stateOptions .= ''; } return $stateOptions; } @@ -103,19 +115,20 @@ public static function getStatesOption( ): string { /** * Will get the years for the next 3 years. * Formatted in HTML select options + * * @return string */ - public static function getYearsOption( ): string { - $year = intval(date('Y')); + public static function getYearsOption(): string { + $year = intval( date( 'Y' ) ); $year_options = ''; - for ( $i = 0 ; $i < 3; $i++ ) { - $year_options .= ''; } return $year_options; } diff --git a/src/Service/MassOperations.php b/src/Service/MassOperations.php index a4938ba26..6e70f346a 100644 --- a/src/Service/MassOperations.php +++ b/src/Service/MassOperations.php @@ -25,12 +25,12 @@ public static function ajaxMigrateOrphaned() { if ( $success ) { $result = array( 'success' => true, - 'message' => __( 'All selected orphaned bookings have been migrated.', 'commonsbooking' ) + 'message' => __( 'All selected orphaned bookings have been migrated.', 'commonsbooking' ), ); } else { $result = array( 'success' => false, - 'message' => $errorMessage ?? __( 'An error occurred while moving bookings.', 'commonsbooking' ) + 'message' => $errorMessage ?? __( 'An error occurred while moving bookings.', 'commonsbooking' ), ); } @@ -53,7 +53,7 @@ public static function migrateOrphaned( array $bookingIds ): bool { } $orphanedBookings = \CommonsBooking\Repository\Booking::getOrphaned(); - //iterate over them and assign them new locations + // iterate over them and assign them new locations foreach ( $orphanedBookings as $booking ) { if ( ! in_array( $booking->ID, $bookingIds ) ) { continue; @@ -76,4 +76,4 @@ public static function migrateOrphaned( array $bookingIds ): bool { return true; } -} \ No newline at end of file +} diff --git a/src/Service/Scheduler.php b/src/Service/Scheduler.php index 762bdf4aa..8dfd50fe7 100644 --- a/src/Service/Scheduler.php +++ b/src/Service/Scheduler.php @@ -14,8 +14,8 @@ */ class Scheduler { - protected string $jobhook; - protected string $reccurence; + protected string $jobhook; + protected string $reccurence; protected int $timestamp; const UNSCHEDULER_HOOK = COMMONSBOOKING_PLUGIN_SLUG . '_unschedule'; @@ -26,12 +26,13 @@ class Scheduler { * The constructor determines if the job is scheduled and if it should be scheduled. * It also hooks the appropriate actions that will un-schedule the job upon certain changes. * We can safely un-schedule the job upon changes, because the job will be re-scheduled with the correct settings when the page is loaded again. - * @param string $jobhook the action hook to run when the event is executed + * + * @param string $jobhook the action hook to run when the event is executed * @param callable $callback the callback function of that hook - * @param string $reccurence how often the event should subsequently recur - * @param string $executionTime takes time of day the job should be executed, only for daily reccurence - * @param array $option first element is the options_key, second is the field_id. If set, the field is checked and determines wether the hook should be ran - * @param string $updateHook The wordpress hook that should update the option + * @param string $reccurence how often the event should subsequently recur + * @param string $executionTime takes time of day the job should be executed, only for daily reccurence + * @param array $option first element is the options_key, second is the field_id. If set, the field is checked and determines wether the hook should be ran + * @param string $updateHook The WordPress hook that should update the option */ function __construct( string $jobhook, @@ -39,59 +40,56 @@ function __construct( string $reccurence, string $executionTime = '', array $option = array(), - string $updateHook= '' - ) - { + string $updateHook = '' + ) { // Add custom cron intervals add_filter( 'cron_schedules', array( self::class, 'initIntervals' ) ); - $this->jobhook = COMMONSBOOKING_PLUGIN_SLUG . '_' .$jobhook; //Prepends plugin slug so that hooks can be found easily afterwards + $this->jobhook = COMMONSBOOKING_PLUGIN_SLUG . '_' . $jobhook; // Prepends plugin slug so that hooks can be found easily afterwards - if ((count($option) == 2) && Settings::getOption($option[0],$option[1]) != 'on' ) { //removes job if option unset + if ( ( count( $option ) == 2 ) && Settings::getOption( $option[0], $option[1] ) != 'on' ) { // removes job if option unset $this->unscheduleJob(); return false; } - if (empty($executionTime)){ + if ( empty( $executionTime ) ) { $this->timestamp = time(); - } - elseif ($reccurence == 'daily'){ - $this->timestamp = strtotime($executionTime); - if($this->timestamp < time()) { //if timestamp is in the past, add one day - $this->timestamp = strtotime("+1 day",$this->timestamp); + } elseif ( $reccurence == 'daily' ) { + $this->timestamp = strtotime( $executionTime ); + if ( $this->timestamp < time() ) { // if timestamp is in the past, add one day + $this->timestamp = strtotime( '+1 day', $this->timestamp ); } - } - else { + } else { return false; } - $this->reccurence = $reccurence; - add_action($this->jobhook,$callback); //attaches the jobhook to the callback function + add_action( $this->jobhook, $callback ); // attaches the jobhook to the callback function - if (! wp_next_scheduled( $this->jobhook )){ //add job if it does not exist yet - wp_schedule_event($this->timestamp,$this->reccurence,$this->jobhook); + if ( ! wp_next_scheduled( $this->jobhook ) ) { // add job if it does not exist yet + wp_schedule_event( $this->timestamp, $this->reccurence, $this->jobhook ); } - if ($updateHook) { //attach updateHook to updater function + if ( $updateHook ) { // attach updateHook to updater function add_action( $updateHook, - function(){ - $this->unscheduleJob(); //hooks is unscheduled upon change, needs to be rescheduled + function () { + $this->unscheduleJob(); // hooks is unscheduled upon change, needs to be rescheduled } ); } add_action( self::UNSCHEDULER_HOOK, - function(){ + function () { $this->unscheduleJob(); } - ); //registers unschedule action + ); // registers unschedule action } /** * Returns array with custom time intervals. + * * @return array[] */ public static function getIntervals(): array { @@ -111,7 +109,7 @@ public static function getIntervals(): array { 'thirty_minutes' => array( 'display' => 'Every 30 Minutes', 'interval' => 1800, - ) + ), ); } @@ -135,54 +133,54 @@ public static function initIntervals( $schedules ): array { */ public static function initHooks() { // Init booking cleanup job - New Scheduler( + new Scheduler( 'cleanup', array( \CommonsBooking\Service\Booking::class, 'cleanupBookings' ), 'ten_minutes' ); // Init booking reminder job - New Scheduler( + new Scheduler( 'reminder', array( \CommonsBooking\Service\Booking::class, 'sendReminderMessage' ), 'daily', 'today ' . Settings::getOption( 'commonsbooking_options_reminder', 'pre-booking-time' ) . ':00', - array( 'commonsbooking_options_reminder', 'pre-booking-reminder-activate'), + array( 'commonsbooking_options_reminder', 'pre-booking-reminder-activate' ), 'update_option_commonsbooking_options_reminder' ); // Init booking start reminder job for locations - New Scheduler( + new Scheduler( 'location-reminder-booking-start', array( \CommonsBooking\Service\Booking::class, 'sendBookingStartLocationReminderMessage' ), 'daily', 'today ' . Settings::getOption( 'commonsbooking_options_reminder', 'booking-start-location-reminder-time' ) . ':00', - array( 'commonsbooking_options_reminder', 'booking-start-location-reminder-activate'), + array( 'commonsbooking_options_reminder', 'booking-start-location-reminder-activate' ), 'update_option_commonsbooking_options_reminder' ); // Init booking end reminder job for locations - New Scheduler( + new Scheduler( 'location-reminder-booking-end', array( \CommonsBooking\Service\Booking::class, 'sendBookingEndLocationReminderMessage' ), 'daily', 'today ' . Settings::getOption( 'commonsbooking_options_reminder', 'booking-end-location-reminder-time' ) . ':00', - array( 'commonsbooking_options_reminder', 'booking-end-location-reminder-activate'), + array( 'commonsbooking_options_reminder', 'booking-end-location-reminder-activate' ), 'update_option_commonsbooking_options_reminder' ); // Init booking feedback job - New Scheduler( + new Scheduler( 'feedback', array( \CommonsBooking\Service\Booking::class, 'sendFeedbackMessage' ), 'daily', 'tomorrow midnight', - array( 'commonsbooking_options_reminder', 'post-booking-notice-activate'), + array( 'commonsbooking_options_reminder', 'post-booking-notice-activate' ), 'update_option_commonsbooking_options_reminder' ); // Init email booking codes job - New Scheduler( + new Scheduler( 'email_bookingcodes', array( \CommonsBooking\Service\BookingCodes::class, 'sendBookingCodesMessage' ), 'daily', @@ -190,16 +188,16 @@ public static function initHooks() { ); // Init timeframe export job - $exportPath = Settings::getOption( 'commonsbooking_options_export', 'export-filepath' ); + $exportPath = Settings::getOption( 'commonsbooking_options_export', 'export-filepath' ); $exportInterval = Settings::getOption( 'commonsbooking_options_export', 'export-interval' ); - New Scheduler( + new Scheduler( 'export', - function() use ( $exportPath ) { + function () use ( $exportPath ) { TimeframeExport::cronExport( $exportPath ); }, $exportInterval, '', - array( 'commonsbooking_options_export', 'export-cron' ), + array( 'commonsbooking_options_export', 'export-cron' ), 'update_option_commonsbooking_options_export' ); } @@ -226,10 +224,11 @@ public function getTimestamp(): int { * - The job is no longer needed * - The job has been updated and needs to be rescheduled * - The plugin has been deactivated - * @return boolean + * + * @return int|false|\WP_Error */ private function unscheduleJob() { - return wp_clear_scheduled_hook($this->jobhook); + return wp_clear_scheduled_hook( $this->jobhook ); } /** @@ -245,11 +244,11 @@ public static function unscheduleOldEvents() { 'cb_feedback_cron_hook', 'cb_cron_export', 'cb_map_import', - 'cb_cron_delete_pending' + 'cb_cron_delete_pending', ]; foreach ( $cbCronHooks as $cbCronHook ) { - wp_clear_scheduled_hook($cbCronHook); + wp_clear_scheduled_hook( $cbCronHook ); } } -} \ No newline at end of file +} diff --git a/src/Service/TimeframeExport.php b/src/Service/TimeframeExport.php index e869a2437..aaab4b5dd 100644 --- a/src/Service/TimeframeExport.php +++ b/src/Service/TimeframeExport.php @@ -23,19 +23,20 @@ class TimeframeExport { * The post type to export. * This corresponds to the return of @see \CommonsBooking\Wordpress\CustomPostType\Timeframe::getTypes() * The all option is corresponding to 0. + * * @var string */ private int $exportType; private ?array $locationFields = null; - private ?array $itemFields = null; - private ?array $userFields = null; + private ?array $itemFields = null; + private ?array $userFields = null; private string $exportStartDate; private string $exportEndDate; private string $exportFilename; private bool $exportDataComplete = false; - private bool $isCron = false; + private bool $isCron = false; private ?string $lastProcessedPage = null; private ?string $totalPosts; @@ -50,16 +51,16 @@ class TimeframeExport { const ITERATION_COUNTS = 100; /** - * @param string $exportType - * @param string $exportStartDate - * @param string $exportEndDate + * @param string $exportType + * @param string $exportStartDate + * @param string $exportEndDate * - * @param array|null $locationFields - * @param array|null $itemFields - * @param array|null $userFields + * @param array|null $locationFields + * @param array|null $itemFields + * @param array|null $userFields * @param string|null $lastProcessedPage * @param string|null $totalPosts - * @param array|null $relevantTimeframes + * @param array|null $relevantTimeframes * * @throws ExportException */ @@ -77,23 +78,21 @@ public function __construct( if ( ! array_key_exists( $exportType, \CommonsBooking\Wordpress\CustomPostType\Timeframe::getTypes( true ) ) ) { throw new ExportException( 'Post type to export not valid' ); - } else { - if ( $exportType === 'all' ) { + } elseif ( $exportType === 'all' ) { $exportType = 0; - } else { - $exportType = intval( $exportType ); - } + } else { + $exportType = intval( $exportType ); } $startDateTimestamp = strtotime( $exportStartDate ); if ( ! $startDateTimestamp ) { - throw new ExportException( __( "Invalid start date", 'commonsbooking' ) ); + throw new ExportException( __( 'Invalid start date', 'commonsbooking' ) ); } $endDateTimestamp = strtotime( $exportEndDate ); if ( ! $endDateTimestamp ) { - throw new ExportException( __( "Invalid end date", 'commonsbooking' ) ); + throw new ExportException( __( 'Invalid end date', 'commonsbooking' ) ); } if ( $startDateTimestamp > $endDateTimestamp ) { - throw new ExportException( __( "Start date must not be after the end date.", 'commonsbooking' ) ); + throw new ExportException( __( 'Start date must not be after the end date.', 'commonsbooking' ) ); } $this->exportFilename = 'timeframe-export-' . date( 'Y-m-d-H-i-s' ) . '.csv'; @@ -110,7 +109,7 @@ public function __construct( public static function ajaxExportCsv() { - //verify nonce + // verify nonce check_ajax_referer( 'cb_export_timeframes', 'nonce' ); $postData = isset( $_POST['data'] ) ? (array) $_POST['data'] : array(); @@ -118,7 +117,7 @@ public static function ajaxExportCsv() { $postSettings = $postData['settings']; - $relevantTimeframes = empty ( $postSettings['relevantTimeframes'] ) ? null : $postSettings['relevantTimeframes']; + $relevantTimeframes = empty( $postSettings['relevantTimeframes'] ) ? null : $postSettings['relevantTimeframes']; if ( $relevantTimeframes !== null ) { $relevantTimeframes = array_map( 'intval', $relevantTimeframes ); } @@ -136,11 +135,13 @@ public static function ajaxExportCsv() { $relevantTimeframes, ); } catch ( ExportException $e ) { - wp_send_json( array( - 'success' => false, - 'error' => true, - 'message' => $e->getMessage() - ) ); + wp_send_json( + array( + 'success' => false, + 'error' => true, + 'message' => $e->getMessage(), + ) + ); return; } @@ -150,24 +151,28 @@ public static function ajaxExportCsv() { try { $csvString = $exportObject->getCSV(); } catch ( ExportException $e ) { - wp_send_json( array( - 'success' => false, - 'error' => true, - 'message' => $e->getMessage() - ) ); + wp_send_json( + array( + 'success' => false, + 'error' => true, + 'message' => $e->getMessage(), + ) + ); return; } - wp_send_json( array( - 'success' => true, - 'error' => false, - 'message' => __( 'Export finished', 'commonsbooking' ), - 'csv' => $csvString, - 'filename' => $exportObject->exportFilename - ) ); + wp_send_json( + array( + 'success' => true, + 'error' => false, + 'message' => __( 'Export finished', 'commonsbooking' ), + 'csv' => $csvString, + 'filename' => $exportObject->exportFilename, + ) + ); } else { $options = array( - 'exportType' => $exportObject->exportType == 0 ? "all" : $exportObject->exportType, + 'exportType' => $exportObject->exportType == 0 ? 'all' : $exportObject->exportType, 'exportStartDate' => $exportObject->exportStartDate, 'exportEndDate' => $exportObject->exportEndDate, 'locationFields' => $exportObject->locationFields, @@ -177,12 +182,14 @@ public static function ajaxExportCsv() { 'totalPosts' => $exportObject->totalPosts, 'relevantTimeframes' => $exportObject->relevantTimeframes, ); - wp_send_json( array( - 'success' => false, - 'error' => false, - 'settings' => $options, - 'progress' => $exportObject->getProgressString() - ) ); + wp_send_json( + array( + 'success' => false, + 'error' => false, + 'settings' => $options, + 'progress' => $exportObject->getProgressString(), + ) + ); } } @@ -247,20 +254,20 @@ public function getCSV( string $exportPath = null ): string { $inputFields = [ 'location' => self::getInputFields( 'location-fields' ), 'item' => self::getInputFields( 'item-fields' ), - 'user' => self::getInputFields( 'user-fields' ) + 'user' => self::getInputFields( 'user-fields' ), ]; if ( ! $this->exportDataComplete ) { - throw new ExportException( __( "Export data is not complete. Please complete the process before trying to export.", 'commonsbooking' ) ); + throw new ExportException( __( 'Export data is not complete. Please complete the process before trying to export.', 'commonsbooking' ) ); } if ( $this->relevantTimeframes === null ) { - throw new ExportException( __( "No data was found for the selected time period", 'commonsbooking' ) ); + throw new ExportException( __( 'No data was found for the selected time period', 'commonsbooking' ) ); } if ( $this->isCron ) { if ( $exportPath === null ) { - throw new ExportException( __( "You need to set an export path to execute the export", 'commonsbooking' ) ); + throw new ExportException( __( 'You need to set an export path to execute the export', 'commonsbooking' ) ); } $output = fopen( $exportPath, 'w' ); } else { @@ -273,7 +280,6 @@ public function getCSV( string $exportPath = null ): string { $timeframeDataRows = self::getTimeframeData( $this->relevantTimeframes ); foreach ( $timeframeDataRows as $timeframeDataRow ) { - if ( ! $headline ) { $headline = true; $headColumns = array_keys( $timeframeDataRow ); @@ -281,20 +287,23 @@ public function getCSV( string $exportPath = null ): string { // Iterate through in put fields foreach ( $inputFields as $type => $fields ) { $columnNames = $fields; - array_walk( $columnNames, function ( &$item ) use ( $type ) { - $item = $type . ': ' . $item; - } ); + array_walk( + $columnNames, + function ( &$item ) use ( $type ) { + $item = $type . ': ' . $item; + } + ); $headColumns = array_merge( $headColumns, $columnNames ); } // output the column headings - fputcsv( $output, $headColumns, ";" ); + fputcsv( $output, $headColumns, ';' ); } // output the column values $valueColumns = array_values( $timeframeDataRow ); - //TODO #507 + // TODO #507 $timeframeDataPost = new \CommonsBooking\Model\Timeframe( $timeframeDataRow['ID'] ); // Get values for user defined input fields. @@ -324,7 +333,7 @@ public function getCSV( string $exportPath = null ): string { } } - fputcsv( $output, $valueColumns, ";" ); + fputcsv( $output, $valueColumns, ';' ); } if ( $this->isCron ) { @@ -352,6 +361,7 @@ private static function convertInputFields( $inputString ) { /** * This will get a formatted string to display the pages that have been processed. + * * @return string */ private function getProgressString(): string { @@ -361,7 +371,7 @@ private function getProgressString(): string { $totalBookings = $this->totalPosts; $progressBookings = $this->lastProcessedPage * self::ITERATION_COUNTS; - return sprintf( __( 'Processed %d of %d bookings', 'commonsbooking' ), $progressBookings, $totalBookings ); + return sprintf( __( 'Processed %1$d of %2$d bookings', 'commonsbooking' ), $progressBookings, $totalBookings ); } /** @@ -393,7 +403,6 @@ public function getExportData( int $page = - 1 ): bool { $start = $this->exportStartDate; $end = $this->exportEndDate; - // Timerange $period = self::getPeriod( $start, $end ); @@ -403,14 +412,14 @@ public function getExportData( int $page = - 1 ): bool { $types = [ $this->exportType ]; } - //some custom arg for WP_Query to improve performance + // some custom arg for WP_Query to improve performance $customArgs = [ - "fields" => "ids", + 'fields' => 'ids', ]; - //when we already know the amount of posts, we can disable the SQL_CALC_FOUND_ROWS flag + // when we already know the amount of posts, we can disable the SQL_CALC_FOUND_ROWS flag if ( $this->totalPosts !== null ) { - $customArgs["no_found_rows"] = true; + $customArgs['no_found_rows'] = true; } if ( $page == - 1 ) { @@ -419,7 +428,7 @@ public function getExportData( int $page = - 1 ): bool { [], [], $this->exportType ? [ $this->exportType ] : [], - $dt->format( "Y-m-d" ), + $dt->format( 'Y-m-d' ), false, null, [ 'canceled', 'confirmed', 'unconfirmed', 'publish', 'inherit' ] @@ -448,7 +457,7 @@ public function getExportData( int $page = - 1 ): bool { $this->lastProcessedPage = $page; $this->exportDataComplete = $relevantTimeframes['done']; - if ( ! empty ( $relevantTimeframes['posts'] ) ) { + if ( ! empty( $relevantTimeframes['posts'] ) ) { foreach ( $relevantTimeframes['posts'] as $timeframeID ) { if ( ! is_array( $this->relevantTimeframes ) || ! in_array( $timeframeID, $this->relevantTimeframes ) ) { $this->relevantTimeframes[] = $timeframeID; @@ -480,6 +489,7 @@ protected static function getPeriod( $start, $end ) { /** * Returns selected timeframe type id. + * * @return int */ protected static function getType(): int { @@ -489,7 +499,7 @@ protected static function getType(): int { if ( array_key_exists( 'export-type', $_REQUEST ) && $_REQUEST['export-type'] !== 'all' ) { $type = intval( $_REQUEST['export-type'] ); } else { - //cron download + // cron download $configuredType = Settings::getOption( 'commonsbooking_options_export', 'export-type' ); if ( $configuredType && $configuredType != 'all' ) { $type = intval( $configuredType ); @@ -527,24 +537,26 @@ public static function getTimeframeData( array $timeframeIDs ): array { } // Repetition option - $repetitions = \CommonsBooking\Wordpress\CustomPostType\Timeframe::getTimeFrameRepetitions(); - $repetitionId = $timeframePost->getFieldValue( \CommonsBooking\Model\Timeframe::META_REPETITION ); + $repetitions = \CommonsBooking\Wordpress\CustomPostType\Timeframe::getTimeFrameRepetitions(); + $repetitionId = $timeframePost->getFieldValue( \CommonsBooking\Model\Timeframe::META_REPETITION ); $timeframeData[ \CommonsBooking\Model\Timeframe::META_REPETITION ] = array_key_exists( $repetitionId, $repetitions ) ? $repetitions[ $repetitionId ] : __( 'Unknown', 'commonsbooking' ); // Grid option $gridOptions = \CommonsBooking\Wordpress\CustomPostType\Timeframe::getGridOptions(); $gridOptionId = $timeframePost->getGrid(); - $timeframeData["grid"] = array_key_exists( $gridOptionId, $gridOptions ) ? + $timeframeData['grid'] = array_key_exists( $gridOptionId, $gridOptions ) ? $gridOptions[ $gridOptionId ] : __( 'Unknown', 'commonsbooking' ); - // get corresponding item title(s) $items = $timeframePost->getItems(); if ( $items != null ) { - $items_title = array_map( function ( $item ) { - return $item->post_title; - }, $items ); + $items_title = array_map( + function ( $item ) { + return $item->post_title; + }, + $items + ); } else { $items_title = __( 'Unknown', 'commonsbooking' ); } @@ -552,39 +564,41 @@ public static function getTimeframeData( array $timeframeIDs ): array { // get corresponding location title(s) $locations = $timeframePost->getLocations(); if ( $locations != null ) { - $locations_title = array_map( function ( $location ) { - return $location->post_title; - }, $locations ); + $locations_title = array_map( + function ( $location ) { + return $location->post_title; + }, + $locations + ); } else { $locations_title = __( 'Unknown', 'commonsbooking' ); } $timeframeOwner = $timeframePost->getUserData(); - // populate simple meta fields - $timeframeData[ \CommonsBooking\Model\Timeframe::META_MAX_DAYS ] = $timeframePost->getFieldValue( \CommonsBooking\Model\Timeframe::META_MAX_DAYS ); - $timeframeData["full-day"] = $timeframePost->getFieldValue( "full-day" ); + $timeframeData[ \CommonsBooking\Model\Timeframe::META_MAX_DAYS ] = $timeframePost->getFieldValue( \CommonsBooking\Model\Timeframe::META_MAX_DAYS ); + $timeframeData['full-day'] = $timeframePost->getFieldValue( 'full-day' ); $timeframeData[ \CommonsBooking\Model\Timeframe::REPETITION_START ] = $timeframePost->getStartDate() ? date( 'c', $timeframePost->getStartDate() ) : ''; $timeframeData[ \CommonsBooking\Model\Timeframe::REPETITION_END ] = $timeframePost->getEndDate() ? date( 'c', $timeframePost->getEndDate() ) : ''; - $timeframeData["start-time"] = $timeframePost->getStartTime(); - $timeframeData["end-time"] = $timeframePost->getEndTime(); - $timeframeData["pickup"] = isset( $booking ) ? $booking->pickupDatetime() : ""; - $timeframeData["return"] = isset( $booking ) ? $booking->returnDatetime() : ""; - $timeframeData["booking-code"] = $timeframePost->getFieldValue( "_cb_bookingcode" ); - $timeframeData["user-firstname"] = $timeframeOwner ? $timeframeOwner->first_name : ""; - $timeframeData["user-lastname"] = $timeframeOwner ? $timeframeOwner->last_name : ""; - $timeframeData["user-login"] = $timeframeOwner ? $timeframeOwner->user_login : ""; - $timeframeData["comment"] = $timeframePost->getFieldValue( 'comment' ); + $timeframeData['start-time'] = $timeframePost->getStartTime(); + $timeframeData['end-time'] = $timeframePost->getEndTime(); + $timeframeData['pickup'] = isset( $booking ) ? $booking->pickupDatetime() : ''; + $timeframeData['return'] = isset( $booking ) ? $booking->returnDatetime() : ''; + $timeframeData['booking-code'] = $timeframePost->getFieldValue( '_cb_bookingcode' ); + $timeframeData['user-firstname'] = $timeframeOwner ? $timeframeOwner->first_name : ''; + $timeframeData['user-lastname'] = $timeframeOwner ? $timeframeOwner->last_name : ''; + $timeframeData['user-login'] = $timeframeOwner ? $timeframeOwner->user_login : ''; + $timeframeData['comment'] = $timeframePost->getFieldValue( 'comment' ); foreach ( $locations_title as $location_title ) { foreach ( $items_title as $item_title ) { - $timeframeData["location-post_title"] = $location_title; - $timeframeData["item-post_title"] = $item_title; - //every item / location combination is a new row + $timeframeData['location-post_title'] = $location_title; + $timeframeData['item-post_title'] = $item_title; + // every item / location combination is a new row $timeframeDataRows[] = $timeframeData; } } @@ -605,14 +619,14 @@ protected static function getRelevantTimeframeFields( \CommonsBooking\Model\Time $relevantTimeframeFields = [ 'ID', 'post_title', - "post_author", - "post_date", - "post_date_gmt", - "post_content", - "comment", - "post_excerpt", - "post_status", - "post_name" + 'post_author', + 'post_date', + 'post_date_gmt', + 'post_content', + 'comment', + 'post_excerpt', + 'post_status', + 'post_name', ]; return array_filter( @@ -626,9 +640,10 @@ function ( $key ) use ( $relevantTimeframeFields ) { /** * Sets the cron flag. This is used to determine if the export is triggered by a cron job. + * * @return void */ public function setCron(): void { $this->isCron = true; } -} \ No newline at end of file +} diff --git a/src/Service/Upgrade.php b/src/Service/Upgrade.php index a47d8ca56..3a4abf2c7 100644 --- a/src/Service/Upgrade.php +++ b/src/Service/Upgrade.php @@ -35,26 +35,27 @@ class Upgrade { * you would add a new entry to this array with the key being "2.6.0" and the value being the function that needs to be run. * * This is so that once the upgrade from a specific version has been run, it will not be run again. + * * @var array[] */ private static array $upgradeTasks = [ '2.6.0' => [ [ \CommonsBooking\Migration\Booking::class, 'migrate' ], - [ self::class, 'setAdvanceBookingDaysDefault' ] + [ self::class, 'setAdvanceBookingDaysDefault' ], ], '2.8.0' => [ - [ \CommonsBooking\Service\Scheduler::class, 'unscheduleOldEvents' ] + [ \CommonsBooking\Service\Scheduler::class, 'unscheduleOldEvents' ], ], '2.8.2' => [ [ self::class, 'resetBrokenColorScheme' ], - [ self::class, 'fixBrokenICalTitle' ] + [ self::class, 'fixBrokenICalTitle' ], ], '2.9.2' => [ - [ self::class, 'enableLocationBookingNotification' ] + [ self::class, 'enableLocationBookingNotification' ], ], '2.10' => [ - [ self::class, 'migrateMapSettings' ] - ] + [ self::class, 'migrateMapSettings' ], + ], ]; /** @@ -71,20 +72,21 @@ class Upgrade { */ private static array $ajaxUpgradeTasks = [ '2.8.5' => [ - [ self::class, 'removeBreakingPostmeta' ] + [ self::class, 'removeBreakingPostmeta' ], ], '2.9.0' => [ - [ self::class, 'setMultiSelectTimeFrameDefault' ] - ] + [ self::class, 'setMultiSelectTimeFrameDefault' ], + ], ]; /** * The tasks that will be run upon every upgrade. + * * @return void */ private function runEveryUpgrade(): void { // set Options default values (e.g. if there are new fields added) - AdminOptions::SetOptionsDefaultValues(); + AdminOptions::setOptionsDefaultValues(); // flush rewrite rules flush_rewrite_rules(); @@ -98,14 +100,12 @@ private function runEveryUpgrade(): void { // update version number in options update_option( self::VERSION_OPTION, $this->currentVersion ); - // Clear cache try { Plugin::clearCache(); } catch ( InvalidArgumentException $e ) { // Do nothing } - } /** @@ -131,7 +131,7 @@ public function run(): bool { if ( $this->previousVersion === $this->currentVersion ) { return false; } - //upgrade needs to be run in AJAX + // upgrade needs to be run in AJAX if ( $this->getTasksForUpgrade( self::$ajaxUpgradeTasks ) ) { new AdminMessage( 'CommonsBooking: ' . @@ -201,41 +201,40 @@ public static function runTasksAfterUpdate(): void { /** * * Test in @see \CommonsBooking\Tests\Service\UpgradeTest_AJAX - * */ public static function runAJAXUpgradeTasks(): void { - //verify nonce + // verify nonce check_ajax_referer( 'cb_run_upgrade', 'nonce' ); - $data = isset ( $_POST['data'] ) ? (array) $_POST['data'] : array(); + $data = isset( $_POST['data'] ) ? (array) $_POST['data'] : array(); $data = commonsbooking_sanitizeArrayorString( $data ); $taskNo = $data['progress']['task'] ?? 0; $page = $data['progress']['page'] ?? 1; - $taskNo = (int) $taskNo; - $page = (int) $page; - $upgrade = new Upgrade( + $taskNo = (int) $taskNo; + $page = (int) $page; + $upgrade = new Upgrade( esc_html( get_option( self::VERSION_OPTION ) ), COMMONSBOOKING_VERSION ); - $totalTasks = $upgrade->getTasksForUpgrade( self::$ajaxUpgradeTasks ); - $task = $totalTasks[ $taskNo ]; + $totalTasks = $upgrade->getTasksForUpgrade( self::$ajaxUpgradeTasks ); + $task = $totalTasks[ $taskNo ]; list ( $className, $methodName ) = $task; - $page = call_user_func( array( $className, $methodName ), $page ); - //previous task was successful + $page = call_user_func( array( $className, $methodName ), $page ); + // previous task was successful if ( $page === true ) { - //check if there are more tasks + // check if there are more tasks if ( isset( $totalTasks[ $taskNo + 1 ] ) ) { $response = [ 'success' => false, 'error' => false, 'progress' => [ 'task' => $taskNo + 1, - 'page' => 1 - ] + 'page' => 1, + ], ]; } else { - //all tasks are done + // all tasks are done $response = [ 'success' => true, 'error' => false, @@ -248,12 +247,12 @@ public static function runAJAXUpgradeTasks(): void { 'error' => false, 'progress' => [ 'task' => $taskNo, - 'page' => $page - ] + 'page' => $page, + ], ]; } - //run other upgrade actions + // run other upgrade actions if ( $response['success'] === true ) { $upgrade->runUpgradeTasks(); $upgrade->runEveryUpgrade(); @@ -264,6 +263,7 @@ public static function runAJAXUpgradeTasks(): void { /** * Will determine if the latest upgrade needs to run AJAX actions to complete. + * * @return bool true if AJAX actions are needed, false if not. */ public static function isAJAXUpgrade(): bool { @@ -370,6 +370,7 @@ public static function updateLocationCoordinates(): void { /** * sets advance booking days to default value for existing timeframes. * Advances booking timeframes are available since 2.6 - all timeframes created prior to this version need to have this value set to a default value. + * * @return void * @see \CommonsBooking\Wordpress\CustomPostType\Timeframe::ADVANCE_BOOKING_DAYS * @@ -485,20 +486,22 @@ public static function enableLocationBookingNotification() { * @since 2.10 */ public static function migrateMapSettings(): void { - $maps = get_posts( [ - 'post_type' => \CommonsBooking\Wordpress\CustomPostType\Map::$postType, - 'numberposts' => - 1 - ] ); + $maps = get_posts( + [ + 'post_type' => \CommonsBooking\Wordpress\CustomPostType\Map::$postType, + 'numberposts' => - 1, + ] + ); foreach ( $maps as $map ) { $options = get_post_meta( $map->ID, 'cb_map_options', true ); - if ( empty( $options ) ) { //When default map options are empty + if ( empty( $options ) ) { // When default map options are empty continue; } if ( get_post_meta( $map->ID, array_key_first( $options ), true ) ) { - //if the first key in the options array is already set, we assume that the migration has already been done + // if the first key in the options array is already set, we assume that the migration has already been done continue; } - //will map to an associative array with key being the option name and the value the default value + // will map to an associative array with key being the option name and the value the default value $defaultValues = array_reduce( Map::getCustomFields(), function ( $result, $option ) { @@ -512,7 +515,7 @@ function ( $result, $option ) { ); foreach ( $options as $key => $value ) { if ( empty( $value ) && ! empty( $defaultValues[ $key ] ) ) { - //fetch from default values when key happens to be empty + // fetch from default values when key happens to be empty $value = $defaultValues[ $key ]; } if ( ! empty( $value ) ) { @@ -536,19 +539,19 @@ function ( $result, $option ) { } if ( ! empty( $options['cb_items_available_categories'] ) ) { $newCategoryArray = []; - $currentCategoryIndex = -1; //start with -1 so we can increment to 0 + $currentCategoryIndex = -1; // start with -1 so we can increment to 0 foreach ( $options['cb_items_available_categories'] as $key => $value ) { if ( substr( $key, 0, 1 ) == 'g' ) { - $currentCategoryIndex ++; + ++$currentCategoryIndex; $newCategoryArray[ $currentCategoryIndex ] = [ 'name' => $value, 'type' => '', 'isExclusive' => false, - 'categories' => [] + 'categories' => [], ]; } else { $newCategoryArray[ $currentCategoryIndex ]['categories'][] = (string) $key; - //see if specified name is different from taxonomy name, save differing name in taxonomy meta + // see if specified name is different from taxonomy name, save differing name in taxonomy meta if ( get_term( $key )->name != $value ) { update_term_meta( $key, COMMONSBOOKING_METABOX_PREFIX . 'markup', $value ); } diff --git a/src/Service/iCalendar.php b/src/Service/iCalendar.php index 70359b05b..111005d6d 100755 --- a/src/Service/iCalendar.php +++ b/src/Service/iCalendar.php @@ -30,68 +30,78 @@ */ class iCalendar { - private ?Calendar $calendar; + private ?Calendar $calendar; - public const URL_SLUG = COMMONSBOOKING_PLUGIN_SLUG . '_ical_download'; - public const QUERY_USER = COMMONSBOOKING_PLUGIN_SLUG . '_user'; - public const QUERY_USERHASH = COMMONSBOOKING_PLUGIN_SLUG . '_userhash'; + public const URL_SLUG = COMMONSBOOKING_PLUGIN_SLUG . '_ical_download'; + public const QUERY_USER = COMMONSBOOKING_PLUGIN_SLUG . '_user'; + public const QUERY_USERHASH = COMMONSBOOKING_PLUGIN_SLUG . '_userhash'; - public function __construct() - { + public function __construct() { // Create new calendar instance (eluceo/iCal) - $this->calendar = new Calendar(); - } + $this->calendar = new Calendar(); + } /** * Registers url to download ics file. - * Only enabled, when the setting is set in the advanced options + * Only enabled, when the setting is set in the advanced options + * * @return void */ public static function initRewrite() { - if (Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'feed_enabled' ) == 'on'){ - add_action( 'wp_loaded', function (){ - add_rewrite_rule( self::URL_SLUG, 'index.php?' . self::URL_SLUG. '=1', 'top' ); - } ); - - add_filter( 'query_vars', function ( $query_vars ){ - $query_vars[] = self::URL_SLUG; - return $query_vars; - } ); - - add_action( 'parse_request', function( &$wp ){ - - if (!array_key_exists( self::URL_SLUG, $wp->query_vars ) ) { - return; - } - self::getICSDownload(); - }); - } + if ( Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'feed_enabled' ) == 'on' ) { + add_action( + 'wp_loaded', + function () { + add_rewrite_rule( self::URL_SLUG, 'index.php?' . self::URL_SLUG . '=1', 'top' ); + } + ); + + add_filter( + 'query_vars', + function ( $query_vars ) { + $query_vars[] = self::URL_SLUG; + return $query_vars; + } + ); + + add_action( + 'parse_request', + function ( &$wp ) { + + if ( ! array_key_exists( self::URL_SLUG, $wp->query_vars ) ) { + return; + } + self::getICSDownload(); + } + ); + } } - /** - * Returns a valid link to retrieve iCalendar data for the current user, - * for this it takes the user id and hashes it using the wp_hash algorithm. - * This should be relatively secure, since the hash is salted. - * Returns false when user is not logged in - * - * @return string | bool - false when user is not logged in - */ - public static function getCurrentUserCalendarLink() { - if (!is_user_logged_in()) { return false;} - - $user_id = wp_get_current_user()->ID; - $user_hash = wp_hash($user_id); - $script_location = get_site_url() . '/'; - - return add_query_arg( - array( - self::QUERY_USER => $user_id, - self::QUERY_USERHASH => $user_hash, - self::URL_SLUG => true - ), - $script_location - ); - } + /** + * Returns a valid link to retrieve iCalendar data for the current user, + * for this it takes the user id and hashes it using the wp_hash algorithm. + * This should be relatively secure, since the hash is salted. + * Returns false when user is not logged in + * + * @return string | bool - false when user is not logged in + */ + public static function getCurrentUserCalendarLink() { + if ( ! is_user_logged_in() ) { + return false;} + + $user_id = wp_get_current_user()->ID; + $user_hash = wp_hash( $user_id ); + $script_location = get_site_url() . '/'; + + return add_query_arg( + array( + self::QUERY_USER => $user_id, + self::QUERY_USERHASH => $user_hash, + self::URL_SLUG => true, + ), + $script_location + ); + } /** * Get the ics file for an existing booking. Will be called, when the "Add to Calendar" button on the booking page is pressed @@ -128,101 +138,98 @@ public static function downloadICS( $bookingID ): void { * The title and description for the iCalendar, that can be set by the user in the options, will be used as the title and description of the event. * * @param Booking $booking - The booking to add to the calendar - * @param String $eventTitle - The title of the event in the ics calendar - * @param String $eventDescription - The description of the event in the ics calendar + * @param String $eventTitle - The title of the event in the ics calendar + * @param String $eventDescription - The description of the event in the ics calendar * * @throws \Exception */ - public function addBookingEvent( - Booking $booking, - String $eventTitle, - String $eventDescription) - { - $eventDescription = preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $eventDescription); //remove empty lines from the description, they are not part of the standard - - $bookingLocation = $booking->getLocation(); - $bookingLocation_latitude = $bookingLocation->getMeta( 'geo_latitude' ); - $bookingLocation_longitude = $bookingLocation->getMeta( 'geo_longitude' ); - - //create immutable DateTime objects from Mutable (recommended by iCal library developer) - $booking_startDateDateTime = DateTimeImmutable::createFromMutable( $booking->getUTCStartDateDateTime() ); - $booking_endDateDateTime = DateTimeImmutable::createFromMutable( $booking->getUTCEndDateDateTime() ); - - // Create timezone entity - $php_date_time_zone = wp_timezone(); - //will only get timezone object if current timezone has transitions that can be fetched - if ($php_date_time_zone->getTransitions()){ - $timezone = \Eluceo\iCal\Domain\Entity\TimeZone::createFromPhpDateTimeZone( - $php_date_time_zone, - $booking_startDateDateTime, - $booking_endDateDateTime + public function addBookingEvent( + Booking $booking, + string $eventTitle, + string $eventDescription + ) { + $eventDescription = preg_replace( "/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $eventDescription ); // remove empty lines from the description, they are not part of the standard + + $bookingLocation = $booking->getLocation(); + $bookingLocation_latitude = $bookingLocation->getMeta( 'geo_latitude' ); + $bookingLocation_longitude = $bookingLocation->getMeta( 'geo_longitude' ); + + // create immutable DateTime objects from Mutable (recommended by iCal library developer) + $booking_startDateDateTime = DateTimeImmutable::createFromMutable( $booking->getUTCStartDateDateTime() ); + $booking_endDateDateTime = DateTimeImmutable::createFromMutable( $booking->getUTCEndDateDateTime() ); + + // Create timezone entity + $php_date_time_zone = wp_timezone(); + // will only get timezone object if current timezone has transitions that can be fetched + if ( $php_date_time_zone->getTransitions() ) { + $timezone = \Eluceo\iCal\Domain\Entity\TimeZone::createFromPhpDateTimeZone( + $php_date_time_zone, + $booking_startDateDateTime, + $booking_endDateDateTime + ); + if ( empty( $this->calendar->getTimeZones() ) ) { + $this->calendar->addTimeZone( $timezone ); + } + } + + // Create event occurrence + if ( $booking->isFullDay() ) { + if ( $booking_startDateDateTime->format( 'Y-m-d' ) == $booking_endDateDateTime->format( 'Y-m-d' ) ) { // is single day event + $occurrence = new SingleDay( + new Date( $booking_startDateDateTime ) + ); + } else { // is multi day event + $occurrence = new MultiDay( + new Date( $booking_startDateDateTime ), + new Date( $booking_endDateDateTime ) ); - if (empty($this->calendar->getTimeZones())){ - $this->calendar->addTimeZone($timezone); - } } + } else { // is timespan - //Create event occurrence - if ($booking->isFullDay()){ - if ($booking_startDateDateTime->format('Y-m-d') == $booking_endDateDateTime->format('Y-m-d') ) { //is single day event - $occurrence = new SingleDay( - new Date( $booking_startDateDateTime ) - ); - } - else { //is multi day event - $occurrence = new MultiDay( - new Date( $booking_startDateDateTime ), - new Date( $booking_endDateDateTime ) - ); - } - } - else { //is timespan - - //add one minute to EndDate (this minute was removed to prevent overlapping but would confuse users) - $booking_endDateDateTime = $booking_endDateDateTime->add(new DateInterval('PT1M')); - - $occurrence = new TimeSpan( - new \Eluceo\iCal\Domain\ValueObject\DateTime($booking_startDateDateTime, true), - new \Eluceo\iCal\Domain\ValueObject\DateTime($booking_endDateDateTime, true) - ); - } + // add one minute to EndDate (this minute was removed to prevent overlapping but would confuse users) + $booking_endDateDateTime = $booking_endDateDateTime->add( new DateInterval( 'PT1M' ) ); + + $occurrence = new TimeSpan( + new \Eluceo\iCal\Domain\ValueObject\DateTime( $booking_startDateDateTime, true ), + new \Eluceo\iCal\Domain\ValueObject\DateTime( $booking_endDateDateTime, true ) + ); + } $eventStatus = EventStatus::CONFIRMED(); - if ($booking->isCancelled()) { - $eventStatus = EventStatus::CANCELLED(); - } + if ( $booking->isCancelled() ) { + $eventStatus = EventStatus::CANCELLED(); + } // Create unique identifier - $uniqueIdentifier = new UniqueIdentifier($booking->post_name); - // Create Event domain entity. - $event = new Event($uniqueIdentifier); - $event - ->setSummary($eventTitle) - ->setDescription($eventDescription) - ->setOccurrence($occurrence) - ->setStatus($eventStatus) - ->touch(new Timestamp()) - ; - - //Add location to domain entity - - $location_address = $bookingLocation->formattedAddressOneLine(); - if (!empty($location_address)){ - $event->setLocation( - ( - new Location( $location_address, $bookingLocation->post_title)) - ->withGeographicPosition( - new GeographicPosition( - floatval( $bookingLocation_latitude ), - floatval( $bookingLocation_longitude ) - ) + $uniqueIdentifier = new UniqueIdentifier( $booking->post_name ); + // Create Event domain entity. + $event = new Event( $uniqueIdentifier ); + $event + ->setSummary( $eventTitle ) + ->setDescription( $eventDescription ) + ->setOccurrence( $occurrence ) + ->setStatus( $eventStatus ) + ->touch( new Timestamp() ); + + // Add location to domain entity + + $location_address = $bookingLocation->formattedAddressOneLine(); + if ( ! empty( $location_address ) ) { + $event->setLocation( + ( + new Location( $location_address, $bookingLocation->post_title ) ) + ->withGeographicPosition( + new GeographicPosition( + floatval( $bookingLocation_latitude ), + floatval( $bookingLocation_longitude ) ) - ); - } + ) + ); + } - $this->calendar->addEvent($event); - } + $this->calendar->addEvent( $event ); + } /** * Will get the string representation of the current calendar. @@ -230,29 +237,30 @@ public function addBookingEvent( * * @return String - The string representation of the calendar */ - public function getCalendarData (): String { - // Transform domain entity into an iCalendar component - $componentFactory = new CalendarFactory(); - $calendarComponent = $componentFactory->createCalendar($this->calendar); + public function getCalendarData(): string { + // Transform domain entity into an iCalendar component + $componentFactory = new CalendarFactory(); + $calendarComponent = $componentFactory->createCalendar( $this->calendar ); return $calendarComponent->__toString(); - } + } /** * Adds a generic event to Calendar * * @param array|DateTimeImmutable $eventDate - * @param string $eventTitle - * @param string $eventDescription - * @param bool $isTimeSpan + * @param string $eventTitle + * @param string $eventDescription + * @param bool $isTimeSpan * * @return Event|false */ public function addEvent( $eventDate, - String $eventTitle, - String $eventDescription, - bool $isTimeSpan=false):Event { + string $eventTitle, + string $eventDescription, + bool $isTimeSpan = false + ): Event { if ( is_array( $eventDate ) ) { if ( count( $eventDate ) < 2 || ! ( $eventDate[0] instanceof DateTimeImmutable ) || ! ( $eventDate[1] instanceof DateTimeImmutable ) || $eventDate[0] > $eventDate[1] ) { @@ -276,7 +284,6 @@ public function addEvent( ->setDescription( $eventDescription ) ->setOccurrence( $occurence ); - $this->calendar->addEvent( $event ); return $event; @@ -296,33 +303,25 @@ public function addEvent( */ public static function getICSDownload() { - $user_id = intval($_GET[self::QUERY_USER]); - $user_hash = strval($_GET[self::QUERY_USERHASH]); + $user_id = intval( $_GET[ self::QUERY_USER ] ); + $user_hash = strval( $_GET[ self::QUERY_USERHASH ] ); - if (commonsbooking_isUIDHashComboCorrect($user_id,$user_hash)){ - - $bookingiCal = \CommonsBooking\View\Booking::getBookingListiCal($user_id); - if ($bookingiCal) { - header('Content-Type: text/calendar; charset=utf-8'); - header('Content-Disposition: attachment; filename="ical.ics"'); + if ( commonsbooking_isUIDHashComboCorrect( $user_id, $user_hash ) ) { + $bookingiCal = \CommonsBooking\View\Booking::getBookingListiCal( $user_id ); + if ( $bookingiCal ) { + header( 'Content-Type: text/calendar; charset=utf-8' ); + header( 'Content-Disposition: attachment; filename="ical.ics"' ); echo $bookingiCal; - die(); - } - else { - die("Error in retrieving booking list."); - } - - } - else { - if (!$user_id){ - die("user id missing"); - } - elseif (!$user_hash){ - die("user hash missing"); - } - else { - die("user_id and user_hash mismatch. Authentication failed."); + die(); + } else { + die( 'Error in retrieving booking list.' ); } + } elseif ( ! $user_id ) { + die( 'user id missing' ); + } elseif ( ! $user_hash ) { + die( 'user hash missing' ); + } else { + die( 'user_id and user_hash mismatch. Authentication failed.' ); } } -} \ No newline at end of file +} diff --git a/src/Settings/Settings.php b/src/Settings/Settings.php index 7618ce15a..0810228b1 100644 --- a/src/Settings/Settings.php +++ b/src/Settings/Settings.php @@ -22,9 +22,9 @@ class Settings { * * @param mixed $options_key * @param mixed $field_id - * @param mixed $sanitizeFunction Optional. Function to sanitize return value. If an array, each element - * is sanitized recursively. Use false to not sanitize. - * Default: 'commonsbooking_sanitizeHTML'. + * @param mixed $sanitizeFunction Optional. Function to sanitize return value. If an array, each element + * is sanitized recursively. Use false to not sanitize. + * Default: 'commonsbooking_sanitizeHTML'. * * @return mixed */ @@ -41,7 +41,6 @@ public static function getOption( $options_key, $field_id, $sanitizeFunction = ' } else { return false; } - } @@ -49,7 +48,6 @@ public static function getOption( $options_key, $field_id, $sanitizeFunction = ' * Updates a single field in a multidimensional options-array in wp_options * Will create the option if it does not exist yet. * - * * @param mixed $option_name the options name as defined in wp_options table, column option_name * @param mixed $field_id the field_id in the array * @param mixed $field_value the new value @@ -60,8 +58,8 @@ public static function updateOption( $option_name, $field_id, $field_value ) { // Load all the option values from wp_options $options = get_option( $option_name ); - //if the option does not exist, we need to create an empty - //array instead because we cannot convert false to an array + // if the option does not exist, we need to create an empty + // array instead because we cannot convert false to an array if ( $options === false ) { $options = array(); } @@ -71,15 +69,14 @@ public static function updateOption( $option_name, $field_id, $field_value ) { // Save to wp_options return update_option( $option_name, $options ); - } public static function returnFormattedMetaboxFields( $postType ) { - $metabox_array = Settings::getOption('commonsbooking_settings_metaboxfields', $postType); + $metabox_array = self::getOption( 'commonsbooking_settings_metaboxfields', $postType ); - $result = "
        "; - if(is_array($metabox_array)) { + $result = '
        '; + if ( is_array( $metabox_array ) ) { foreach ( $metabox_array as $metabox_id => $metabox_name ) { $result .= $metabox_name . ' => [' . $metabox_id . ']
        '; } @@ -87,5 +84,4 @@ public static function returnFormattedMetaboxFields( $postType ) { return $result; } - } diff --git a/src/View/Admin/Filter.php b/src/View/Admin/Filter.php index 547987549..7b03abe61 100644 --- a/src/View/Admin/Filter.php +++ b/src/View/Admin/Filter.php @@ -13,16 +13,15 @@ class Filter { * @param $values */ public static function renderFilter( $postType, $label, $key, $values ) { - //only add filter to post type you want + // only add filter to post type you want if ( isset( $_GET['post_type'] ) && $postType == $_GET['post_type'] ) { ?> - + $label ) { - printf - ( + printf( '', $value, $value == $filterValue ? ' selected="selected"' : '', @@ -30,13 +29,14 @@ public static function renderFilter( $postType, $label, $key, $values ) { ); } ?> - + + 'End date', + 'commonsbooking' + ) . '" value="' . esc_attr( $to ) . '" /> '; } } - } \ No newline at end of file diff --git a/src/View/Booking.php b/src/View/Booking.php index de9fa6104..c1af07f15 100755 --- a/src/View/Booking.php +++ b/src/View/Booking.php @@ -2,7 +2,6 @@ namespace CommonsBooking\View; - use CommonsBooking\CB\CB; use CommonsBooking\Repository\Timeframe; use Exception; @@ -31,16 +30,16 @@ public static function getTemplateData(): void { } /** - * @param int $postsPerPage + * @param int $postsPerPage * @param \WP_User|null $user * * @return array|false|mixed * @throws Exception */ - public static function getBookingListData( int $postsPerPage = 6, \WP_User $user = null) { + public static function getBookingListData( int $postsPerPage = 6, \WP_User $user = null ) { - //sets selected user to current user when no specific user is passed - if ($user == null) { + // sets selected user to current user when no specific user is passed + if ( $user == null ) { $user = wp_get_current_user(); } @@ -80,7 +79,7 @@ public static function getBookingListData( int $postsPerPage = 6, \WP_User $user 'user' => false, 'startDate' => time(), 'endDate' => false, - 'status' => false + 'status' => false, ]; foreach ( $filters as $key => $value ) { @@ -107,7 +106,7 @@ public static function getBookingListData( int $postsPerPage = 6, \WP_User $user 'user' => [], 'item' => [], 'location' => [], - 'status' => [] + 'status' => [], ]; $posts = \CommonsBooking\Repository\Booking::getForUser( @@ -120,10 +119,10 @@ public static function getBookingListData( int $postsPerPage = 6, \WP_User $user // Because upon initial load the form stays empty when we just have bookings in the past // With an empty form, the user can't change the start date so we look for bookings in the past if ( ! $startDateDefined ) { - //Don't fetch all bookings so that admins are not overwhelmed with all bookings of all time - for ( $year = 1; $year <= 3; $year++) { + // Don't fetch all bookings so that admins are not overwhelmed with all bookings of all time + for ( $year = 1; $year <= 3; $year++ ) { $currentTime = strtotime( '-' . $year . ' year' ); - $posts = \CommonsBooking\Repository\Booking::getForUser( + $posts = \CommonsBooking\Repository\Booking::getForUser( $user, true, $currentTime @@ -136,8 +135,7 @@ public static function getBookingListData( int $postsPerPage = 6, \WP_User $user if ( ! $posts ) { return false; } - } - else { + } else { return false; } } @@ -153,17 +151,16 @@ public static function getBookingListData( int $postsPerPage = 6, \WP_User $user $editLink = get_permalink( $booking->ID ); $actions = '' . - commonsbooking_sanitizeHTML( __( 'Details', 'commonsbooking' ) ) . - ''; + commonsbooking_sanitizeHTML( __( 'Details', 'commonsbooking' ) ) . + ''; $menuitems = ''; - if (Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_advanced-options', 'feed_enabled' ) == 'on'){ - $menuitems .= '

        {$field->args['msg_next_email']} {$nextCronEventFmt}

        HTML; + } - } - - /** + /** * renders CMB2 field row * - * @param array $field_args Array of field arguments. - * @param CMB2_Field $field The field object - */ - public static function renderDirectEmailRow( $field_args, $field) { + * @param array $field_args Array of field arguments. + * @param CMB2_Field $field The field object + */ + public static function renderDirectEmailRow( $field_args, $field ) { - $timeframeId=$field->object_id(); - $timeframe=new Timeframe($timeframeId); + $timeframeId = $field->object_id(); + $timeframe = new Timeframe( $timeframeId ); - $location=$timeframe->getLocation(); - $location_emails = $location? - CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email', $timeframe->getLocation() ): - array() ; + $location = $timeframe->getLocation(); + $location_emails = $location ? + CB::get( \CommonsBooking\Wordpress\CustomPostType\Location::$postType, COMMONSBOOKING_METABOX_PREFIX . 'location_email', $timeframe->getLocation() ) : + array(); - echo '
        + echo '
        - +
        '; - if(empty($location)) { - echo commonsbooking_sanitizeHTML( __('No location configured for this timeframe', 'commonsbooking')); - } - elseif( empty($location_emails)) { - echo commonsbooking_sanitizeHTML( __('Unable to send Emails. No location email configured, check location', 'commonsbooking') . - sprintf( ' %s', esc_url(get_edit_post_link( $location->ID )), commonsbooking_sanitizeHTML($location->post_title) )); - } - elseif( !$timeframe->hasBookingCodes()){ - echo commonsbooking_sanitizeHTML( __('This timeframe has no booking codes. To generate booking codes you need to save the timeframe.', 'commonsbooking')); - } - else - { - echo ' + if ( empty( $location ) ) { + echo commonsbooking_sanitizeHTML( __( 'No location configured for this timeframe', 'commonsbooking' ) ); + } elseif ( empty( $location_emails ) ) { + echo commonsbooking_sanitizeHTML( + __( 'Unable to send Emails. No location email configured, check location', 'commonsbooking' ) . + sprintf( ' %s', esc_url( get_edit_post_link( $location->ID ) ), commonsbooking_sanitizeHTML( $location->post_title ) ) + ); + } elseif ( ! $timeframe->hasBookingCodes() ) { + echo commonsbooking_sanitizeHTML( __( 'This timeframe has no booking codes. To generate booking codes you need to save the timeframe.', 'commonsbooking' ) ); + } else { + echo ' '; + ' . commonsbooking_sanitizeHTML( __( 'All codes for the entire timeframe will be emailed to the location email(s), given in bold below.', 'commonsbooking' ) ) + . '
        '; - $from=strtotime("midnight first day of this month"); - $to=strtotime("midnight last day of this month"); - echo ' + $from = strtotime( 'midnight first day of this month' ); + $to = strtotime( 'midnight last day of this month' ); + echo ' '; - $from=strtotime("midnight first day of next month"); - $to=strtotime("midnight last day of next month"); + ' . commonsbooking_sanitizeHTML( __( 'The codes of the current month will be sent to all the location email(s), given in bold below', 'commonsbooking' ) ) + . '
        '; + $from = strtotime( 'midnight first day of next month' ); + $to = strtotime( 'midnight last day of next month' ); - echo ' + echo '

        "cb_email-bookingcodes", "from" => $from, "to" =>$to, "redir" => rawurlencode(add_query_arg([])) ])) . '" > - '. commonsbooking_sanitizeHTML( __('Email booking codes of next month', 'commonsbooking')) .' + href="' . esc_url( + add_query_arg( + [ + 'action' => 'cb_email-bookingcodes', + 'from' => $from, + 'to' => $to, + 'redir' => rawurlencode( add_query_arg( [] ) ), + ] + ) + ) . '" > + ' . commonsbooking_sanitizeHTML( __( 'Email booking codes of next month', 'commonsbooking' ) ) . '
        - '. commonsbooking_sanitizeHTML( __('The codes of the next month will be sent to all the location email(s), given in bold below.', 'commonsbooking')) . - '

        -
        '. commonsbooking_sanitizeHTML( __('Currently configured location email(s): ', 'commonsbooking')) .'' . $location_emails . '
        ' - . '

        -
        '. commonsbooking_sanitizeHTML(__('IMPORTANT: You need to save the timeframe before you can send out the booking codes.')) .'
        ' - . '
        ' - ; - - $lastBookingEmail=get_post_meta( $timeframeId, \CommonsBooking\View\BookingCodes::LAST_CODES_EMAIL, true); - if(!empty($lastBookingEmail)) { - echo '

        ' - . commonsbooking_sanitizeHTML( __('Last booking codes email sent:', 'commonsbooking')) . ' ' - . wp_date(get_option( 'date_format' ) . ' ' . get_option( 'time_format' ),$lastBookingEmail) . '

        '; - } - } - - echo ' + ' . commonsbooking_sanitizeHTML( __( 'The codes of the next month will be sent to all the location email(s), given in bold below.', 'commonsbooking' ) ) . + '

        +
        ' . commonsbooking_sanitizeHTML( __( 'Currently configured location email(s): ', 'commonsbooking' ) ) . '' . $location_emails . '
        ' + . '

        +
        ' . commonsbooking_sanitizeHTML( __( 'IMPORTANT: You need to save the timeframe before you can send out the booking codes.' ) ) . '
        ' + . '
        '; + + $lastBookingEmail = get_post_meta( $timeframeId, self::LAST_CODES_EMAIL, true ); + if ( ! empty( $lastBookingEmail ) ) { + echo '

        ' + . commonsbooking_sanitizeHTML( __( 'Last booking codes email sent:', 'commonsbooking' ) ) . ' ' + . wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $lastBookingEmail ) . '

        '; + } + } + + echo '
        '; - return true; - } + return true; + } /** * Renders table of booking codes. @@ -342,89 +375,94 @@ public static function renderDirectEmailRow( $field_args, $field) { * @param $timeframeId */ public static function renderTable( $timeframeId ) { - try { - $timeframe=new Timeframe($timeframeId);} catch ( BookingCodeException $e ) { + try { + $timeframe = new Timeframe( $timeframeId );} catch ( BookingCodeException $e ) { echo $e->getMessage(); return; - } + } - echo ' + echo '
        -
        ' . ($timeframe->hasBookingCodes()?' - "cb_download-bookingscodes-csv", ])) . '" target="_blank">Download booking codes +
        ' . ( $timeframe->hasBookingCodes() ? ' + Download booking codes

        ' . commonsbooking_sanitizeHTML( sprintf( __( 'Will download all available booking codes for this timeframe. If the timeframe has no end-date, the booking codes for the next %s days will be retrieved.', 'commonsbooking' ), \CommonsBooking\Repository\BookingCodes::ADVANCE_GENERATION_DAYS ) ) . '
        ' . commonsbooking_sanitizeHTML( __( 'The file will be exported as tab delimited .txt file so you can choose wether you want to print it, open it in a separate application (like Word, Excel etc.)', 'commonsbooking' ) ) . ' -

        ':commonsbooking_sanitizeHTML( __('This timeframe has no booking codes. To generate booking codes you need to save the timeframe.', 'commonsbooking'))) . ' +

        ' : commonsbooking_sanitizeHTML( __( 'This timeframe has no booking codes. To generate booking codes you need to save the timeframe.', 'commonsbooking' ) ) ) . '
        '; - //This settings is the amount of booking codes that should be shown to the user - $bcToShow=Settings::getOption( 'commonsbooking_options_bookingcodes','bookingcodes-listed-timeframe' ); - if($bcToShow > 0) { - $tsStart=max(Wordpress::getUTCDateTime("today")->getTimestamp(), $timeframe->getStartDate()); - $tsEnd=strtotime(" +" . ( $bcToShow - 1 ) . " days",$tsStart); - $bookingCodes = \CommonsBooking\Repository\BookingCodes::getCodes( $timeframeId,$tsStart,$tsEnd); + // This settings is the amount of booking codes that should be shown to the user + $bcToShow = Settings::getOption( 'commonsbooking_options_bookingcodes', 'bookingcodes-listed-timeframe' ); + if ( $bcToShow > 0 ) { + $tsStart = max( Wordpress::getUTCDateTime( 'today' )->getTimestamp(), $timeframe->getStartDate() ); + $tsEnd = strtotime( ' +' . ( $bcToShow - 1 ) . ' days', $tsStart ); + $bookingCodes = \CommonsBooking\Repository\BookingCodes::getCodes( $timeframeId, $tsStart, $tsEnd ); - echo '
        + echo '
        '; - if($timeframe->hasBookingCodes()) { - echo apply_filters('commonsbooking_emailcodes_rendertable', - self::renderBookingCodesTable($bookingCodes),$bookingCodes,'timeframe_form'); + if ( $timeframe->hasBookingCodes() ) { + echo apply_filters( + 'commonsbooking_emailcodes_rendertable', + self::renderBookingCodesTable( $bookingCodes ), + $bookingCodes, + 'timeframe_form' + ); echo '
        '; echo '

        '; - echo sprintf( __('Only showing booking codes for the next %s days.', 'commonsbooking'), $bcToShow ); + printf( __( 'Only showing booking codes for the next %s days.', 'commonsbooking' ), $bcToShow ); echo '
        '; - echo __('The amount of booking codes shown in the overview can be changed in the settings.', 'commonsbooking'); + echo __( 'The amount of booking codes shown in the overview can be changed in the settings.', 'commonsbooking' ); echo '

        '; - } - else { - echo commonsbooking_sanitizeHTML( __('This timeframe has no booking codes. To generate booking codes you need to save the timeframe.', 'commonsbooking')); - } - echo '
        '; - } - - return true; + } else { + echo commonsbooking_sanitizeHTML( __( 'This timeframe has no booking codes. To generate booking codes you need to save the timeframe.', 'commonsbooking' ) ); + } + echo '
        '; + } + + return true; } /** * Renders HTML table of bookingCodes List. * * @param $bookingCodes array : CommonsBooking\Model\BookingCode - * - * @return string HTML table + * + * @return string HTML table */ - public static function renderBookingCodesTable( $bookingCodes ) : string { - if(empty($bookingCodes)) return ''; - - $lines=[]; - foreach($bookingCodes as $bookingCode) { - $lines[]='' . commonsbooking_sanitizeHTML(wp_date("D j. F Y", strtotime ($bookingCode->getDate() )) ) . - '' . commonsbooking_sanitizeHTML( $bookingCode->getCode() ) . ''; - } + public static function renderBookingCodesTable( $bookingCodes ): string { + if ( empty( $bookingCodes ) ) { + return ''; + } - // if odd number of lines add empty row - if(count($lines) % 2 != 0) { - array_push($lines,"  "); - } - $parts=array_chunk($lines,ceil(count($lines) / 2)); + $lines = []; + foreach ( $bookingCodes as $bookingCode ) { + $lines[] = '' . commonsbooking_sanitizeHTML( wp_date( 'D j. F Y', strtotime( $bookingCode->getDate() ) ) ) . + '' . commonsbooking_sanitizeHTML( $bookingCode->getCode() ) . ''; + } - return "
        " . - implode("",$parts[0]) . - "
        " . - implode("",$parts[1]) . - "
        "; + // if odd number of lines add empty row + if ( count( $lines ) % 2 != 0 ) { + array_push( $lines, '  ' ); + } + $parts = array_chunk( $lines, ceil( count( $lines ) / 2 ) ); - } + return "
        " . + implode( '', $parts[0] ) . + "
        " . + implode( '', $parts[1] ) . + '
        '; + } /** * Renders CVS file (txt-format) with booking codes for download + * * @param $timeframeId */ public static function renderCSV( $timeframeId = null ) { @@ -433,10 +471,10 @@ public static function renderCSV( $timeframeId = null ) { } header( 'Content-Encoding: UTF-8' ); header( 'Content-type: text/csv; charset=UTF-8' ); - header( "Content-Disposition: attachment; filename=buchungscode-" . commonsbooking_sanitizeHTML( $timeframeId ) . ".txt" ); + header( 'Content-Disposition: attachment; filename=buchungscode-' . commonsbooking_sanitizeHTML( $timeframeId ) . '.txt' ); header( 'Content-Transfer-Encoding: binary' ); - header( "Pragma: no-cache" ); - header( "Expires: 0" ); + header( 'Pragma: no-cache' ); + header( 'Expires: 0' ); echo "\xEF\xBB\xBF"; // UTF-8 BOM try { @@ -448,74 +486,75 @@ public static function renderCSV( $timeframeId = null ) { foreach ( $bookingCodes as $bookingCode ) { echo commonsbooking_sanitizeHTML( $bookingCode->getDate() ) . - "\t" . commonsbooking_sanitizeHTML( $bookingCode->getItemName() ) . - "\t" . commonsbooking_sanitizeHTML( $bookingCode->getCode() ) . "\n"; + "\t" . commonsbooking_sanitizeHTML( $bookingCode->getItemName() ) . + "\t" . commonsbooking_sanitizeHTML( $bookingCode->getCode() ) . "\n"; } die; } - /** - * action for sending Booking Codes by E-mail - * - * @param int $timeframeId ID of requested timeframe - * @param int $tsFrom Timestamp of first Booking Code - * @param int $tsTo Timestamp of last Booking Code - */ - public static function emailCodes($timeframeId = null, $tsFrom=null, $tsTo=null) { - - if($timeframeId == null) { - $timeframeId = empty($_GET['post']) ? null : sanitize_text_field( $_GET['post'] ); - } - - - if(empty($timeframeId)) { - wp_die( - commonsbooking_sanitizeHTML( __( "Unable to retrieve booking codes", "commonsbooking" ) ), - commonsbooking_sanitizeHTML( __( "Missing ID of timeframe post", "commonsbooking" ) ), - [ 'back_link' => true ] - ); - } - - if($tsFrom == null) { - $tsFrom = empty($_GET['from']) ? null : absint( $_GET['from'] ); - } - if($tsTo == null) { - $tsTo = empty($_GET['to']) ? null : absint( $_GET['to'] ); - } - - - add_action( 'commonsbooking_mail_sent',function($action,$result) use ($timeframeId){ - $redir=empty($_GET['redir'])?add_query_arg([ "post" => $timeframeId, "action" => "edit"],admin_url('post.php')):$_GET['redir']; - - if(is_wp_error($result)) - { - set_transient(BookingCode::ERROR_TYPE,$result->get_error_message()); - } - elseif($result === false) - { - set_transient(BookingCode::ERROR_TYPE,__( "Error sending booking codes", "commonsbooking" )); - } - else - { - // $redir=add_query_arg([ 'cmb2_bookingcodes_result' => 'success' ],$redir); - $redir=explode('#',$redir)[0] . '#email-booking-codes-list'; - } - - wp_safe_redirect($redir); - exit; - - } - , 10, 2 ); - - $booking_msg = new BookingCodesMessage($timeframeId, "codes",$tsFrom,$tsTo ); - $booking_msg->sendMessage(); - - //this should never happen - wp_die( - commonsbooking_sanitizeHTML( __( "An unknown error occured", "commonsbooking" ) ), - commonsbooking_sanitizeHTML( __( "Email booking codes", "commonsbooking" ) ), - [ 'back_link' => true ] - ); - - } + /** + * action for sending Booking Codes by E-mail + * + * @param int $timeframeId ID of requested timeframe + * @param int $tsFrom Timestamp of first Booking Code + * @param int $tsTo Timestamp of last Booking Code + */ + public static function emailCodes( $timeframeId = null, $tsFrom = null, $tsTo = null ) { + + if ( $timeframeId == null ) { + $timeframeId = empty( $_GET['post'] ) ? null : sanitize_text_field( $_GET['post'] ); + } + + if ( empty( $timeframeId ) ) { + wp_die( + commonsbooking_sanitizeHTML( __( 'Unable to retrieve booking codes', 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( __( 'Missing ID of timeframe post', 'commonsbooking' ) ), + [ 'back_link' => true ] + ); + } + + if ( $tsFrom == null ) { + $tsFrom = empty( $_GET['from'] ) ? null : absint( $_GET['from'] ); + } + if ( $tsTo == null ) { + $tsTo = empty( $_GET['to'] ) ? null : absint( $_GET['to'] ); + } + + add_action( + 'commonsbooking_mail_sent', + function ( $action, $result ) use ( $timeframeId ) { + $redir = empty( $_GET['redir'] ) ? add_query_arg( + [ + 'post' => $timeframeId, + 'action' => 'edit', + ], + admin_url( 'post.php' ) + ) : $_GET['redir']; + + if ( is_wp_error( $result ) ) { + set_transient( BookingCode::ERROR_TYPE, $result->get_error_message() ); + } elseif ( $result === false ) { + set_transient( BookingCode::ERROR_TYPE, __( 'Error sending booking codes', 'commonsbooking' ) ); + } else { + // $redir=add_query_arg([ 'cmb2_bookingcodes_result' => 'success' ],$redir); + $redir = explode( '#', $redir )[0] . '#email-booking-codes-list'; + } + + wp_safe_redirect( $redir ); + exit; + }, + 10, + 2 + ); + + $booking_msg = new BookingCodesMessage( $timeframeId, 'codes', $tsFrom, $tsTo ); + $booking_msg->sendMessage(); + + // this should never happen + wp_die( + commonsbooking_sanitizeHTML( __( 'An unknown error occured', 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( __( 'Email booking codes', 'commonsbooking' ) ), + [ 'back_link' => true ] + ); + } } diff --git a/src/View/Calendar.php b/src/View/Calendar.php index 391af8a92..33ef8f94d 100644 --- a/src/View/Calendar.php +++ b/src/View/Calendar.php @@ -37,10 +37,10 @@ class Calendar { * Forked from https://github.com/flotte-berlin/cb-shortcodes/blob/master/custom-shortcodes-cb-items.php * * @param $atts array Supports the following attributes: - * - locationcat: Filter by location category - * - itemcat: Filter by item category - * - days: Number of days to show in calendar table view - * - desc: Description text + * - locationcat: Filter by location category + * - itemcat: Filter by item category + * - days: Number of days to show in calendar table view + * - desc: Description text * * @return string * @throws Exception @@ -69,8 +69,8 @@ public static function renderTable( $atts ): string { $month_cols = [ $month => 0 ]; $days_dates = []; - for ( $i = 0; $i < $days; $i ++ ) { - $month_cols[ $month ] ++; + for ( $i = 0; $i < $days; $i++ ) { + ++$month_cols[ $month ]; $days_display[ $i ] = $date->format( 'd' ); $days_dates[ $i ] = $date->format( 'Y-m-d' ); @@ -90,8 +90,8 @@ public static function renderTable( $atts ): string { $print = '
        '; $print .= "" . $colStr . ''; // Use td-tag when no table header description is given, to match semantics of header cells - $accessible_table_header_tag = empty($desc) ? "td" : "th"; - $print .= "<$accessible_table_header_tag colspan='2' class='sortless'>" . $desc . ""; + $accessible_table_header_tag = empty( $desc ) ? 'td' : 'th'; + $print .= "<$accessible_table_header_tag colspan='2' class='sortless'>" . $desc . ""; // Render months $print .= self::renderHeadlineMonths( $month_cols ); @@ -100,7 +100,7 @@ public static function renderTable( $atts ): string { // Render Headline Days $print .= ''; $print .= self::renderHeadlineDays( $days_display ); - $print .= ''; + $print .= ''; $items = get_posts( array( @@ -145,7 +145,7 @@ public static function renderTable( $atts ): string { // loop through location foreach ( $locations as $locationId => $locationName ) { $customCacheKey = $item->ID . $locationId . $today; - $cacheItem = Plugin::getCacheItem( $customCacheKey ); + $cacheItem = Plugin::getCacheItem( $customCacheKey ); if ( $cacheItem ) { $rowHtml .= $cacheItem; } else { @@ -174,7 +174,7 @@ public static function renderTable( $atts ): string { $print .= '
        '; $print .= '
        '; - return $print; + return $print; } public static function shortcode( $atts ) { @@ -201,7 +201,7 @@ protected static function renderHeadlineMonths( $month_cols ): string { foreach ( $month_cols as $month => $colspan ) { $print .= ""; - if ( $colspan > 3 ) { + if ( $colspan > 3 ) { $print .= date_i18n( 'F', strtotime( get_date_from_gmt( $month ) ) ) . ''; } else { $print .= date_i18n( 'M', strtotime( get_date_from_gmt( $month ) ) ) . ''; @@ -223,7 +223,7 @@ protected static function renderHeadlineDays( $days_display ): string { $dayStr = implode( $divider, $days_display ); return '' . __( 'Item', 'commonsbooking' ) . '' . - '' . __( 'Location', 'commonsbooking' ) . "" . $dayStr . ''; + '' . __( 'Location', 'commonsbooking' ) . "" . $dayStr . ''; } /** @@ -257,7 +257,7 @@ protected static function renderItemLocationRow( $item, $locationId, $locationNa true ); - $gotStartDate = false; + $gotStartDate = false; $gotEndDate = false; $dayIterator = 0; foreach ( $calendarData['days'] as $day => $data ) { @@ -279,33 +279,33 @@ protected static function renderItemLocationRow( $item, $locationId, $locationNa $gotEndDate = true; } - // Check day state + // Check day state if ( ! count( $data['slots'] ) ) { - $days_display[ $dayIterator ++ ] = ""; + $days_display[ $dayIterator++ ] = ""; } elseif ( $data['holiday'] ) { - $days_display[ $dayIterator ++ ] = ""; + $days_display[ $dayIterator++ ] = ""; } elseif ( $data['locked'] && $data['firstSlotBooked'] && $data['lastSlotBooked'] ) { - $days_display[ $dayIterator ++ ] = ""; + $days_display[ $dayIterator++ ] = ""; } elseif ( $data['locked'] && $data['partiallyBookedDay'] ) { $cssClass = 'is-partially-booked-end'; if ( ! $data['firstSlotBooked'] && $data['lastSlotBooked'] ) { $cssClass = 'is-partially-booked-start'; } - $days_display[ $dayIterator ++ ] = ""; + $days_display[ $dayIterator++ ] = ""; } elseif ( $data['locked'] ) { - $days_display[ $dayIterator ++ ] = ""; - } else { - $days_display[ $dayIterator ++ ] = ''; + $days_display[ $dayIterator++ ] = ""; + } else { + $days_display[ $dayIterator++ ] = ''; } - // Stop when enddate (advanced booking days limit) is reached + // Stop when enddate (advanced booking days limit) is reached if ( $day == $calendarData['endDate'] ) { break; } - } + } // Show item as not available outside of timeframe timerange. - for ( $dayIterator; $dayIterator < count( $days_display ); $dayIterator ++ ) { + for ( $dayIterator; $dayIterator < count( $days_display ); $dayIterator++ ) { $days_display[ $dayIterator ] = ""; } @@ -373,7 +373,7 @@ public static function getCalendarDataArray( $item, $location, string $startDate // Check if start-/enddate was requested, then don't change it // otherwise start with current day $startDateTimestamp = time(); - if ( $closestBookableTimeframe->getStartDate() > $startDateTimestamp ) { + if ( $closestBookableTimeframe->getStartDate() > $startDateTimestamp ) { $startDateTimestamp = $closestBookableTimeframe->getStartDate(); } @@ -412,50 +412,63 @@ public static function getCalendarDataArray( $item, $location, string $startDate public static function getClosestBookableTimeFrameForToday( $bookableTimeframes ): ?\CommonsBooking\Model\Timeframe { $today = new Day( date( 'Y-m-d' ) ); $todayTimeframes = \CommonsBooking\Repository\Timeframe::filterTimeframesForTimerange( $bookableTimeframes, $today->getStartTimestamp(), $today->getEndTimestamp() ); - $todayTimeframes = array_filter( $todayTimeframes, function ( $timeframe ) use ( $today ) { //also consider repetition - return $today->isInTimeframe( $timeframe ); - } ); + $todayTimeframes = array_filter( + $todayTimeframes, + function ( $timeframe ) use ( $today ) { + // also consider repetition + return $today->isInTimeframe( $timeframe ); + } + ); switch ( count( $todayTimeframes ) ) { case 1: $bookableTimeframes = $todayTimeframes; break; case 0: - usort( $bookableTimeframes, function ( $a, $b ) { - $aStartDate = $a->getStartDate(); - $bStartDate = $b->getStartDate(); + usort( + $bookableTimeframes, + function ( $a, $b ) { + $aStartDate = $a->getStartDate(); + $bStartDate = $b->getStartDate(); - if ( $aStartDate == $bStartDate ) { - $aStartTimeDT = $a->getStartTimeDateTime(); - $bStartTimeDT = $b->getStartTimeDateTime(); + if ( $aStartDate == $bStartDate ) { + $aStartTimeDT = $a->getStartTimeDateTime(); + $bStartTimeDT = $b->getStartTimeDateTime(); - return $bStartTimeDT <=> $aStartTimeDT; - } + return $bStartTimeDT <=> $aStartTimeDT; + } - return $bStartDate <=> $aStartDate; - } ); + return $bStartDate <=> $aStartDate; + } + ); break; - default: //More than one timeframe for current day + default: // More than one timeframe for current day // consider starttime and endtime - $now = new DateTime(); - $bookableTimeframes = array_filter( $todayTimeframes, function ( $timeframe ) use ( $now ) { - $startTime = $timeframe->getStartTime(); - $startTimeDT = new DateTime( $startTime ); - $endTime = $timeframe->getEndTime(); - $endTimeDT = new DateTime( $endTime ); - - return $startTimeDT <= $now && $now <= $endTimeDT; - } ); - - //condition, that we are not currently in a timeframe - // for example, we have two timeframes, one from 02:00pm to 04:00pm and one from 04:00pm to 06:00pm. + $now = new DateTime(); + $bookableTimeframes = array_filter( + $todayTimeframes, + function ( $timeframe ) use ( $now ) { + $startTime = $timeframe->getStartTime(); + $startTimeDT = new DateTime( $startTime ); + $endTime = $timeframe->getEndTime(); + $endTimeDT = new DateTime( $endTime ); + + return $startTimeDT <= $now && $now <= $endTimeDT; + } + ); + + // condition, that we are not currently in a timeframe + // for example, we have two timeframes, one from 02:00pm to 04:00pm and one from 04:00pm to 06:00pm. // it is currently 11:00am, so we should take the first timeframe if ( empty( $bookableTimeframes ) ) { - usort( $todayTimeframes, function ( $a, $b ) { - $aStartTimeDT = $a->getStartTimeDateTime(); - $bStartTimeDT = $b->getStartTimeDateTime(); + usort( + $todayTimeframes, + function ( $a, $b ) { + $aStartTimeDT = $a->getStartTimeDateTime(); + $bStartTimeDT = $b->getStartTimeDateTime(); - return $bStartTimeDT <=> $aStartTimeDT; - } ); + return $bStartTimeDT <=> $aStartTimeDT; + } + ); $bookableTimeframes = $todayTimeframes; } break; @@ -494,10 +507,10 @@ public static function prepareJsonResponse( array $items, $advanceBookingDays = null, $lastBookableDate = null, - $firstBookableDay = null + $firstBookableDay = null ): array { - $current_user = wp_get_current_user(); + $current_user = wp_get_current_user(); $customCacheKey = serialize( $current_user->roles ); // we calculate the max advance booking days here to prepare the notice string in calender json. @@ -539,10 +552,9 @@ public static function prepareJsonResponse( // are overbooking allowed in location options? $useGlobalSettings = get_post_meta( $locations[0], COMMONSBOOKING_METABOX_PREFIX . 'use_global_settings', true ) === 'on'; if ( $useGlobalSettings ) { - $allowLockedDaysInRange = Settings::getOption('commonsbooking_options_general', COMMONSBOOKING_METABOX_PREFIX . 'allow_lockdays_in_range'); - } - else { - $allowLockedDaysInRange = get_post_meta( + $allowLockedDaysInRange = Settings::getOption( 'commonsbooking_options_general', COMMONSBOOKING_METABOX_PREFIX . 'allow_lockdays_in_range' ); + } else { + $allowLockedDaysInRange = get_post_meta( $locations[0], COMMONSBOOKING_METABOX_PREFIX . 'allow_lockdays_in_range', true @@ -552,9 +564,8 @@ public static function prepareJsonResponse( // should overbooked non bookable days be counted into maxdays selection? if ( $useGlobalSettings ) { - $countLockedDaysInRange = Settings::getOption('commonsbooking_options_general', COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_in_range'); - } - else { + $countLockedDaysInRange = Settings::getOption( 'commonsbooking_options_general', COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_in_range' ); + } else { $countLockedDaysInRange = get_post_meta( $locations[0], COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_in_range', @@ -563,11 +574,10 @@ public static function prepareJsonResponse( } $jsonResponse['countLockDaysInRange'] = $countLockedDaysInRange === 'on'; - //if yes, what is the maximum amount of days they should count? + // if yes, what is the maximum amount of days they should count? if ( $useGlobalSettings ) { - $countLockdaysMaximum = Settings::getOption('commonsbooking_options_general', COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_maximum'); - } - else { + $countLockdaysMaximum = Settings::getOption( 'commonsbooking_options_general', COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_maximum' ); + } else { $countLockdaysMaximum = get_post_meta( $locations[0], COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_maximum', true ); } $jsonResponse['countLockDaysMaxDays'] = (int) $countLockdaysMaximum; @@ -591,7 +601,7 @@ public static function prepareJsonResponse( /** * Processes day for calendar view of json. * - * @param Day $day + * @param Day $day * @param $lastBookableDate * @param $endDate * @param $jsonResponse @@ -612,7 +622,7 @@ protected static function mapDay( $day, $lastBookableDate, $endDate, &$jsonRespo 'lastSlotBooked' => null, ]; - // If all slots are locked, day cannot be selected + // If all slots are locked, day cannot be selected $allLocked = true; // If no slots are existing, day shall be locked @@ -644,13 +654,12 @@ protected static function mapDay( $day, $lastBookableDate, $endDate, &$jsonRespo $dayArray = self::getLockedDayArray( $day ); } - // if day is before minium bookable offset, day is locked - // We need to add this here and in section predefined day types below too, because - // renderTable function uses only the days array to generate the calendar. - if ( $day->getFormattedDate( 'Y-m-d' ) < $firstBookableDay ) { - $dayArray['locked'] = true; - } - + // if day is before minium bookable offset, day is locked + // We need to add this here and in section predefined day types below too, because + // renderTable function uses only the days array to generate the calendar. + if ( $day->getFormattedDate( 'Y-m-d' ) < $firstBookableDay ) { + $dayArray['locked'] = true; + } // Add day to calendar data. $jsonResponse['days'][ $day->getFormattedDate( 'Y-m-d' ) ] = $dayArray; @@ -671,10 +680,10 @@ protected static function mapDay( $day, $lastBookableDate, $endDate, &$jsonRespo } } - // if day is before minium bookable offset, day is locked - if ( $day->getFormattedDate( 'Y-m-d' ) < $firstBookableDay ) { - $jsonResponse['lockDays'][] = $day->getFormattedDate( 'Y-m-d' ); - } + // if day is before minium bookable offset, day is locked + if ( $day->getFormattedDate( 'Y-m-d' ) < $firstBookableDay ) { + $jsonResponse['lockDays'][] = $day->getFormattedDate( 'Y-m-d' ); + } } /** @@ -742,14 +751,14 @@ protected static function processSlot( $slot, &$dayArray, &$jsonResponse, &$allL // Set partiallyBookedDay flag, if there is at least one slot that is not bookable if ( in_array( - $timeFrameType, - [ + $timeFrameType, + [ Timeframe::BOOKING_ID, Timeframe::HOLIDAYS_ID, Timeframe::REPAIR_ID, \CommonsBooking\Model\Restriction::TYPE_REPAIR, ] - ) ) { + ) ) { $dayArray['partiallyBookedDay'] = true; } @@ -785,7 +794,7 @@ protected static function getLockedDayArray( Day $day ): array { /** * Ajax request - Returns json-formatted calendardata. - * + * * @throws Exception */ public static function getCalendarData() { @@ -803,7 +812,7 @@ public static function getCalendarData() { // Ajax-Request param check if ( array_key_exists( 'sd', $_POST ) && Wordpress::isValidDateString( $_POST['sd'] ) ) { - $startDateString = sanitize_text_field( $_POST['sd'] ); + $startDateString = sanitize_text_field( $_POST['sd'] ); } else { throw new Exception( 'wrong or missing start date.' ); } @@ -820,5 +829,4 @@ public static function getCalendarData() { echo wp_json_encode( $jsonResponse ); wp_die(); // All ajax handlers die when finished } - } diff --git a/src/View/Dashboard.php b/src/View/Dashboard.php index 3e950ae37..e62e99441 100644 --- a/src/View/Dashboard.php +++ b/src/View/Dashboard.php @@ -15,6 +15,7 @@ public static function index() { /** * Renders list of beginngin bookings for today. + * * @return void * @throws \Exception */ @@ -23,23 +24,29 @@ public static function renderBeginningBookings() { // filter bookings to show only allowed bookings for current user role if ( $beginningBookings ) { - $beginningBookings = array_filter( $beginningBookings, function ( $beginningBooking ) { - return commonsbooking_isCurrentUserAllowedToEdit( $beginningBooking ); - } ); + $beginningBookings = array_filter( + $beginningBookings, + function ( $beginningBooking ) { + return commonsbooking_isCurrentUserAllowedToEdit( $beginningBooking ); + } + ); } if ( count( $beginningBookings ) > 0 ) { - usort( $beginningBookings, function ( $a, $b ) { - return strtotime( $a->getStartTime() ) <=> strtotime( $b->getStartTime() ); - } ); - $html = '
        '; + usort( + $beginningBookings, + function ( $a, $b ) { + return strtotime( $a->getStartTime() ) <=> strtotime( $b->getStartTime() ); + } + ); + $html = '
        '; $html .= ''; @@ -50,9 +57,10 @@ public static function renderBeginningBookings() { } } - + /** * Renders list of ending bookings for today. + * * @return void * @throws \Exception */ @@ -61,33 +69,38 @@ public static function renderEndingBookings() { // filter bookings to show only allowed bookings for current user role if ( $endingBookings ) { - $endingBookings = array_filter( $endingBookings, function ( $endingBooking ) { - return commonsbooking_isCurrentUserAllowedToEdit( $endingBooking ); - } ); + $endingBookings = array_filter( + $endingBookings, + function ( $endingBooking ) { + return commonsbooking_isCurrentUserAllowedToEdit( $endingBooking ); + } + ); } if ( count( $endingBookings ) ) { - usort( $endingBookings, function ( $a, $b ) { - return strtotime( $a->getEndTime() ) <=> strtotime( $b->getEndTime() ); - } ); - //return self::renderBookingsTable( $endingBookings, false); - $html = '
        '; + usort( + $endingBookings, + function ( $a, $b ) { + return strtotime( $a->getEndTime() ) <=> strtotime( $b->getEndTime() ); + } + ); + // return self::renderBookingsTable( $endingBookings, false); + $html = '
        '; $html .= ''; $html .= '
        '; - + return $html; } else { return false; } } - } diff --git a/src/View/Item.php b/src/View/Item.php index 3985056d0..65663cd18 100644 --- a/src/View/Item.php +++ b/src/View/Item.php @@ -21,17 +21,17 @@ public static function getTemplateData( WP_Post $post = null ) { if ( $post == null ) { global $post; } - $item = $post; - $location = get_query_var( 'cb-location' ) ?: false; - $customId = md5($item->ID . $location); + $item = $post; + $location = get_query_var( 'cb-location' ) ?: false; + $customId = md5( $item->ID . $location ); $cacheItem = Plugin::getCacheItem( $customId ); if ( $cacheItem ) { return $cacheItem; } else { - $locations = \CommonsBooking\Repository\Location::getByItem( $item->ID, true ); + $locations = \CommonsBooking\Repository\Location::getByItem( $item->ID, true ); $locationIds = array_map( - function (\CommonsBooking\Model\Location $location) { + function ( \CommonsBooking\Model\Location $location ) { return $location->getPost()->ID; }, $locations @@ -45,11 +45,11 @@ function (\CommonsBooking\Model\Location $location) { 'type' => Timeframe::BOOKING_ID, 'restrictions' => \CommonsBooking\Repository\Restriction::get( $locationIds, - [$item->ID], + [ $item->ID ], null, true, time() - ) + ), ]; // If there's no location selected, we'll show all available. @@ -70,13 +70,13 @@ function (\CommonsBooking\Model\Location $location) { $calendarData = Calendar::getCalendarDataArray( $item, - array_key_exists('location', $args) ? $args['location'] : null, + array_key_exists( 'location', $args ) ? $args['location'] : null, date( 'Y-m-d', strtotime( 'first day of this month', time() ) ), date( 'Y-m-d', strtotime( '+3 months', time() ) ) ); $args['calendar_data'] = wp_json_encode( $calendarData ); - Plugin::setCacheItem($args, ['misc'], $customId); + Plugin::setCacheItem( $args, [ 'misc' ], $customId ); return $args; } @@ -109,19 +109,18 @@ public static function shortcode( $atts ) { $itemData[ $item->ID ] = self::getShortcodeData( $item, 'Location' ); } - if ($itemData) { + if ( $itemData ) { ob_start(); foreach ( $itemData as $id => $data ) { $templateData['item'] = $id; $templateData['data'] = $data; - commonsbooking_get_template_part( 'shortcode', 'items', true, false, false ) ; + commonsbooking_get_template_part( 'shortcode', 'items', true, false, false ); } return ob_get_clean(); - } - else { //Message to show when no item matches query + } else { // Message to show when no item matches query return '
        -
        ' - . __('No bookable items found.','commonsbooking') . +
        ' + . __( 'No bookable items found.', 'commonsbooking' ) . '
        '; } diff --git a/src/View/Location.php b/src/View/Location.php index 6cae912bf..80ed146bb 100644 --- a/src/View/Location.php +++ b/src/View/Location.php @@ -23,15 +23,15 @@ public static function getTemplateData( WP_Post $post = null ): array { } $location = $post; $item = get_query_var( 'cb-item' ) ?: false; - $customId = md5($item . $location->ID); + $customId = md5( $item . $location->ID ); $cacheItem = Plugin::getCacheItem( $customId ); if ( $cacheItem ) { return $cacheItem; } else { - $items = \CommonsBooking\Repository\Item::getByLocation( $location->ID, true ); + $items = \CommonsBooking\Repository\Item::getByLocation( $location->ID, true ); $itemIds = array_map( - function (\CommonsBooking\Model\Item $item) { + function ( \CommonsBooking\Model\Item $item ) { return $item->getPost()->ID; }, $items @@ -44,12 +44,12 @@ function (\CommonsBooking\Model\Item $item) { 'postUrl' => get_permalink( $location ), 'type' => Timeframe::BOOKING_ID, 'restrictions' => \CommonsBooking\Repository\Restriction::get( - [$location->ID], + [ $location->ID ], $itemIds, null, true, - current_time('timestamp') - ) + current_time( 'timestamp' ) + ), ]; // If there's no item selected, we'll show all available. @@ -67,7 +67,7 @@ function (\CommonsBooking\Model\Item $item) { } $calendarData = Calendar::getCalendarDataArray( - array_key_exists('item', $args) ? $args['item'] : null, + array_key_exists( 'item', $args ) ? $args['item'] : null, $location, date( 'Y-m-d', strtotime( Calendar::DEFAULT_RANGE_START, time() ) ), date( 'Y-m-d', strtotime( Calendar::DEFAULT_RANGE, time() ) ) @@ -94,8 +94,11 @@ public static function shortcode( $atts ) { global $templateData; $templateData = []; $locations = []; - $queryArgs = shortcode_atts( static::$allowedShortCodeArgs, $atts, - \CommonsBooking\Wordpress\CustomPostType\Location::getPostType() ); + $queryArgs = shortcode_atts( + static::$allowedShortCodeArgs, + $atts, + \CommonsBooking\Wordpress\CustomPostType\Location::getPostType() + ); if ( is_array( $atts ) && array_key_exists( 'item-id', $atts ) ) { $location = \CommonsBooking\Repository\Location::getByItem( $atts['item-id'] ); @@ -110,7 +113,7 @@ public static function shortcode( $atts ) { $locationData[ $location->ID ] = self::getShortcodeData( $location, 'Item' ); } - if ($locationData){ + if ( $locationData ) { ob_start(); foreach ( $locationData as $id => $data ) { $templateData['location'] = $id; @@ -118,18 +121,15 @@ public static function shortcode( $atts ) { commonsbooking_get_template_part( 'shortcode', 'locations', true, false, false ); } return ob_get_clean(); - - } - else { //Message to show when no item matches query + } else { // Message to show when no item matches query return '
        ' - . __('No locations found.','commonsbooking') . + . __( 'No locations found.', 'commonsbooking' ) . '
        '; } - } /** @@ -140,24 +140,23 @@ public static function shortcode( $atts ) { * @return void */ public static function renderLocationMap( \CommonsBooking\Model\Location $post = null ) { - //renders map for location-calendar-header template, only renders when set as option + // renders map for location-calendar-header template, only renders when set as option if ( $post->getMeta( 'loc_showmap' ) ) { $latitude = $post->getMeta( 'geo_latitude' ); $longitude = $post->getMeta( 'geo_longitude' ); - wp_enqueue_style( 'cb-leaflet'); - wp_enqueue_script( 'cb-leaflet'); - + wp_enqueue_style( 'cb-leaflet' ); + wp_enqueue_script( 'cb-leaflet' ); echo '
        '; - wp_enqueue_script( 'cb-map-locationview_js', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-locationview.js', array(), false, true ); + wp_enqueue_script( 'cb-map-locationview_js', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-locationview.js', array(), false, true ); - //location geo-coordinates + // location geo-coordinates $defaults = [ 'latitude' => $latitude, 'longitude' => $longitude, ]; - wp_add_inline_script('cb-map-locationview_js','cb_map_locationview.defaults =' . wp_json_encode($defaults) ); + wp_add_inline_script( 'cb-map-locationview_js', 'cb_map_locationview.defaults =' . wp_json_encode( $defaults ) ); } } } diff --git a/src/View/Map.php b/src/View/Map.php index aecb669ce..f8a56e612 100644 --- a/src/View/Map.php +++ b/src/View/Map.php @@ -14,38 +14,37 @@ class Map extends View { * load needed assets for the map that provides fine tuning of the location's position **/ public static function render_cb_map( $field, $escaped_value, $object_id, $object_type, $field_type_object ) { - //map - wp_enqueue_style( 'cb-leaflet'); - wp_enqueue_script( 'cb-leaflet'); + // map + wp_enqueue_style( 'cb-leaflet' ); + wp_enqueue_script( 'cb-leaflet' ); echo '
        '; - wp_enqueue_script( 'cb-map-positioning_js', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-positioning.js' ); + wp_enqueue_script( 'cb-map-positioning_js', COMMONSBOOKING_MAP_ASSETS_URL . 'js/cb-map-positioning.js' ); - //map defaults + // map defaults $defaults = [ 'latitude' => \CommonsBooking\Wordpress\CustomPostType\Map::LATITUDE_DEFAULT, 'longitude' => \CommonsBooking\Wordpress\CustomPostType\Map::LONGITUDE_DEFAULT, ]; - wp_add_inline_script('cb-map-positioning_js','cb_map_positioning.defaults =' . wp_json_encode($defaults) ); + wp_add_inline_script( 'cb-map-positioning_js', 'cb_map_positioning.defaults =' . wp_json_encode( $defaults ) ); } public static function renderGeoRefreshButton() { - echo '
        + echo '
        + esc_html__( 'Set / update GPS coordinates from address', 'commonsbooking' ) . + '

        ' . - commonsbooking_sanitizeHTML( __('Click this button to automatically set the GPS coordinates based on the given address and set the marker on the map.
        Save or update this location after setting the gps data.', 'commonsbooking' ) ) . - '

        + commonsbooking_sanitizeHTML( __( 'Click this button to automatically set the GPS coordinates based on the given address and set the marker on the map.
        Save or update this location after setting the gps data.', 'commonsbooking' ) ) . + '

        + commonsbooking_sanitizeHTML( __( 'No GPS data could be found for the address entered.
        Please check if the address is written correctly.
        Alternatively, you can enter the GPS data manually into the corresponding fields.', 'commonsbooking' ) ) . + '
        '; } - -} \ No newline at end of file +} diff --git a/src/View/MassOperations.php b/src/View/MassOperations.php index f9d25b115..daee0e919 100644 --- a/src/View/MassOperations.php +++ b/src/View/MassOperations.php @@ -6,7 +6,7 @@ class MassOperations { public static function index() { global $templateData; $templateData = []; - $templateData["orphanedBookings"] = \CommonsBooking\Repository\Booking::getOrphaned(); + $templateData['orphanedBookings'] = \CommonsBooking\Repository\Booking::getOrphaned(); ob_start(); commonsbooking_sanitizeHTML( commonsbooking_get_template_part( 'massoperations', 'index' ) ); @@ -34,18 +34,18 @@ public static function renderBookingViewTable( array $bookings ) { - ' . esc_html__( "ID", 'commonsbooking' ) . ' - ' . esc_html__( "User", 'commonsbooking' ) . ' - ' . esc_html__( "Item name", 'commonsbooking' ) . ' - ' . esc_html__( "Start-date", 'commonsbooking' ) . ' - ' . esc_html__( "End-date", 'commonsbooking' ) . ' - ' . esc_html__( "Status", 'commonsbooking' ) . ' - ' . esc_html__( "Location name", 'commonsbooking' ) . ' - ' . esc_html__( "New location name", 'commonsbooking' ) . ' + ' . esc_html__( 'ID', 'commonsbooking' ) . ' + ' . esc_html__( 'User', 'commonsbooking' ) . ' + ' . esc_html__( 'Item name', 'commonsbooking' ) . ' + ' . esc_html__( 'Start-date', 'commonsbooking' ) . ' + ' . esc_html__( 'End-date', 'commonsbooking' ) . ' + ' . esc_html__( 'Status', 'commonsbooking' ) . ' + ' . esc_html__( 'Location name', 'commonsbooking' ) . ' + ' . esc_html__( 'New location name', 'commonsbooking' ) . ' '; - foreach ( $bookings as $booking ): + foreach ( $bookings as $booking ) : try { $itemTitle = $booking->getItem()->post_title; } catch ( \Exception $e ) { @@ -111,5 +111,4 @@ public static function renderOrphanedMigrationButton() {
        '; } - -} \ No newline at end of file +} diff --git a/src/View/Migration.php b/src/View/Migration.php index df2f6190b..201ec729e 100644 --- a/src/View/Migration.php +++ b/src/View/Migration.php @@ -2,7 +2,6 @@ namespace CommonsBooking\View; - use CMB2_Field; use CommonsBooking\Repository\CB1; use CommonsBooking\Service\Upgrade; @@ -15,21 +14,26 @@ class Migration { /** * Render Migration Form. * - * @param array $field_args Array of field arguments. + * @param array $field_args Array of field arguments. * @param CMB2_Field $field The field object */ public static function renderMigrationForm( array $field_args, CMB2_Field $field ) { $cb1Installed = CB1::isInstalled(); ?> -
        + ' . esc_html__( 'We could not detect a version of an older CommonsBooking Installation (Version 0.X).', - 'commonsbooking' ) . ''; + echo '' . esc_html__( + 'We could not detect a version of an older CommonsBooking Installation (Version 0.X).', + 'commonsbooking' + ) . ''; } else { - echo '' . esc_html__( 'Found a version of an older CommonsBooking Installation (Version 0.X). You can migrate.', - 'commonsbooking' ) . ''; + echo '' . esc_html__( + 'Found a version of an older CommonsBooking Installation (Version 0.X). You can migrate.', + 'commonsbooking' + ) . ''; } echo( ' @@ -45,7 +49,7 @@ public static function renderMigrationForm( array $field_args, CMB2_Field $field

        - ' . commonsbooking_sanitizeHTML( __( 'migration in process .. please wait ...
        This could take several minutes. Do not close this browser tab', 'commonsbooking' ) ). ' + ' . commonsbooking_sanitizeHTML( __( 'migration in process .. please wait ...
        This could take several minutes. Do not close this browser tab', 'commonsbooking' ) ) . '

        @@ -57,31 +61,32 @@ public static function renderMigrationForm( array $field_args, CMB2_Field $field if ( $cb1Installed ) { ?> -
        -
        -
        - - -

        - -

        -
        -
        -
        - - - - +
        +
        + + +

        + +

        +
        +
        +
        + + + + -
        +
        ' - ); + ); } public static function renderUpgradeForm( array $field_args, CMB2_Field $field ) { - if (! Upgrade::isAJAXUpgrade() ) return false; + if ( ! Upgrade::isAJAXUpgrade() ) { + return false; + } ?>
        @@ -131,5 +138,4 @@ public static function renderUpgradeForm( array $field_args, CMB2_Field $field )
        -
        -
        - -
        -
        - - -

        - -

        - - -

        - -

        +
        +
        + +
        +
        + + +

        + +

        + + +

        + +

        -
        -
        +
        +
        - +
        - - - + + +
        - - - + + +
        @@ -54,5 +54,6 @@ public static function renderExportButton( $field_args, $field ) {
        - '', // Order: https://developer.wordpress.org/reference/classes/wp_query/#order-orderby-parameters 'order' => '', - 'orderby' => '', + 'orderby' => '', ); /** @@ -51,7 +52,7 @@ abstract class View { * This includes the availability timeframe, see assumptions in class docstring for more details. * * @param \CommonsBooking\Model\Item|\CommonsBooking\Model\Location $cpt location or item model object to retrieve timeframe data from. - * @param string $type 'Item' or 'Location'. + * @param string $type 'Item' or 'Location'. * @return array * @throws Exception */ @@ -60,9 +61,12 @@ public static function getShortcodeData( $cpt, string $type ): array { $timeframes = $cpt->getBookableTimeframes( true ); // sort by start date, to get latest possible booking date by first timeframe - usort( $timeframes, function ( $a, $b ) { - return $a->getStartDate() <=> $b->getStartDate(); - } ); + usort( + $timeframes, + function ( $a, $b ) { + return $a->getStartDate() <=> $b->getStartDate(); + } + ); $latestPossibleBookingDate = false; /** @var Timeframe $timeframe */ @@ -73,18 +77,20 @@ public static function getShortcodeData( $cpt, string $type ): array { // We only fetch the latest possible booking date from the first timeframe. // This is ok, because the timeframes are sorted by their start date. - if(!$latestPossibleBookingDate) { + if ( ! $latestPossibleBookingDate ) { $latestPossibleBookingDate = $timeframe->getLatestPossibleBookingDateTimestamp(); } // If start date is after latest possible booking date, we leave range out - $endOfStartDay = strtotime('+1 day midnight', $timeframe->getStartDate()) - 1; - if($endOfStartDay > $latestPossibleBookingDate) continue; + $endOfStartDay = strtotime( '+1 day midnight', $timeframe->getStartDate() ) - 1; + if ( $endOfStartDay > $latestPossibleBookingDate ) { + continue; + } $item = $timeframe->{'get' . $type}(); // We need only published items - if ( !$item || $item->post_status !== 'publish' ) { + if ( ! $item || $item->post_status !== 'publish' ) { continue; } @@ -151,13 +157,16 @@ public static function getShortcodeData( $cpt, string $type ): array { } } - //Remove duplicate ranges + // Remove duplicate ranges $cptData[ $item->ID ]['ranges'] = array_unique( $cptData[ $item->ID ]['ranges'], SORT_REGULAR ); - //sort ranges by starting date - usort( $cptData[ $item->ID ]['ranges'], function ( $a, $b ) { - return $a['start_date'] <=> $b['start_date']; - } ); + // sort ranges by starting date + usort( + $cptData[ $item->ID ]['ranges'], + function ( $a, $b ) { + return $a['start_date'] <=> $b['start_date']; + } + ); } return $cptData; @@ -168,47 +177,43 @@ public static function getShortcodeData( $cpt, string $type ): array { * * @return string */ - public static function getColorCSS():string{ - $compiler = new Compiler(); - $var_import = COMMONSBOOKING_PLUGIN_DIR . 'assets/global/sass/partials/_variables.scss'; + public static function getColorCSS(): string { + $compiler = new Compiler(); + $var_import = COMMONSBOOKING_PLUGIN_DIR . 'assets/global/sass/partials/_variables.scss'; $import_path = COMMONSBOOKING_PLUGIN_DIR . 'assets/public/sass/partials/'; - $compiler ->setImportPaths($import_path); + $compiler->setImportPaths( $import_path ); $variables = [ - 'color-primary' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_primarycolor'), - 'color-secondary' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_secondarycolor'), - 'color-buttons' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_buttoncolor'), - 'color-accept' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_acceptcolor'), - 'color-cancel' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_cancelcolor'), - 'color-holiday' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_holidaycolor'), - 'color-greyedout' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_greyedoutcolor'), - 'color-bg' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_backgroundcolor'), - 'color-noticebg' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_noticebackgroundcolor'), - 'color-lighttext' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_lighttext'), - 'color-darktext' => Settings::getOption('commonsbooking_options_templates', 'colorscheme_darktext'), + 'color-primary' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_primarycolor' ), + 'color-secondary' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_secondarycolor' ), + 'color-buttons' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_buttoncolor' ), + 'color-accept' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_acceptcolor' ), + 'color-cancel' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_cancelcolor' ), + 'color-holiday' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_holidaycolor' ), + 'color-greyedout' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_greyedoutcolor' ), + 'color-bg' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_backgroundcolor' ), + 'color-noticebg' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_noticebackgroundcolor' ), + 'color-lighttext' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_lighttext' ), + 'color-darktext' => Settings::getOption( 'commonsbooking_options_templates', 'colorscheme_darktext' ), ]; - foreach ($variables as &$variable){ //iterate over array, convert valid values. - if ($variable){ //values are only converted when set so ValueParser does not throw an error - $variable = ValueConverter::parseValue($variable); - } - else { - return false; //do not return CSS when no values are set + foreach ( $variables as &$variable ) { // iterate over array, convert valid values. + if ( $variable ) { // values are only converted when set so ValueParser does not throw an error + $variable = ValueConverter::parseValue( $variable ); + } else { + return false; // do not return CSS when no values are set } } - $compiler->replaceVariables($variables); + $compiler->replaceVariables( $variables ); $content = '@import "' . $var_import . '";'; - $result = $compiler->compileString($content); - $css = $result->getCss(); + $result = $compiler->compileString( $content ); + $css = $result->getCss(); - if (!empty($css) && is_string($css)) { + if ( ! empty( $css ) && is_string( $css ) ) { return $css; - } - else { + } else { return false; } - } - } diff --git a/src/Wordpress/CustomPostType/Booking.php b/src/Wordpress/CustomPostType/Booking.php index 445c0dd4f..17cf001ae 100644 --- a/src/Wordpress/CustomPostType/Booking.php +++ b/src/Wordpress/CustomPostType/Booking.php @@ -18,9 +18,9 @@ */ class Booking extends Timeframe { - //this is the error type for the validation that failed for the FRONTEND user - //TODO: Switch the error type with the one from Model/Booking, because most functions regarding backend booking are in this class - public const ERROR_TYPE = COMMONSBOOKING_PLUGIN_SLUG . '-bookingValidationError'; + // this is the error type for the validation that failed for the FRONTEND user + // TODO: Switch the error type with the one from Model/Booking, because most functions regarding backend booking are in this class + public const ERROR_TYPE = COMMONSBOOKING_PLUGIN_SLUG . '-bookingValidationError'; private const SUBMIT_BUTTON_ID = 'booking-submit'; /** @@ -30,7 +30,7 @@ class Booking extends Timeframe { /** * Position in backend menu. - * + * * @var int */ protected $menuPosition = 4; @@ -39,19 +39,18 @@ public function __construct() { // does not trigger when initiated in initHooks add_action( 'post_updated', array( $this, 'postUpdated' ), 1, 3 ); - } - /** + /** * Initiates needed hooks. */ public function initHooks() { // Add Meta Boxes add_action( 'cmb2_admin_init', array( $this, 'registerMetabox' ) ); - // we need to add some additional fields and modify the autor if admin booking is made - add_action( 'save_post_' . self::$postType, array( $this, 'savePost' ), 10 ); + // we need to add some additional fields and modify the autor if admin booking is made + add_action( 'save_post_' . self::$postType, array( $this, 'savePost' ), 10 ); // Set Tepmlates add_filter( 'the_content', array( $this, 'getTemplate' ) ); @@ -69,102 +68,105 @@ public function initHooks() { // show admin notice add_action( 'admin_notices', array( $this, 'displayBookingsAdminListNotice' ) ); - add_action( 'edit_form_top', array( $this, 'displayOverlappingBookingNotice' ), 99 ); + add_action( 'edit_form_top', array( $this, 'displayOverlappingBookingNotice' ), 99 ); } - /** - * Adds and modifies some booking CPT fields in order to make admin boookings - * compatible to user made bookings via frontend. - * - * @param mixed $post_id - * @param mixed $post - * @param mixed $update - * @return void - */ - public function savePost( $post_id, $post = null, $update = null ) { - global $pagenow; - - $post = $post ?? get_post( $post_id ); - $is_trash_action = str_contains(($_REQUEST ?? array())['action'] ?? '', 'trash'); - - // we check if it's a new created post - TODO: This is not the case - if ( + /** + * Adds and modifies some booking CPT fields in order to make admin boookings + * compatible to user made bookings via frontend. + * + * @param mixed $post_id + * @param mixed $post + * @param mixed $update + * @return void + */ + public function savePost( $post_id, $post = null, $update = null ) { + global $pagenow; + + $post = $post ?? get_post( $post_id ); + $is_trash_action = str_contains( ( $_REQUEST ?? array() )['action'] ?? '', 'trash' ); + + // we check if it's a new created post - TODO: This is not the case + if ( ! empty( $_REQUEST ) && ! $is_trash_action && $pagenow === 'post.php' && ( commonsbooking_isCurrentUserAdmin() || commonsbooking_isCurrentUserCBManager() ) ) { - // set request variables - $booking_user = isset( $_REQUEST['booking_user'] ) ? esc_html( $_REQUEST['booking_user'] ) : false; + // set request variables + $booking_user = isset( $_REQUEST['booking_user'] ) ? esc_html( $_REQUEST['booking_user'] ) : false; - $post_status = esc_html( $_REQUEST['post_status'] ?? '' ); + $post_status = esc_html( $_REQUEST['post_status'] ?? '' ); - $start_time = isset( $_REQUEST['repetition-start'] ) ? esc_html( $_REQUEST['repetition-start']['time'] ?? '' ) : false; - $end_time = isset( $_REQUEST['repetition-end'] ) ? esc_html( $_REQUEST['repetition-end']['time'] ?? '' ) : false; - $full_day = ( !$start_time || $start_time === '0:00' || $start_time === '00:00' ) && ( !$end_time || $end_time === '23:59' ) ? 'on' : ''; + $start_time = isset( $_REQUEST['repetition-start'] ) ? esc_html( $_REQUEST['repetition-start']['time'] ?? '' ) : false; + $end_time = isset( $_REQUEST['repetition-end'] ) ? esc_html( $_REQUEST['repetition-end']['time'] ?? '' ) : false; + $full_day = ( ! $start_time || $start_time === '0:00' || $start_time === '00:00' ) && ( ! $end_time || $end_time === '23:59' ) ? 'on' : ''; - $postarr = array( + $postarr = array( 'post_title' => esc_html__( 'Admin-Booking', 'commonsbooking' ), - 'post_author' => $booking_user, - 'post_status' => $post_status, - 'meta_input' => [ - 'admin_booking_id' => get_current_user_id(), - 'start-time' => $start_time, - 'end-time' => $end_time, - 'type' => Timeframe::BOOKING_ID, - 'grid' => '', - 'full-day' => $full_day, + 'post_author' => $booking_user, + 'post_status' => $post_status, + 'meta_input' => [ + 'admin_booking_id' => get_current_user_id(), + 'start-time' => $start_time, + 'end-time' => $end_time, + 'type' => Timeframe::BOOKING_ID, + 'grid' => '', + 'full-day' => $full_day, ], - ); - - // set post_name if new post - if ( in_array( $post->post_status, array( 'auto-draft', 'new' ) ) || $post->post_name === '' ) { - $postarr['post_name'] = Helper::generateRandomString(); - } - - $postarr['ID'] = $post_id; - - // unhook this function so it doesn't loop infinitely - remove_action( 'save_post_' . self::$postType, array( $this, 'savePost' ) ); - - // update this post - wp_update_post( $postarr, true, true ); - - //run validation only on new posts (the submit button is only available on new posts) - if ( array_key_exists( self::SUBMIT_BUTTON_ID, $_REQUEST ) ) { - try { - $booking = new \CommonsBooking\Model\Booking( $post_id ); - $booking->isValid(); - wp_update_post( array( - 'ID' => $post_id, - 'post_status' => 'confirmed' - ) - ); - $post_status = 'confirmed'; - } catch ( TimeframeInvalidException $e ) { - // set to draft and display error message - wp_update_post( array( - 'ID' => $post_id, - 'post_status' => 'draft', - ) ); - set_transient( - \CommonsBooking\Model\Booking::ERROR_TYPE, - nl2br(commonsbooking_sanitizeHTML( $e->getMessage() )), - 30 //Expires very quickly, so that outdated messsages will not be shown to the user - ); - } - } - - // readd the hook - add_action( 'save_post_' . self::$postType, array( $this, 'savePost' ) ); - - //if we just created a new confirmed booking we trigger the confirmation mail - if ( $post_status == 'confirmed' ) { - $booking_msg = new BookingMessage( $post_id, $post_status ); - $booking_msg->triggerMail(); - } - } - } + ); + + // set post_name if new post + if ( in_array( $post->post_status, array( 'auto-draft', 'new' ) ) || $post->post_name === '' ) { + $postarr['post_name'] = Helper::generateRandomString(); + } + + $postarr['ID'] = $post_id; + + // unhook this function so it doesn't loop infinitely + remove_action( 'save_post_' . self::$postType, array( $this, 'savePost' ) ); + + // update this post + wp_update_post( $postarr, true, true ); + + // run validation only on new posts (the submit button is only available on new posts) + if ( array_key_exists( self::SUBMIT_BUTTON_ID, $_REQUEST ) ) { + try { + $booking = new \CommonsBooking\Model\Booking( $post_id ); + $booking->isValid(); + wp_update_post( + array( + 'ID' => $post_id, + 'post_status' => 'confirmed', + ) + ); + $post_status = 'confirmed'; + } catch ( TimeframeInvalidException $e ) { + // set to draft and display error message + wp_update_post( + array( + 'ID' => $post_id, + 'post_status' => 'draft', + ) + ); + set_transient( + \CommonsBooking\Model\Booking::ERROR_TYPE, + nl2br( commonsbooking_sanitizeHTML( $e->getMessage() ) ), + 30 // Expires very quickly, so that outdated messsages will not be shown to the user + ); + } + } + + // readd the hook + add_action( 'save_post_' . self::$postType, array( $this, 'savePost' ) ); + + // if we just created a new confirmed booking we trigger the confirmation mail + if ( $post_status == 'confirmed' ) { + $booking_msg = new BookingMessage( $post_id, $post_status ); + $booking_msg->triggerMail(); + } + } + } /** * Handles frontend save-Request for timeframe. @@ -218,7 +220,7 @@ function_exists( 'wp_verify_nonce' ) && * @param string|null $itemId * @param string|null $locationId * @param string|null $post_status - * @param int|null $post_ID + * @param int|null $post_ID * @param string|null $comment * @param string|null $repetitionStart * @param string|null $repetitionEnd @@ -241,11 +243,11 @@ public static function handleBookingRequest( int $overbookedDays = 0 ): int { - if ( isset ( $_POST['calendar-download'] ) ) { + if ( isset( $_POST['calendar-download'] ) ) { try { iCalendar::downloadICS( $post_ID ); } catch ( Exception $e ) { - //redirect to booking page and do nothing + // redirect to booking page and do nothing return $post_ID; } exit; @@ -337,22 +339,21 @@ public static function handleBookingRequest( 'type' => Timeframe::BOOKING_ID, ); - $postId = wp_insert_post( $postarr, true ); + $postId = wp_insert_post( $postarr, true ); $needsValidation = true; // Existing booking } else { $postarr['ID'] = $booking->ID; if ( $postarr['post_status'] === 'canceled' ) { - $postarr['meta_input']['cancellation_time'] = current_time('timestamp'); + $postarr['meta_input']['cancellation_time'] = current_time( 'timestamp' ); } - $postId = wp_update_post( $postarr ); + $postId = wp_update_post( $postarr ); - //we check if this is an already denied booking and demand validation again - if ($postarr["post_status"] == "unconfirmed"){ + // we check if this is an already denied booking and demand validation again + if ( $postarr['post_status'] == 'unconfirmed' ) { $needsValidation = true; - } - else { + } else { $needsValidation = false; } } @@ -363,29 +364,30 @@ public static function handleBookingRequest( // we need some meta-fields from bookable-timeframe, so we assign them here to the booking-timeframe try { $bookingModel->assignBookableTimeframeFields(); - if ( $overbookedDays > 0 ) { //avoid setting the value when not present (for example when updating the booking) + if ( $overbookedDays > 0 ) { // avoid setting the value when not present (for example when updating the booking) $bookingModel->setOverbookedDays( $overbookedDays ); } } catch ( \Exception $e ) { - throw new BookingDeniedException( __( 'There was an error while saving the booking. Please try again. Thrown error:', 'commonsbooking' ) . - PHP_EOL . $e->getMessage() + throw new BookingDeniedException( + __( 'There was an error while saving the booking. Please try again. Thrown error:', 'commonsbooking' ) . + PHP_EOL . $e->getMessage() ); } - //check if the Booking we want to create conforms to the set booking rules - if( $needsValidation){ + // check if the Booking we want to create conforms to the set booking rules + if ( $needsValidation ) { try { BookingRuleApplied::bookingConformsToRules( $bookingModel ); - } - catch (BookingDeniedException $e) { - wp_delete_post($bookingModel->ID); - throw new BookingDeniedException($e->getMessage()); + } catch ( BookingDeniedException $e ) { + wp_delete_post( $bookingModel->ID ); + throw new BookingDeniedException( $e->getMessage() ); } } if ( $postId instanceof \WP_Error ) { - throw new BookingDeniedException( __( 'There was an error while saving the booking. Please try again. Resulting WP_ERROR: ', 'commonsbooking' ) . - PHP_EOL . $postId->get_error_messages() + throw new BookingDeniedException( + __( 'There was an error while saving the booking. Please try again. Resulting WP_ERROR: ', 'commonsbooking' ) . + PHP_EOL . $postId->get_error_messages() ); } @@ -404,7 +406,7 @@ public static function handleBookingRequest( */ private static function saveGridSizes( $postId, $locationId, $itemId, $startDate, $endDate ): void { $startTimeFrame = \CommonsBooking\Repository\Timeframe::getByLocationItemTimestamp( $locationId, $itemId, $startDate ); - if ( $startTimeFrame && !$startTimeFrame->isFullDay() && $startTimeFrame->getGrid() == 0 ) { + if ( $startTimeFrame && ! $startTimeFrame->isFullDay() && $startTimeFrame->getGrid() == 0 ) { update_post_meta( $postId, \CommonsBooking\Model\Booking::START_TIMEFRAME_GRIDSIZE, @@ -412,7 +414,7 @@ private static function saveGridSizes( $postId, $locationId, $itemId, $startDate ); } $endTimeFrame = \CommonsBooking\Repository\Timeframe::getByLocationItemTimestamp( $locationId, $itemId, $endDate ); - if ( $endTimeFrame && !$endTimeFrame->isFullDay() && $endTimeFrame->getGrid() == 0 ) { + if ( $endTimeFrame && ! $endTimeFrame->isFullDay() && $endTimeFrame->getGrid() == 0 ) { update_post_meta( $postId, \CommonsBooking\Model\Booking::END_TIMEFRAME_GRIDSIZE, @@ -484,16 +486,16 @@ public function getTemplate( $content ) { */ public function postUpdated( $post_ID, $post_after, $post_before ) { - if ( ! $this->hasRunBefore( __FUNCTION__ ) ) { + if ( ! $this->hasRunBefore( __FUNCTION__ ) ) { $isBooking = get_post_meta( $post_ID, 'type', true ) == Timeframe::BOOKING_ID; - if ( $isBooking ) { + if ( $isBooking ) { - // Trigger Mail, only send mail if status has changed + // Trigger Mail, only send mail if status has changed if ( $post_before->post_status != $post_after->post_status and - ! ( - $post_before->post_status === 'unconfirmed' and - $post_after->post_status === 'canceled' - ) + ! ( + $post_before->post_status === 'unconfirmed' and + $post_after->post_status === 'canceled' + ) ) { if ( $post_after->post_status == 'canceled' ) { $booking = new \CommonsBooking\Model\Booking( $post_ID ); @@ -503,13 +505,13 @@ public function postUpdated( $post_ID, $post_after, $post_before ) { $booking_msg->triggerMail(); } } - } + } } } /** * Returns CPT arguments. - * + * * @return array */ public function getArgs() { @@ -596,15 +598,15 @@ public function getArgs() { * @param $post_id */ public function setCustomColumnsData( $column, $post_id ) { - global $pagenow; + global $pagenow; - if ( $pagenow !== 'edit.php' || empty( esc_html( $_GET['post_type'] ) ) || esc_html( $_GET['post_type'] ) !== $this::$postType ) { - return; - } + if ( $pagenow !== 'edit.php' || empty( esc_html( $_GET['post_type'] ) ) || esc_html( $_GET['post_type'] ) !== $this::$postType ) { + return; + } // we alter the author column data and link the username to the user profile if ( $column == 'booking_user' ) { - $post = get_post( $post_id ); + $post = get_post( $post_id ); $bookingUser = get_user_by( 'id', $post->post_author ); echo '' . commonsbooking_sanitizeHTML( $bookingUser->user_login ) . ''; } @@ -615,7 +617,7 @@ public function setCustomColumnsData( $column, $post_id ) { case 'item-id': if ( $post = get_post( $value ) ) { if ( get_post_type( $post ) == Location::getPostType() || - get_post_type( $post ) == Item::getPostType() + get_post_type( $post ) == Item::getPostType() ) { echo commonsbooking_sanitizeHTML( $post->post_title ); break; @@ -660,15 +662,15 @@ public function setCustomColumnsData( $column, $post_id ) { ) ) { - // get translated label for post status - if ($column === 'post_status') { - echo __( commonsbooking_sanitizeHTML( get_post_status_object( get_post_status( $post_id ) )->label ) ); - } else { - echo __( commonsbooking_sanitizeHTML( $post->{$column} ) ); - } - } + // get translated label for post status + if ( $column === 'post_status' ) { + echo __( commonsbooking_sanitizeHTML( get_post_status_object( get_post_status( $post_id ) )->label ) ); + } else { + echo __( commonsbooking_sanitizeHTML( $post->{$column} ) ); + } + } } - } + } /** * @param \WP_Query $query @@ -676,7 +678,7 @@ public function setCustomColumnsData( $column, $post_id ) { * @return void */ public function setCustomColumnSortOrder( \WP_Query $query ) { - if (! parent::setCustomColumnSortOrder( $query ) ) { + if ( ! parent::setCustomColumnSortOrder( $query ) ) { return; } @@ -692,7 +694,7 @@ public function setCustomColumnSortOrder( \WP_Query $query ) { * Registers metaboxes for cpt. */ public function registerMetabox() { - //do not render the metabox if the user is on the login page (not yet logged in) + // do not render the metabox if the user is on the login page (not yet logged in) if ( ! is_user_logged_in() ) { return; } @@ -711,7 +713,7 @@ public function registerMetabox() { /** * Returns custom (meta) fields for Costum Post Type Timeframe. - * + * * @return array */ protected function getCustomFields() { @@ -725,15 +727,15 @@ protected function getCustomFields() { $dateFormat = 'm/d/Y'; } - $booking_user = get_user_by('ID', get_current_user_id()); + $booking_user = get_user_by( 'ID', get_current_user_id() ); - // define form fields based on CMB2 + // define form fields based on CMB2 return array( array( 'name' => esc_html__( 'Edit booking', 'commonsbooking' ), 'desc' => '

        ' . commonsbooking_sanitizeHTML( - __( - '

        Notice

        In this view, you as an admin can create or modify existing bookings. Please use it with caution.
        + __( + '

        Notice

        In this view, you as an admin can create or modify existing bookings. Please use it with caution.

        • Click on the preview button on the right panel to view more booking details and to cancel the booking via the cancel button.
        • Click on the Submit booking button at the end of the page to submit a new booking.
        • @@ -741,9 +743,9 @@ protected function getCustomFields() { Please note: Only a few basic checks against existing bookings are performed. Please be wary of overlapping bookings.

          ', - 'commonsbooking' - ) . '

        ' - ), + 'commonsbooking' + ) . '

        ' + ), 'id' => 'title-booking-hint', 'type' => 'title', ), @@ -763,7 +765,7 @@ protected function getCustomFields() { 'name' => esc_html__( 'Book full day', 'commonsbooking' ), 'id' => 'full-day', 'type' => 'checkbox', - 'desc' => esc_html__( 'The booking should apply to the entire day(s)', 'commonsbooking' ), + 'desc' => esc_html__( 'The booking should apply to the entire day(s)', 'commonsbooking' ), ), array( 'name' => esc_html__( 'Start date', 'commonsbooking' ), @@ -772,7 +774,7 @@ protected function getCustomFields() { 'type' => 'text_datetime_timestamp', 'time_format' => get_option( 'time_format' ), 'date_format' => $dateFormat, - 'default' => '00:00', + 'default' => '00:00', 'attributes' => array( 'data-timepicker' => wp_json_encode( array( @@ -789,7 +791,7 @@ protected function getCustomFields() { 'type' => 'text_datetime_timestamp', 'time_format' => get_option( 'time_format' ), 'date_format' => $dateFormat, - 'default' => '23:59', + 'default' => '23:59', 'attributes' => array( 'data-timepicker' => wp_json_encode( array( @@ -805,38 +807,38 @@ protected function getCustomFields() { 'type' => 'text', 'desc' => esc_html__( 'Valid booking code will be automatically retrieved for bookings that apply to the full day.', 'commonsbooking' ), ), - array( + array( 'name' => esc_html__( 'Booking User', 'commonsbooking' ), 'id' => 'booking_user', 'type' => 'user_ajax_search', - 'multiple-items' => true, - 'default' => array( self::class, 'getFrontendBookingUser' ), - 'desc' => commonsbooking_sanitizeHTML( - __( - 'Here you must select the user for whom the booking is made.
        + 'multiple-items' => true, + 'default' => array( self::class, 'getFrontendBookingUser' ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'Here you must select the user for whom the booking is made.
        If the booking was made by a user via frontend booking process, the user will be shown in this field.
        Notice:The user will receive a booking confirmation as soon as the booking is submitted.', - 'commonsbooking' - ) - ), + 'commonsbooking' + ) + ), ), - array( + array( 'name' => esc_html__( 'Admin Booking User', 'commonsbooking' ), 'id' => 'admin_booking_id', 'type' => 'select', - 'default' => get_current_user_id(), - 'options' => array ( - $booking_user->ID => $booking_user->get( 'user_nicename' ) . ' (' . $booking_user->first_name . ' ' . $booking_user->last_name . ')', - ), - 'attributes' => array( - 'readonly' => true, - ), - 'desc' => commonsbooking_sanitizeHTML( - __( - 'This is the admin user who created or modified this booking.', - 'commonsbooking' - ) - ), + 'default' => get_current_user_id(), + 'options' => array( + $booking_user->ID => $booking_user->get( 'user_nicename' ) . ' (' . $booking_user->first_name . ' ' . $booking_user->last_name . ')', + ), + 'attributes' => array( + 'readonly' => true, + ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'This is the admin user who created or modified this booking.', + 'commonsbooking' + ) + ), ), array( 'name' => esc_html__( 'External comment', 'commonsbooking' ), @@ -874,16 +876,16 @@ public function displayBookingsAdminListNotice() { global $pagenow; $notice = commonsbooking_sanitizeHTML( - __( - 'Bookings should be created via frontend booking calendar.
        + __( + 'Bookings should be created via frontend booking calendar.
        As an admin you can create bookings via this admin interface. Please be aware that admin bookings are not validated and checked. Use this function with care.
        Click on preview to show booking details in frontend
        To search and filter bookings please integrate the frontend booking list via shortcode. See here How to display the booking list', - 'commonsbooking' - ) - ); + 'commonsbooking' + ) + ); if ( ( $pagenow == 'edit.php' ) && isset( $_GET['post_type'] ) ) { if ( sanitize_text_field( $_GET['post_type'] ) == self::getPostType() ) { @@ -893,17 +895,17 @@ public function displayBookingsAdminListNotice() { } - /** - * Displays a permanent admin-notice if booking overlaps - * - * @return void - */ - public function displayOverlappingBookingNotice( $post ) { + /** + * Displays a permanent admin-notice if booking overlaps + * + * @return void + */ + public function displayOverlappingBookingNotice( $post ) { - if ( get_transient( 'commonsbooking_booking_validation_failed_' . $post->ID ) ) { - echo commonsbooking_sanitizeHTML( get_transient( 'commonsbooking_booking_validation_failed_' . $post->ID, 'warning' ) ); - } - } + if ( get_transient( 'commonsbooking_booking_validation_failed_' . $post->ID ) ) { + echo commonsbooking_sanitizeHTML( get_transient( 'commonsbooking_booking_validation_failed_' . $post->ID, 'warning' ) ); + } + } /** * Export user bookings using the supplied email. This is for integration with the WordPress personal data exporter. @@ -914,30 +916,30 @@ public function displayOverlappingBookingNotice( $post ) { * @return array */ public static function exportUserBookingsByEmail( string $emailAddress, $page = 1 ): array { - $page = intval( $page ); + $page = intval( $page ); $itemsPerPage = 10; - $exportItems = array(); - //The internal group ID used by WordPress to group the data exported by this exporter. - $groupID = 'bookings'; + $exportItems = array(); + // The internal group ID used by WordPress to group the data exported by this exporter. + $groupID = 'bookings'; $groupLabel = __( 'CommonsBooking Bookings', 'commonsbooking' ); $user = get_user_by( 'email', $emailAddress ); if ( ! $user ) { - return array( - 'data' => $exportItems, - 'done' => true, - ); + return array( + 'data' => $exportItems, + 'done' => true, + ); } $bookings = \CommonsBooking\Repository\Booking::getForUserPaginated( $user, $page, $itemsPerPage ); if ( ! $bookings ) { - return array( - 'data' => $exportItems, - 'done' => true, - ); + return array( + 'data' => $exportItems, + 'done' => true, + ); } - foreach ($bookings as $booking) { + foreach ( $bookings as $booking ) { $bookingID = $booking->ID; - //exclude bookings that the user is eligible to see but are not their own + // exclude bookings that the user is eligible to see but are not their own // we are only concerned about one user's personal data if ( $booking->getUserData()->user_email !== $emailAddress ) { continue; @@ -945,7 +947,7 @@ public static function exportUserBookingsByEmail( string $emailAddress, $page = $bookingData = [ [ 'name' => __( 'Booking start', 'commonsbooking' ), - 'value' => $booking->pickupDatetime() , + 'value' => $booking->pickupDatetime(), ], [ 'name' => __( 'Booking end', 'commonsbooking' ), @@ -953,7 +955,7 @@ public static function exportUserBookingsByEmail( string $emailAddress, $page = ], [ 'name' => __( 'Time of booking', 'commonsbooking' ), - 'value' => Helper::FormattedDateTime(get_post_timestamp( $bookingID ) ), + 'value' => Helper::FormattedDateTime( get_post_timestamp( $bookingID ) ), ], [ 'name' => __( 'Status', 'commonsbooking' ), @@ -991,7 +993,7 @@ public static function exportUserBookingsByEmail( string $emailAddress, $page = 'item_id' => $bookingID, 'data' => $bookingData, ]; - } + } $done = count( $bookings ) < $itemsPerPage; return array( 'data' => $exportItems, @@ -1001,14 +1003,15 @@ public static function exportUserBookingsByEmail( string $emailAddress, $page = /** * Remove user bookings using the supplied email. This is for integration with the WordPress personal data eraser. - * @param string $emailAddress The email address + * + * @param string $emailAddress The email address * @param $page This parameter has no real use in this function, we just use it to stick to WordPress expected parameters. * * @return array */ public static function removeUserBookingsByEmail( string $emailAddress, $page = 1 ): array { - //we reset the page to 1, because we are deleting our results as we go. Therefore, increasing the page number would skip some results. - $page = 1; + // we reset the page to 1, because we are deleting our results as we go. Therefore, increasing the page number would skip some results. + $page = 1; $itemsPerPage = 10; $removedItems = false; @@ -1030,16 +1033,16 @@ public static function removeUserBookingsByEmail( string $emailAddress, $page = 'done' => true, ); } - foreach ($bookings as $booking) { + foreach ( $bookings as $booking ) { $bookingID = $booking->ID; - //exclude bookings that the user is eligible to see but are not their own + // exclude bookings that the user is eligible to see but are not their own // we are only concerned about one user's personal data if ( $booking->getUserData()->user_email !== $emailAddress ) { continue; } - //Cancel the booking before deletion so that status change emails are sent + // Cancel the booking before deletion so that status change emails are sent $booking->cancel(); - //Delete the booking + // Delete the booking wp_delete_post( $bookingID, true ); $removedItems = true; } @@ -1053,21 +1056,21 @@ public static function removeUserBookingsByEmail( string $emailAddress, $page = ); } - /** - * Returns the user that a specific booking is for if booking exists, otherwise returns current user. - * The post_author of a booking is always who the booking is for but not always the one who MADE the booking. - * A booking can be created by an admin but still be for a different user. - * This is helper function - * - * @return int|string - */ - public static function getFrontendBookingUser() { - global $post; - if ( $post ) { - $authorID = $post->post_author; - } else { - $authorID = get_current_user_id(); - } - return $authorID; - } + /** + * Returns the user that a specific booking is for if booking exists, otherwise returns current user. + * The post_author of a booking is always who the booking is for but not always the one who MADE the booking. + * A booking can be created by an admin but still be for a different user. + * This is helper function + * + * @return int|string + */ + public static function getFrontendBookingUser() { + global $post; + if ( $post ) { + $authorID = $post->post_author; + } else { + $authorID = get_current_user_id(); + } + return $authorID; + } } diff --git a/src/Wordpress/CustomPostType/CustomPostType.php b/src/Wordpress/CustomPostType/CustomPostType.php index c68aceddc..493f4633c 100644 --- a/src/Wordpress/CustomPostType/CustomPostType.php +++ b/src/Wordpress/CustomPostType/CustomPostType.php @@ -41,7 +41,7 @@ abstract class CustomPostType { * @return string */ public static function getWPAction(): string { - return static::getPostType() . "-custom-fields"; + return static::getPostType() . '-custom-fields'; } /** @@ -55,7 +55,7 @@ public static function getPostType(): string { * @return string */ public static function getWPNonceId(): string { - return static::getPostType() . "-custom-fields" . '_wpnonce'; + return static::getPostType() . '-custom-fields' . '_wpnonce'; } /** @@ -79,12 +79,10 @@ public static function sanitizeOptions( $data ) { $key = $item->ID; $label = $item->post_title . $statusLabel; - } - elseif ( $item instanceof \WP_Term){ - $key = $item->term_id; + } elseif ( $item instanceof \WP_Term ) { + $key = $item->term_id; $label = $item->name . ' (' . $item->slug . ')'; - } - else { + } else { $label = $item; } $options[ $key ] = $label; @@ -96,7 +94,7 @@ public static function sanitizeOptions( $data ) { /** * retrieve Custom Meta Data from CommonsBooking Options and convert them to cmb2 fields array - * The content is managed by user via options -> metadata sets + * The content is managed by user via options -> metadata sets * * @param mixed $type (item or location) * @@ -111,8 +109,7 @@ public static function getCMB2FieldsArrayFromCustomMetadata( $type ): ?array { foreach ( $metaDataLines as $metaDataLine ) { $metaDataArray = explode( ';', $metaDataLine ); - if ( count( $metaDataArray ) == 5 ) - { + if ( count( $metaDataArray ) == 5 ) { // $metaDataArray[0] = Type $metaDataFields[ $metaDataArray[0] ][] = array( 'id' => $metaDataArray[1], @@ -123,8 +120,8 @@ public static function getCMB2FieldsArrayFromCustomMetadata( $type ): ?array { } } - //allows to programmatically add custom metaboxes - $metaDataFields = apply_filters('commonsbooking_custom_metadata', $metaDataFields); + // allows to programmatically add custom metaboxes + $metaDataFields = apply_filters( 'commonsbooking_custom_metadata', $metaDataFields ); if ( array_key_exists( $type, $metaDataFields ) ) { return $metaDataFields[ $type ]; @@ -143,14 +140,14 @@ public static function getCMB2FieldsArrayFromCustomMetadata( $type ): ?array { public static function modifyRowActions( $actions, $post ) { // remove quick edit for timeframes, restrictions and bookings - if ( $post->post_type == Timeframe::getPostType() - OR $post->post_type == Restriction::getPostType() - OR $post->post_type == Booking::getPostType()) { + if ( $post->post_type == Timeframe::getPostType() + or $post->post_type == Restriction::getPostType() + or $post->post_type == Booking::getPostType() ) { unset( $actions['inline hide-if-no-js'] ); } // remove preview for timeframes and restrictions - if ( $post->post_type == Timeframe::getPostType() OR $post->post_type == Restriction::getPostType() ) { + if ( $post->post_type == Timeframe::getPostType() or $post->post_type == Restriction::getPostType() ) { unset( $actions['view'] ); } @@ -164,6 +161,7 @@ abstract public static function getView(); /** * Returns param for backend menu. + * * @return array */ public function getMenuParams() { @@ -174,7 +172,7 @@ public function getMenuParams() { 'manage_' . COMMONSBOOKING_PLUGIN_SLUG, 'edit.php?post_type=' . static::getPostType(), '', - $this->menuPosition ?: null + $this->menuPosition ?: null, ]; } @@ -219,23 +217,29 @@ public function setSortableColumns( $columns ) { * Removes title column from backend listing. */ public function removeListTitleColumn() { - add_filter( 'manage_' . static::getPostType() . '_posts_columns', function ( $columns ) { - unset( $columns['title'] ); + add_filter( + 'manage_' . static::getPostType() . '_posts_columns', + function ( $columns ) { + unset( $columns['title'] ); - return $columns; - } ); + return $columns; + } + ); } /** * Removes date column from backend listing. */ public function removeListDateColumn() { - add_filter( 'manage_' . static::getPostType() . '_posts_columns', function ( $columns ) { - unset( $columns['date'] ); - unset ( $columns['author'] ); // = 'Nutzer*in'; + add_filter( + 'manage_' . static::getPostType() . '_posts_columns', + function ( $columns ) { + unset( $columns['date'] ); + unset( $columns['author'] ); // = 'Nutzer*in'; - return $columns; - } ); + return $columns; + } + ); } /** @@ -247,38 +251,49 @@ abstract public function initHooks(); * Configures list-view */ public function initListView() { - if ( array_key_exists('post_type', $_GET) && static::$postType !== $_GET['post_type'] ) { + if ( array_key_exists( 'post_type', $_GET ) && static::$postType !== $_GET['post_type'] ) { return; } // List-View add_filter( 'manage_' . static::getPostType() . '_posts_columns', array( $this, 'setCustomColumns' ) ); - add_action( 'manage_' . static::getPostType() . '_posts_custom_column', array( - $this, - 'setCustomColumnsData' - ), 10, - 2 ); - add_filter( 'manage_edit-' . static::getPostType() . '_sortable_columns', array( - $this, - 'setSortableColumns' - ) ); + add_action( + 'manage_' . static::getPostType() . '_posts_custom_column', + array( + $this, + 'setCustomColumnsData', + ), + 10, + 2 + ); + add_filter( + 'manage_edit-' . static::getPostType() . '_sortable_columns', + array( + $this, + 'setSortableColumns', + ) + ); if ( isset( $this->listColumns ) ) { add_action( 'pre_get_posts', array( $this, 'setCustomColumnSortOrder' ) ); } // add ability to use WP_QUERY orderby for post_status - add_filter('posts_orderby', function ($args, $wp_query) { - if(isset ($wp_query->query_vars['orderby']) && $wp_query->query_vars['orderby'] == 'post_status') { - if($wp_query->query_vars['order']) { - return 'post_status '.$wp_query->query_vars['order']; - } - else { - return 'post_status ASC'; + add_filter( + 'posts_orderby', + function ( $args, $wp_query ) { + if ( isset( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] == 'post_status' ) { + if ( $wp_query->query_vars['order'] ) { + return 'post_status ' . $wp_query->query_vars['order']; + } else { + return 'post_status ASC'; + } } - } - return $args; - }, 10,2); + return $args; + }, + 10, + 2 + ); } /** @@ -290,25 +305,24 @@ public function initListView() { public function setCustomColumnsData( $column, $post_id ) { if ( $value = get_post_meta( $post_id, $column, true ) ) { - echo commonsbooking_sanitizeHTML($value); + echo commonsbooking_sanitizeHTML( $value ); + } elseif ( property_exists( $post = get_post( $post_id ), $column ) ) { + echo commonsbooking_sanitizeHTML( $post->{$column} ); } else { - if ( property_exists( $post = get_post( $post_id ), $column ) ) { - echo commonsbooking_sanitizeHTML($post->{$column}); - } else { - echo '-'; - } + echo '-'; } } /** * Adds Category filter to backend list view - * */ public static function addAdminCategoryFilter() { $values = []; - $terms = get_terms(array( - 'taxonomy' => static::$postType . 's_category' - )); + $terms = get_terms( + array( + 'taxonomy' => static::$postType . 's_category', + ) + ); foreach ( $terms as $term ) { $values[ $term->term_id ] = $term->name; } @@ -322,15 +336,16 @@ public static function addAdminCategoryFilter() { /** * Checks if method has been called before in current request. + * * @param $methodName * * @return bool */ - protected function hasRunBefore($methodName): bool { - if(array_key_exists($methodName, $_REQUEST)) { + protected function hasRunBefore( $methodName ): bool { + if ( array_key_exists( $methodName, $_REQUEST ) ) { return true; } - $_REQUEST[$methodName] = true; + $_REQUEST[ $methodName ] = true; return false; } @@ -346,27 +361,27 @@ public static function getModel( $post ) { if ( $post instanceof CustomPost ) { return $post; } - if (is_int($post)) { - $post = get_post($post); + if ( is_int( $post ) ) { + $post = get_post( $post ); } - if (! $post instanceof WP_Post) { - throw new PostException('No suitable post object.'); + if ( ! $post instanceof WP_Post ) { + throw new PostException( 'No suitable post object.' ); } - switch($post->post_type) { + switch ( $post->post_type ) { case Booking::$postType: - return new \CommonsBooking\Model\Booking($post); + return new \CommonsBooking\Model\Booking( $post ); case Item::$postType: - return new \CommonsBooking\Model\Item($post); + return new \CommonsBooking\Model\Item( $post ); case Location::$postType: - return new \CommonsBooking\Model\Location($post); + return new \CommonsBooking\Model\Location( $post ); case Restriction::$postType: - return new \CommonsBooking\Model\Restriction($post); + return new \CommonsBooking\Model\Restriction( $post ); case Timeframe::$postType: - return new \CommonsBooking\Model\Timeframe($post); + return new \CommonsBooking\Model\Timeframe( $post ); case Map::$postType: - return new \CommonsBooking\Model\Map($post); + return new \CommonsBooking\Model\Map( $post ); } - throw new PostException('No suitable model found for ' . $post->post_type); + throw new PostException( 'No suitable model found for ' . $post->post_type ); } /** @@ -384,5 +399,4 @@ public function setCustomColumnSortOrder( \WP_Query $query ) { } return true; } - } diff --git a/src/Wordpress/CustomPostType/Item.php b/src/Wordpress/CustomPostType/Item.php index 5b5b43096..d3077bbd6 100644 --- a/src/Wordpress/CustomPostType/Item.php +++ b/src/Wordpress/CustomPostType/Item.php @@ -22,7 +22,7 @@ public function initHooks() { // Listing of locations for item add_shortcode( 'cb_locations', array( \CommonsBooking\View\Location::class, 'shortcode' ) ); - //Add filter to backend list view + // Add filter to backend list view add_action( 'restrict_manage_posts', array( self::class, 'addAdminCategoryFilter' ) ); // Filter only for current user allowed posts @@ -34,15 +34,16 @@ public function initHooks() { /** * Handles the creation and editing of the terms in the taxonomy for the location post type + * * @param $term_id * @param $tt_id * @param $taxonomy * * @return void */ - public static function termChange($term_id, $tt_id, $taxonomy) { + public static function termChange( $term_id, $tt_id, $taxonomy ) { if ( $taxonomy == self::$postType . 's_category' ) { - //update all dynamic timeframes + // update all dynamic timeframes Timeframe::updateAllTimeframes(); } } @@ -50,9 +51,9 @@ public static function termChange($term_id, $tt_id, $taxonomy) { /** * Handles save-Request for items. */ - public function savePost($post_id, \WP_Post $post) { + public function savePost( $post_id, \WP_Post $post ) { if ( $post->post_type == self::$postType && $post_id ) { - //update all dynamic timeframes + // update all dynamic timeframes Timeframe::updateAllTimeframes(); } } @@ -91,11 +92,11 @@ function ( &$item, $key ) { $_GET['admin_filter_post_category'] != '' ) { $query->query_vars['tax_query'] = array( - array( - 'taxonomy' => self::$postType . 's_category', - 'field' => 'term_id', - 'terms' => $_GET['admin_filter_post_category'] - ) + array( + 'taxonomy' => self::$postType . 's_category', + 'field' => 'term_id', + 'terms' => $_GET['admin_filter_post_category'], + ), ); } } @@ -107,6 +108,7 @@ public static function getView() { /** * Returns CPT args. + * * @return array */ public function getArgs(): array { @@ -183,7 +185,6 @@ public function getArgs(): array { 'author', ), - // Soll der Post Type Kategorien haben? 'taxonomies' => array( self::$postType . 's_category' ), @@ -202,17 +203,17 @@ public function getArgs(): array { } public function getTemplate( $content ) { - $cb_content = ''; + $cb_content = ''; $errormessage = ''; if ( is_singular( self::getPostType() ) && is_main_query() && get_post_type() == self::getPostType() ) { ob_start(); global $post; - $item = new \CommonsBooking\Model\Item( $post ); + $item = new \CommonsBooking\Model\Item( $post ); $errormessage = \CommonsBooking\View\Booking::getError(); set_query_var( 'item', $item ); commonsbooking_get_template_part( 'item', 'single' ); - $cb_content = ob_get_clean(); + $cb_content = ob_get_clean(); } return $errormessage . $content . $cb_content; @@ -226,45 +227,52 @@ public function getTemplate( $content ) { */ public function registerMetabox() { // Initiate the metabox Adress - $cmb = new_cmb2_box( array( - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_info', - 'title' => esc_html__( 'Item Info', 'commonsbooking' ), - 'object_types' => array( self::$postType ), // Post type - 'context' => 'normal', - 'priority' => 'high', - 'show_names' => true, // Show field names on the left - ) ); - + $cmb = new_cmb2_box( + array( + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_info', + 'title' => esc_html__( 'Item Info', 'commonsbooking' ), + 'object_types' => array( self::$postType ), // Post type + 'context' => 'normal', + 'priority' => 'high', + 'show_names' => true, // Show field names on the left + ) + ); // Show selection only to admins if ( commonsbooking_isCurrentUserAdmin() || commonsbooking_isCurrentUserCBManager() ) { $users = UserRepository::getSelectableCBManagers(); $userOptions = []; foreach ( $users as $user ) { - $userOptions[ $user->ID ] = $user->get( 'user_nicename' ) . " (" . $user->first_name . " " . $user->last_name . ")"; + $userOptions[ $user->ID ] = $user->get( 'user_nicename' ) . ' (' . $user->first_name . ' ' . $user->last_name . ')'; } - //Item Administrators - $cmb->add_field( array( - 'name' => esc_html__( 'Item Admin(s)', 'commonsbooking' ), - 'desc' => esc_html__( 'choose one or more users to give them the permisssion to edit and manage this specific item. Only users with the role cb_manager can be selected here', 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_admins', - 'type' => 'pw_multiselect', - 'options' => $userOptions, - 'attributes' => array( - 'placeholder' => esc_html__( 'Select item admins.', 'commonsbooking' ) - ), - ) ); + // Item Administrators + $cmb->add_field( + array( + 'name' => esc_html__( 'Item Admin(s)', 'commonsbooking' ), + 'desc' => esc_html__( 'choose one or more users to give them the permisssion to edit and manage this specific item. Only users with the role cb_manager can be selected here', 'commonsbooking' ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_admins', + 'type' => 'pw_multiselect', + 'options' => $userOptions, + 'attributes' => array( + 'placeholder' => esc_html__( 'Select item admins.', 'commonsbooking' ), + ), + ) + ); // item maintainer(s) emails - $cmb->add_field( array( - 'name' => esc_html__( 'Item maintainer email', 'commonsbooking' ), - 'desc' => esc_html__( 'Email addresses to which notifications about a change of item status (restriction, breakdown) shall be sent. You can enter multiple addresses separated by commas.', - 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_maintainer_email', - 'type' => 'text', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Item maintainer email', 'commonsbooking' ), + 'desc' => esc_html__( + 'Email addresses to which notifications about a change of item status (restriction, breakdown) shall be sent. You can enter multiple addresses separated by commas.', + 'commonsbooking' + ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_maintainer_email', + 'type' => 'text', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); } // Check if custom meta fields are set in CB Options and generate MetaData-Box and fields @@ -272,27 +280,28 @@ public function registerMetabox() { $customMetaData = self::getCMB2FieldsArrayFromCustomMetadata( 'item' ); // Initiate the metabox Adress - $cmb = new_cmb2_box( array( - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_custom_meta', - 'title' => esc_html__( 'Item Meta-Data', 'commonsbooking' ), - 'object_types' => array( self::$postType ), // Post type - 'context' => 'normal', - 'priority' => 'high', - 'show_names' => true, // Show field names on the left - ) ); + $cmb = new_cmb2_box( + array( + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'item_custom_meta', + 'title' => esc_html__( 'Item Meta-Data', 'commonsbooking' ), + 'object_types' => array( self::$postType ), // Post type + 'context' => 'normal', + 'priority' => 'high', + 'show_names' => true, // Show field names on the left + ) + ); // Add Custom Meta Fields defined in CommonsBooking Options (Tab MetaData) foreach ( $customMetaData as $customMetaDataField ) { $cmb->add_field( $customMetaDataField ); } - } // we store registered metaboxes to options table to be able to retrieve it in export function $metabox_fields = []; - foreach ($cmb->meta_box['fields'] as $metabox_field) { - $metabox_fields[$metabox_field['id']] = $metabox_field['name']; + foreach ( $cmb->meta_box['fields'] as $metabox_field ) { + $metabox_fields[ $metabox_field['id'] ] = $metabox_field['name']; } - Settings::updateOption('commonsbooking_settings_metaboxfields', $this->getPostType(), $metabox_fields); + Settings::updateOption( 'commonsbooking_settings_metaboxfields', $this->getPostType(), $metabox_fields ); } -} \ No newline at end of file +} diff --git a/src/Wordpress/CustomPostType/Location.php b/src/Wordpress/CustomPostType/Location.php index 179165d9f..40c7bb6e5 100644 --- a/src/Wordpress/CustomPostType/Location.php +++ b/src/Wordpress/CustomPostType/Location.php @@ -20,7 +20,7 @@ public function initHooks() { // Listing of items for location add_shortcode( 'cb_items', array( \CommonsBooking\View\Item::class, 'shortcode' ) ); - //Add filter to backend list view + // Add filter to backend list view add_action( 'restrict_manage_posts', array( self::class, 'addAdminCategoryFilter' ) ); // Filter only for current user allowed posts @@ -33,27 +33,28 @@ public function initHooks() { /** * Handles save-Request for location. */ - public function savePost($post_id, \WP_Post $post) { + public function savePost( $post_id, \WP_Post $post ) { if ( $post->post_type == self::$postType && $post_id ) { $location = new \CommonsBooking\Model\Location( intval( $post_id ) ); $location->updateGeoLocation(); - //update all dynamic timeframes + // update all dynamic timeframes Timeframe::updateAllTimeframes(); } } /** * Handles the creation and editing of the terms in the taxonomy for the location post type + * * @param $term_id * @param $tt_id * @param $taxonomy * * @return void */ - public static function termChange($term_id, $tt_id, $taxonomy) { + public static function termChange( $term_id, $tt_id, $taxonomy ) { if ( $taxonomy == self::$postType . 's_category' ) { - //update all dynamic timeframes + // update all dynamic timeframes Timeframe::updateAllTimeframes(); } } @@ -91,11 +92,11 @@ function ( &$item, $key ) { $_GET['admin_filter_post_category'] != '' ) { $query->query_vars['tax_query'] = array( - array( - 'taxonomy' => self::$postType . 's_category', - 'field' => 'term_id', - 'terms' => $_GET['admin_filter_post_category'] - ) + array( + 'taxonomy' => self::$postType . 's_category', + 'field' => 'term_id', + 'terms' => $_GET['admin_filter_post_category'], + ), ); } } @@ -186,7 +187,7 @@ public function getArgs() { 'custom-fields', 'revisions', 'excerpt', - 'author' + 'author', ), // Soll der Post Type Kategien haben? @@ -214,157 +215,192 @@ public function getArgs() { */ public function registerMetabox() { // Initiate the metabox address - $cmb = new_cmb2_box( array( - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_adress', - 'title' => esc_html__( 'Address', 'commonsbooking' ), - 'object_types' => array( self::$postType ), // Post type - 'context' => 'normal', - 'priority' => 'high', - 'show_names' => true, // Show field names on the left - ) ); + $cmb = new_cmb2_box( + array( + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_adress', + 'title' => esc_html__( 'Address', 'commonsbooking' ), + 'object_types' => array( self::$postType ), // Post type + 'context' => 'normal', + 'priority' => 'high', + 'show_names' => true, // Show field names on the left + ) + ); // Adress - $cmb->add_field( array( - 'name' => esc_html__( 'Street / No.', 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_street', - 'type' => 'text', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - 'attributes' => array( - 'required' => 'required', - ), - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Street / No.', 'commonsbooking' ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_street', + 'type' => 'text', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + 'attributes' => array( + 'required' => 'required', + ), + ) + ); // Postcode - $cmb->add_field( array( - 'name' => esc_html__( 'Postcode', 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_postcode', - 'type' => 'text', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - 'attributes' => array( - 'required' => 'required', - ), - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Postcode', 'commonsbooking' ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_postcode', + 'type' => 'text', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + 'attributes' => array( + 'required' => 'required', + ), + ) + ); // City - $cmb->add_field( array( - 'name' => esc_html__( 'City', 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_city', - 'type' => 'text', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - 'attributes' => array( - 'required' => 'required', - ), - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'City', 'commonsbooking' ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_city', + 'type' => 'text', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + 'attributes' => array( + 'required' => 'required', + ), + ) + ); // Country - $cmb->add_field( array( - 'name' => esc_html__( 'Country', 'commonsbooking' ), - //'desc' => esc_html__('field description (optional)', 'commonsbooking'), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_country', - 'type' => 'text', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Country', 'commonsbooking' ), + // 'desc' => esc_html__('field description (optional)', 'commonsbooking'), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_country', + 'type' => 'text', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); // Generate Geo-Coordinates - $cmb->add_field( array( - 'name' => esc_html__( 'Set / Update GPS and map', 'commonsbooking' ), - //'desc' => esc_html__('field description (optional)', 'commonsbooking'), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'get_gps', - 'type' => 'text', - 'render_row_cb' => array( Map::class, 'renderGeoRefreshButton' ), - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); - + $cmb->add_field( + array( + 'name' => esc_html__( 'Set / Update GPS and map', 'commonsbooking' ), + // 'desc' => esc_html__('field description (optional)', 'commonsbooking'), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'get_gps', + 'type' => 'text', + 'render_row_cb' => array( Map::class, 'renderGeoRefreshButton' ), + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); // Latitude - $cmb->add_field( array( - 'name' => esc_html__( 'Latitude', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __('The latitude is calculated automatically when you click the "set / update GPS" button after entering the street, postal code and city.', 'commonsbooking') ), - 'id' => 'geo_latitude', - 'type' => 'text', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Latitude', 'commonsbooking' ), + 'desc' => commonsbooking_sanitizeHTML( __( 'The latitude is calculated automatically when you click the "set / update GPS" button after entering the street, postal code and city.', 'commonsbooking' ) ), + 'id' => 'geo_latitude', + 'type' => 'text', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); // Longitude - $cmb->add_field( array( - 'name' => esc_html__( 'Longitude', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __('The longitude is calculated automatically when you click the "set / update GPS" button after entering the street, postal code and city.', 'commonsbooking') ), - 'id' => 'geo_longitude', - 'type' => 'text', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Longitude', 'commonsbooking' ), + 'desc' => commonsbooking_sanitizeHTML( __( 'The longitude is calculated automatically when you click the "set / update GPS" button after entering the street, postal code and city.', 'commonsbooking' ) ), + 'id' => 'geo_longitude', + 'type' => 'text', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); // Map - $cmb->add_field( array( - 'name' => esc_html__( 'Position', 'commonsbooking' ), - //'desc' => esc_html__('field description (optional)', 'commonsbooking'), - 'id' => COMMONSBOOKING_METABOX_PREFIX . '_map_position', - 'type' => 'cb_map', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Position', 'commonsbooking' ), + // 'desc' => esc_html__('field description (optional)', 'commonsbooking'), + 'id' => COMMONSBOOKING_METABOX_PREFIX . '_map_position', + 'type' => 'cb_map', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); // Show map on item view checkbox - $cmb->add_field( array( - 'name' => esc_html__( 'Show location map on item view', 'commonsbooking' ), - 'desc' => esc_html__('If enabled, a map showing the location will be displayed on the location details page.', 'commonsbooking'), - 'id' => 'loc_showmap', - 'type' => 'checkbox', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Show location map on item view', 'commonsbooking' ), + 'desc' => esc_html__( 'If enabled, a map showing the location will be displayed on the location details page.', 'commonsbooking' ), + 'id' => 'loc_showmap', + 'type' => 'checkbox', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); // Initiate the metabox Information - $cmb = new_cmb2_box( array( - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_info', - 'title' => esc_html__( 'General Location information', 'commonsbooking' ), - 'object_types' => array( self::$postType ), // Post type - 'context' => 'normal', - 'priority' => 'high', - 'show_names' => true, // Show field names on the left - ) ); + $cmb = new_cmb2_box( + array( + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_info', + 'title' => esc_html__( 'General Location information', 'commonsbooking' ), + 'object_types' => array( self::$postType ), // Post type + 'context' => 'normal', + 'priority' => 'high', + 'show_names' => true, // Show field names on the left + ) + ); // location email - $cmb->add_field( array( - 'name' => esc_html__( 'Location email', 'commonsbooking' ), - 'desc' => esc_html__( 'Email addresses of the owner of the station. Can be reminded about bookings / cancellations and will receive the booking codes (when configured in the timeframe). You can enter multiple addresses separated by commas.', - 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_email', - 'type' => 'text', - 'attributes' => array( - 'class' => "regular-text cmb2-oembed", - ), - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + $cmb->add_field( + array( + 'name' => esc_html__( 'Location email', 'commonsbooking' ), + 'desc' => esc_html__( + 'Email addresses of the owner of the station. Can be reminded about bookings / cancellations and will receive the booking codes (when configured in the timeframe). You can enter multiple addresses separated by commas.', + 'commonsbooking' + ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_email', + 'type' => 'text', + 'attributes' => array( + 'class' => 'regular-text cmb2-oembed', + ), + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value // 'repeatable' => true, - ) ); + ) + ); // checkbox BCC bookings / cancellations to location email - $cmb->add_field( array( - 'name' => esc_html__( 'Send copy of bookings / cancellations to location email', 'commonsbooking' ), - 'desc' => esc_html__( 'If enabled, the location email will receive a copy of all booking and cancellation notifications.', 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', - 'type' => 'checkbox', - 'default_cb' => 'cmb2_set_checkbox_default_for_new_post' - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Send copy of bookings / cancellations to location email', 'commonsbooking' ), + 'desc' => esc_html__( 'If enabled, the location email will receive a copy of all booking and cancellation notifications.', 'commonsbooking' ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_email_bcc', + 'type' => 'checkbox', + 'default_cb' => 'cmb2_set_checkbox_default_for_new_post', + ) + ); // pickup description - $cmb->add_field( array( - 'name' => esc_html__( 'Pickup instructions', 'commonsbooking' ), - 'desc' => esc_html__( 'Type in information about the pickup process (e.g. detailed route description, opening hours, etc.). This will be shown to user in booking process and booking confirmation mail', - 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_pickupinstructions', - 'type' => 'textarea_small', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + $cmb->add_field( + array( + 'name' => esc_html__( 'Pickup instructions', 'commonsbooking' ), + 'desc' => esc_html__( + 'Type in information about the pickup process (e.g. detailed route description, opening hours, etc.). This will be shown to user in booking process and booking confirmation mail', + 'commonsbooking' + ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_pickupinstructions', + 'type' => 'textarea_small', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value // 'repeatable' => true, - ) ); + ) + ); // location contact - $cmb->add_field( array( - 'name' => esc_html__( 'Location contact information', 'commonsbooking' ), - 'desc' => esc_html__( 'information about how to contact the location (e.g. contact person, phone number, e-mail etc.). This will be shown to user in booking process and booking confirmation mail', - 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_contact', - 'type' => 'textarea_small', - 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Location contact information', 'commonsbooking' ), + 'desc' => esc_html__( + 'information about how to contact the location (e.g. contact person, phone number, e-mail etc.). This will be shown to user in booking process and booking confirmation mail', + 'commonsbooking' + ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_contact', + 'type' => 'textarea_small', + 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value + ) + ); // Show selection only to admins if ( commonsbooking_isCurrentUserAdmin() || commonsbooking_isCurrentUserCBManager() ) { @@ -372,74 +408,85 @@ public function registerMetabox() { $users = UserRepository::getSelectableCBManagers(); $userOptions = []; foreach ( $users as $user ) { - $userOptions[ $user->ID ] = $user->get( 'user_nicename' ) . " (" . $user->first_name . " " . $user->last_name . ")"; + $userOptions[ $user->ID ] = $user->get( 'user_nicename' ) . ' (' . $user->first_name . ' ' . $user->last_name . ')'; } - $cmb->add_field( array( - 'name' => esc_html__( 'Location Admin(s)', 'commonsbooking' ), - 'desc' => esc_html__( 'choose one or more users to give them the permisssion to edit and manage this specific location. Only users with the role CommonsBooking Manager can be selected here.', - 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_admins', - 'type' => 'pw_multiselect', - 'options' => $userOptions, - 'attributes' => array( - 'placeholder' => esc_html__( 'Select location admins.', 'commonsbooking' ) - ), - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Location Admin(s)', 'commonsbooking' ), + 'desc' => esc_html__( + 'choose one or more users to give them the permisssion to edit and manage this specific location. Only users with the role CommonsBooking Manager can be selected here.', + 'commonsbooking' + ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_admins', + 'type' => 'pw_multiselect', + 'options' => $userOptions, + 'attributes' => array( + 'placeholder' => esc_html__( 'Select location admins.', 'commonsbooking' ), + ), + ) + ); } - $cmb->add_field( array ( - 'name' => esc_html__( 'Use global location settings', 'commonsbooking' ), - 'desc' => esc_html__( 'If selected, the global location settings (under the "General" tab) will be used for this location. If not selected, the settings below will be used.', 'commonsbooking' ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'use_global_settings', - 'type' => 'checkbox', - 'default_cb' => 'cmb2_set_checkbox_default_for_new_post', - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Use global location settings', 'commonsbooking' ), + 'desc' => esc_html__( 'If selected, the global location settings (under the "General" tab) will be used for this location. If not selected, the settings below will be used.', 'commonsbooking' ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'use_global_settings', + 'type' => 'checkbox', + 'default_cb' => 'cmb2_set_checkbox_default_for_new_post', + ) + ); foreach ( self::getOverbookingSettingsMetaboxes() as $metabox ) { $cmb->add_field( $metabox ); } - $cmb->add_field( array( - 'name' => esc_html__( 'Receive booking start reminder', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __( 'If selected, this location receives reminder emails of bookings starting soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings.', 'commonsbooking' ) ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'receive_booking_start_reminder', - 'type' => 'checkbox', - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Receive booking start reminder', 'commonsbooking' ), + 'desc' => commonsbooking_sanitizeHTML( __( 'If selected, this location receives reminder emails of bookings starting soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings.', 'commonsbooking' ) ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'receive_booking_start_reminder', + 'type' => 'checkbox', + ) + ); - $cmb->add_field( array( - 'name' => esc_html__( 'Receive booking end reminder', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __( 'If selected, this location receives reminder emails of bookings ending soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings.', 'commonsbooking' ) ), - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'receive_booking_end_reminder', - 'type' => 'checkbox', - ) ); + $cmb->add_field( + array( + 'name' => esc_html__( 'Receive booking end reminder', 'commonsbooking' ), + 'desc' => commonsbooking_sanitizeHTML( __( 'If selected, this location receives reminder emails of bookings ending soon. The notifications are sent to all addresses specified in the location email list (first as receiver, all following as BCC). This type of reminder needs to be activated in the general CommonsBooking settings.', 'commonsbooking' ) ), + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'receive_booking_end_reminder', + 'type' => 'checkbox', + ) + ); // Check if custom meta fields are set in CB Options and generate MetaData-Box and fields if ( is_array( self::getCMB2FieldsArrayFromCustomMetadata( 'location' ) ) ) { $customMetaData = self::getCMB2FieldsArrayFromCustomMetadata( 'location' ); // Initiate the metabox Adress - $cmb = new_cmb2_box( array( - 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_custom_meta', - 'title' => esc_html__( 'Location Meta-Data', 'commonsbooking' ), - 'object_types' => array( self::$postType ), // Post type - 'context' => 'normal', - 'priority' => 'high', - 'show_names' => true, // Show field names on the left - ) ); + $cmb = new_cmb2_box( + array( + 'id' => COMMONSBOOKING_METABOX_PREFIX . 'location_custom_meta', + 'title' => esc_html__( 'Location Meta-Data', 'commonsbooking' ), + 'object_types' => array( self::$postType ), // Post type + 'context' => 'normal', + 'priority' => 'high', + 'show_names' => true, // Show field names on the left + ) + ); // Add Custom Meta Fields defined in CommonsBooking Options (Tab MetaData) foreach ( $customMetaData as $customMetaDataField ) { $cmb->add_field( $customMetaDataField ); } - } // we store registered metaboxes to options table to be able to retrieve it in export function $metabox_fields = []; - foreach ($cmb->meta_box['fields'] as $metabox_field) { - $metabox_fields[$metabox_field['id']] = $metabox_field['name']; + foreach ( $cmb->meta_box['fields'] as $metabox_field ) { + $metabox_fields[ $metabox_field['id'] ] = $metabox_field['name']; } - Settings::updateOption('commonsbooking_settings_metaboxfields', $this->getPostType(), $metabox_fields); + Settings::updateOption( 'commonsbooking_settings_metaboxfields', $this->getPostType(), $metabox_fields ); } /** @@ -468,9 +515,7 @@ public static function getOverbookingSettingsMetaboxes() { 'id' => COMMONSBOOKING_METABOX_PREFIX . 'count_lockdays_maximum', 'default' => '0', 'type' => 'text_small', - ) + ), ]; - } - } diff --git a/src/Wordpress/CustomPostType/Map.php b/src/Wordpress/CustomPostType/Map.php index e08886057..c1bb33f95 100644 --- a/src/Wordpress/CustomPostType/Map.php +++ b/src/Wordpress/CustomPostType/Map.php @@ -3,7 +3,6 @@ namespace CommonsBooking\Wordpress\CustomPostType; - use CommonsBooking\Map\MapShortcode; use CommonsBooking\Repository\CB1; use CommonsBooking\Repository\Item; @@ -24,7 +23,7 @@ class Map extends CustomPostType { * Is used when no other coordinates are set. * These are currently the coordinates of Cologne, Germany. */ - const LATITUDE_DEFAULT = 50.937531; + const LATITUDE_DEFAULT = 50.937531; const LONGITUDE_DEFAULT = 6.960279; /** @@ -41,13 +40,12 @@ public function initHooks() { public function registerMetabox() { $cmb = new_cmb2_box( [ - 'id' => static::getPostType() . "-custom-fields", + 'id' => static::getPostType() . '-custom-fields', 'title' => esc_html__( 'Map settings', 'commonsbooking' ), 'object_types' => array( static::getPostType() ), ] ); - foreach ( self::getCustomFields() as $customField ) { $cmb->add_field( $customField ); } @@ -65,12 +63,12 @@ public static function getCustomFields(): array { 'type' => 'text', 'id' => 'shortcode', ), - //Begin group presentation + // Begin group presentation array( 'name' => esc_html__( 'Presentation', 'commonsbooking' ), 'type' => 'title', 'id' => 'presentation_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'base map', 'commonsbooking' ), @@ -79,7 +77,7 @@ public static function getCustomFields(): array { 'type' => 'select', 'options' => array( '1' => esc_html__( 'OSM - mapnik', 'commonsbooking' ), - '2' => esc_html__( 'OSM - german style', 'commonsbooking' ) + '2' => esc_html__( 'OSM - german style', 'commonsbooking' ), /* * Reenable the map styles if neede '3' => esc_html__( 'OSM - hike and bike', 'commonsbooking' ), @@ -118,12 +116,12 @@ public static function getCustomFields(): array { 'id' => 'enable_map_data_export', 'type' => 'checkbox', ), - //Begin group Zoom + // Begin group Zoom array( 'name' => esc_html__( 'Zoom', 'commonsbooking' ), 'type' => 'title', 'id' => 'zoom_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'min. zoom level', 'commonsbooking' ), @@ -136,7 +134,7 @@ public static function getCustomFields(): array { 'pattern' => '\d*', 'min' => '1', 'max' => '19', - ) + ), ), array( 'name' => esc_html__( 'max. zoom level', 'commonsbooking' ), @@ -149,7 +147,7 @@ public static function getCustomFields(): array { 'pattern' => '\d*', 'min' => '1', 'max' => '19', - ) + ), ), array( 'name' => esc_html__( 'start zoom level', 'commonsbooking' ), @@ -162,7 +160,7 @@ public static function getCustomFields(): array { 'pattern' => '\d*', 'min' => '1', 'max' => '19', - ) + ), ), array( 'name' => esc_html__( 'enable scroll wheel zoom', 'commonsbooking' ), @@ -171,13 +169,13 @@ public static function getCustomFields(): array { 'type' => 'checkbox', 'default_cb' => 'commonsbooking_cmb2_set_checkbox_default_for_new_post', ), - //End group Zoom - //Begin group Positioning + // End group Zoom + // Begin group Positioning array( 'name' => esc_html__( 'Positioning', 'commonsbooking' ), 'type' => 'title', 'id' => 'positioning_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'start latitude', 'commonsbooking' ), @@ -207,13 +205,13 @@ public static function getCustomFields(): array { 'type' => 'checkbox', 'default_cb' => 'commonsbooking_cmb2_set_checkbox_default_for_new_post', ), - //End group Positioning - //Begin group Tooltip + // End group Positioning + // Begin group Tooltip array( 'name' => esc_html__( 'Marker Tooltip', 'commonsbooking' ), 'type' => 'title', 'id' => 'marker_tooltip_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'Show marker tooltip permanently', 'commonsbooking' ), @@ -221,19 +219,19 @@ public static function getCustomFields(): array { 'id' => 'marker_tooltip_permanent', 'type' => 'checkbox', ), - //End group Tooltip - //Begin group popup + // End group Tooltip + // Begin group popup array( 'name' => esc_html__( 'Marker Popup', 'commonsbooking' ), 'type' => 'title', 'id' => 'marker_popup_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'show item availability', 'commonsbooking' ), 'desc' => esc_html__( 'activate to show the item availability in the marker popup', 'commonsbooking' ), 'id' => 'show_item_availability', - 'type' => 'checkbox' + 'type' => 'checkbox', ), array( 'name' => esc_html__( 'Max. available days in popup', 'commonsbooking' ), @@ -245,7 +243,7 @@ public static function getCustomFields(): array { 'type' => 'number', 'pattern' => '\d*', 'min' => '1', - ) + ), ), array( 'name' => esc_html__( 'Maximum days to choose in map availabilty filter ', 'commonsbooking' ), @@ -256,15 +254,15 @@ public static function getCustomFields(): array { 'attributes' => array( 'type' => 'number', 'pattern' => '\d*', - ) + ), ), - //End group popup - //Begin group custom marker + // End group popup + // Begin group custom marker array( 'name' => esc_html__( 'Custom Marker', 'commonsbooking' ), 'type' => 'title', 'id' => 'custom_marker_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'image file', 'commonsbooking' ), @@ -322,13 +320,13 @@ public static function getCustomFields(): array { 'pattern' => '\d*', ), ), - //End group custom marker - //Begin group cluster + // End group custom marker + // Begin group cluster array( 'name' => esc_html__( 'Cluster', 'commonsbooking' ), 'type' => 'title', 'id' => 'cluster_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'max. cluster radius', 'commonsbooking' ), @@ -340,7 +338,7 @@ public static function getCustomFields(): array { 'type' => 'number', 'pattern' => '\d*', 'min' => 0, - 'max' => 1000 + 'max' => 1000, ), ), array( @@ -379,13 +377,13 @@ public static function getCustomFields(): array { 'min' => '1', ), ), - //End group cluster - //Begin group Appearance + // End group cluster + // Begin group Appearance array( 'name' => esc_html__( 'Appearance by Item Status', 'commonsbooking' ), 'type' => 'title', 'id' => 'item_status_appearance_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'appearance', 'commonsbooking' ), @@ -455,13 +453,13 @@ public static function getCustomFields(): array { 'pattern' => '\d*', ), ), - //End group Appearance - //Begin group Filters + // End group Appearance + // Begin group Filters array( 'name' => esc_html__( 'Filter for Users', 'commonsbooking' ), 'type' => 'title', 'id' => 'filter_info', - 'classes' => 'map-organizer' + 'classes' => 'map-organizer', ), array( 'name' => esc_html__( 'show location distance filter', 'commonsbooking' ), @@ -476,7 +474,7 @@ public static function getCustomFields(): array { 'type' => 'text', 'attributes' => array( 'placeholder' => esc_html__( 'distance', 'commonsbooking' ), - ) + ), ), array( 'name' => esc_html__( 'address search bounds - left bottom', 'commonsbooking' ) . ' ' . esc_html__( 'longitude', 'commonsbooking' ), @@ -515,7 +513,7 @@ public static function getCustomFields(): array { 'type' => 'text', 'attributes' => array( 'placeholder' => esc_html__( 'availability', 'commonsbooking' ), - ) + ), ), array( 'name' => esc_html__( 'label for item category filter', 'commonsbooking' ), @@ -524,7 +522,7 @@ public static function getCustomFields(): array { 'type' => 'text', 'attributes' => array( 'placeholder' => esc_html__( 'categories', 'commonsbooking' ), - ) + ), ), array( 'name' => esc_html__( 'custom text for filter button', 'commonsbooking' ), @@ -533,7 +531,7 @@ public static function getCustomFields(): array { 'type' => 'text', 'attributes' => array( 'placeholder' => esc_html__( 'filter', 'commonsbooking' ), - ) + ), ), array( 'name' => commonsbooking_sanitizeHTML( __( 'Filter groups', 'commonsbooking' ) ), @@ -565,9 +563,9 @@ public static function getCustomFields(): array { 'postmeta' => commonsbooking_sanitizeHTML( __( 'Post-meta', 'commonsbooking' ) ), ), 'default' => 'taxonomy', - //TODO: disabled until postmeta is implemented + // TODO: disabled until postmeta is implemented 'attributes' => array( - 'disabled' => true + 'disabled' => true, ), ), array( @@ -586,9 +584,9 @@ public static function getCustomFields(): array { ), ), ), - //TODO: Add available categories & filtergroups - //End group Filters - //Begin group Presets + // TODO: Add available categories & filtergroups + // End group Filters + // Begin group Presets array( 'name' => esc_html__( 'Filter Item Presets', 'commonsbooking' ), 'desc' => esc_html__( 'select the categories that are used to prefilter the items that are shown on the map - none for all items', 'commonsbooking' ), @@ -605,7 +603,7 @@ public static function getCustomFields(): array { 'options' => CustomPostType::sanitizeOptions( Location::getTerms() ), 'select_all_button' => false, ), - //End group Presets + // End group Presets ); } @@ -669,17 +667,15 @@ public function getArgs() { /** * Renders the shortcode for the map - * */ public static function getShortcode( array $field_args, CMB2_Field $field ) { $id = get_the_ID(); ?> Shortcode:
        - [cb_map id=] - + [cb_map id=] +
        listColumns = [ @@ -54,12 +54,10 @@ public function __construct() { \CommonsBooking\Model\Restriction::META_ITEM_ID => esc_html__( 'Item', 'commonsbooking' ), \CommonsBooking\Model\Restriction::META_LOCATION_ID => esc_html__( 'Location', 'commonsbooking' ), \CommonsBooking\Model\Restriction::META_START => esc_html__( 'Start Date', 'commonsbooking' ), - \CommonsBooking\Model\Restriction::META_END => esc_html__( 'End Date', 'commonsbooking' ), + \CommonsBooking\Model\Restriction::META_END => esc_html__( 'End Date', 'commonsbooking' ), \CommonsBooking\Model\Restriction::META_STATE => esc_html__( 'Restriction Status', 'commonsbooking' ), ]; - - // List settings $this->removeListDateColumn(); } @@ -87,7 +85,7 @@ public static function addAdminItemFilter() { 'post_status' => 'any', 'orderby' => 'post_title', 'order' => 'asc', - 'nopaging' => true + 'nopaging' => true, ] ); if ( $items ) { @@ -97,7 +95,7 @@ public static function addAdminItemFilter() { } Filter::renderFilter( - static::$postType, + static::$postType, esc_html__( 'Filter By Item ', 'commonsbooking' ), 'filter_item', $values @@ -114,7 +112,7 @@ public static function addAdminLocationFilter() { 'post_status' => 'any', 'orderby' => 'post_title', 'order' => 'asc', - 'nopaging' => true + 'nopaging' => true, ] ); if ( $locations ) { @@ -133,7 +131,7 @@ public static function addAdminLocationFilter() { } /** - * Adds filter dropdown // filter by status in restrictions list + * Adds filter dropdown // filter by status in restrictions list */ public static function addAdminStatusFilter() { Filter::renderFilter( @@ -158,16 +156,16 @@ public function setCustomColumnsData( $column, $post_id ) { case \CommonsBooking\Model\Restriction::META_ITEM_ID: if ( $post = get_post( $value ) ) { if ( get_post_type( $post ) == Location::getPostType() || get_post_type( - $post - ) == Item::getPostType() ) { - echo commonsbooking_sanitizeHTML($post->post_title); + $post + ) == Item::getPostType() ) { + echo commonsbooking_sanitizeHTML( $post->post_title ); break; } } echo '-'; break; case \CommonsBooking\Model\Restriction::META_TYPE: - $output = "-"; + $output = '-'; foreach ( $this->getCustomFields() as $customField ) { if ( $customField['id'] == \CommonsBooking\Model\Restriction::META_TYPE ) { @@ -178,10 +176,10 @@ public function setCustomColumnsData( $column, $post_id ) { } } } - echo commonsbooking_sanitizeHTML($output); + echo commonsbooking_sanitizeHTML( $output ); break; case \CommonsBooking\Model\Restriction::META_STATE: - $output = "-"; + $output = '-'; foreach ( $this->getCustomFields() as $customField ) { if ( $customField['id'] == \CommonsBooking\Model\Restriction::META_STATE ) { @@ -192,14 +190,14 @@ public function setCustomColumnsData( $column, $post_id ) { } } } - echo commonsbooking_sanitizeHTML($output); + echo commonsbooking_sanitizeHTML( $output ); break; case \CommonsBooking\Model\Restriction::META_START: case \CommonsBooking\Model\Restriction::META_END: echo date( 'd.m.Y H:i', $value ); break; default: - echo commonsbooking_sanitizeHTML($value); + echo commonsbooking_sanitizeHTML( $value ); break; } } else { @@ -214,13 +212,13 @@ public function setCustomColumnsData( $column, $post_id ) { get_post_meta( $post_id, \CommonsBooking\Model\Restriction::META_TYPE, true ) == Timeframe::BOOKING_ID ) ) { - echo commonsbooking_sanitizeHTML($post->{$column}); + echo commonsbooking_sanitizeHTML( $post->{$column} ); } } } /** - * Filters admin list by type, timerange, user + * Filters admin list by type, timerange, user * * @param \WP_Query $query for admin list objects * @@ -231,7 +229,7 @@ public static function filterAdminList( $query ) { if ( is_admin() && $query->is_main_query() && - isset( $_GET['post_type'] ) && static::$postType == sanitize_text_field( $_GET['post_type'] ) && + isset( $_GET['post_type'] ) && static::$postType == sanitize_text_field( $_GET['post_type'] ) && $pagenow == 'edit.php' ) { // Meta value filtering @@ -240,14 +238,14 @@ public static function filterAdminList( $query ) { ); $meta_filters = [ \CommonsBooking\Model\Restriction::META_TYPE => 'admin_filter_type', - \CommonsBooking\Model\Restriction::META_STATE => 'admin_filter_state', + \CommonsBooking\Model\Restriction::META_STATE => 'admin_filter_state', \CommonsBooking\Model\Restriction::META_ITEM_ID => 'admin_filter_item', \CommonsBooking\Model\Restriction::META_LOCATION_ID => 'admin_filter_location', ]; foreach ( $meta_filters as $key => $filter ) { if ( - isset( $_GET[ $filter ] ) && + isset( $_GET[ $filter ] ) && $_GET[ $filter ] != '' ) { $query->query_vars['meta_query'][] = array( @@ -257,7 +255,6 @@ public static function filterAdminList( $query ) { } } - // Post field filtering $post_filters = [ 'post_status' => 'admin_filter_post_status', @@ -274,25 +271,31 @@ public static function filterAdminList( $query ) { // Check if current user is allowed to see posts if ( ! commonsbooking_isCurrentUserAdmin() ) { $locations = \CommonsBooking\Repository\Location::getByCurrentUser(); - array_walk( $locations, function ( &$item, $key ) { - $item = $item->ID; - } ); + array_walk( + $locations, + function ( &$item, $key ) { + $item = $item->ID; + } + ); $items = \CommonsBooking\Repository\Item::getByCurrentUser(); - array_walk( $items, function ( &$item, $key ) { - $item = $item->ID; - } ); + array_walk( + $items, + function ( &$item, $key ) { + $item = $item->ID; + } + ); $query->query_vars['meta_query'][] = array( 'relation' => 'OR', array( 'key' => \CommonsBooking\Model\Restriction::META_LOCATION_ID, 'value' => $locations, - 'compare' => 'IN' + 'compare' => 'IN', ), array( 'key' => \CommonsBooking\Model\Restriction::META_ITEM_ID, 'value' => $items, - 'compare' => 'IN' + 'compare' => 'IN', ), ); } @@ -376,7 +379,7 @@ public function getArgs() { // dieser Wert wird später in der URL stehen 'rewrite' => array( 'slug' => self::getPostType() ), - 'show_in_rest' => true + 'show_in_rest' => true, ); } @@ -386,7 +389,7 @@ public function getArgs() { public function registerMetabox() { $cmb = new_cmb2_box( [ - 'id' => static::getPostType() . "-custom-fields", + 'id' => static::getPostType() . '-custom-fields', 'title' => esc_html__( 'Restriction', 'commonsbooking' ), 'object_types' => array( static::getPostType() ), ] @@ -399,48 +402,54 @@ public function registerMetabox() { /** * Returns custom (meta) fields for Costum Post Type Timeframe. + * * @return array */ protected function getCustomFields(): array { // We need static types, because german month names dont't work for datepicker - $dateFormat = "d/m/Y"; + $dateFormat = 'd/m/Y'; if ( strpos( get_locale(), 'de_' ) !== false ) { - $dateFormat = "d.m.Y"; + $dateFormat = 'd.m.Y'; } if ( strpos( get_locale(), 'en_' ) !== false ) { - $dateFormat = "m/d/Y"; + $dateFormat = 'm/d/Y'; } return array( array( 'name' => esc_html__( 'Type', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __( 'Select the type of restriction.
        + 'desc' => commonsbooking_sanitizeHTML( + __( + 'Select the type of restriction.
        Select Notice, the item can still be used and if e.g. only one part is missing or defective.
        Select total breakdown if the defect means that the item can no longer be used. If you select total breakdown all affected bookings will be automatically canceled after activating this restriction and after clicking send the information email. - ', 'commonsbooking' ) ), + ', + 'commonsbooking' + ) + ), 'id' => \CommonsBooking\Model\Restriction::META_TYPE, 'type' => 'select', 'options' => self::getTypes(), ), array( - 'name' => esc_html__( "Location", 'commonsbooking' ), + 'name' => esc_html__( 'Location', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Restriction::META_LOCATION_ID, 'type' => 'select', 'options' => self::sanitizeOptions( \CommonsBooking\Repository\Location::getByCurrentUser() ), ), array( - 'name' => esc_html__( "Item", 'commonsbooking' ), + 'name' => esc_html__( 'Item', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Restriction::META_ITEM_ID, 'type' => 'select', 'options' => self::sanitizeOptions( \CommonsBooking\Repository\Item::getByCurrentUser() ), ), array( - 'name' => esc_html__( "Hint", 'commonsbooking' ), + 'name' => esc_html__( 'Hint', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Restriction::META_HINT, 'desc' => commonsbooking_sanitizeHTML( __( 'Please enter here a short information about the reason and possible effects of the usage restriction.
        The explanation will be displayed on the article page and in the notification e-mail.', 'commonsbooking' ) ), - 'type' => 'textarea' + 'type' => 'textarea', ), array( 'name' => esc_html__( 'Start date', 'commonsbooking' ), @@ -466,17 +475,22 @@ protected function getCustomFields(): array { array( 'type' => 'hidden', 'id' => 'restriction-prevent_delete_meta_movetotrash', - 'default' => wp_create_nonce( plugin_basename( __FILE__ ) ) + 'default' => wp_create_nonce( plugin_basename( __FILE__ ) ), ), array( - 'name' => esc_html__( "Status", 'commonsbooking' ), + 'name' => esc_html__( 'Status', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Restriction::META_STATE, - 'desc' => commonsbooking_sanitizeHTML( __( 'Choose status of this restriction.
        + 'desc' => commonsbooking_sanitizeHTML( + __( + 'Choose status of this restriction.
        Set to None if you want to deactivate the restriction.
        Set to Active if the restriction is active.
        Set to Problem Solved, if the restriction is no longer in effect.
        Depending on the selected status, affected users will receive corresponding notification emails. -Select the desired status and then click the "Send" button to send the e-mail.
        ', 'commonsbooking' ) ), +Select the desired status and then click the "Send" button to send the e-mail.
        ', + 'commonsbooking' + ) + ), 'type' => 'select', 'show_option_none' => false, 'options' => self::getStates(), @@ -491,7 +505,7 @@ protected function getCustomFields(): array { array( 'id' => \CommonsBooking\Model\Restriction::META_SENT, 'type' => 'hidden', - ) + ), ); } @@ -538,5 +552,4 @@ public function savePost( $post_id, $post ) { } } } - } diff --git a/src/Wordpress/CustomPostType/Timeframe.php b/src/Wordpress/CustomPostType/Timeframe.php index caaae53f3..5dfe079d1 100644 --- a/src/Wordpress/CustomPostType/Timeframe.php +++ b/src/Wordpress/CustomPostType/Timeframe.php @@ -66,12 +66,14 @@ class Timeframe extends CustomPostType { /** * CPT type. + * * @var string */ public static $postType = 'cb_timeframe'; /** * Timeframetypes which cannot be "overbooked". + * * @var int[] */ public static $multiDayBlockingFrames = [ @@ -80,6 +82,7 @@ class Timeframe extends CustomPostType { ]; /** * Position in backend menu. + * * @var int */ protected $menuPosition = 1; @@ -93,6 +96,7 @@ public function __construct() { /** * Backend listing columns. + * * @var string[] */ $this->listColumns = [ @@ -105,7 +109,6 @@ public function __construct() { \CommonsBooking\Model\Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS => esc_html__( 'Max. Booking Duration', 'commonsbooking' ), ]; - // List settings $this->removeListDateColumn(); } @@ -121,18 +124,18 @@ public static function getTypes( bool $includeAll = false ): array { $typeOptions = []; if ( $includeAll ) { $typeOptions += [ - 'all' => esc_html__( 'All timeframe types', 'commonsbooking' ) + 'all' => esc_html__( 'All timeframe types', 'commonsbooking' ), ]; } $typeOptions += [ // Opening Hours disabled as its not implemented yet - //self::OPENING_HOURS_ID => esc_html__("Opening Hours", 'commonsbooking'), - self::BOOKABLE_ID => esc_html__( "Bookable", 'commonsbooking' ), - self::HOLIDAYS_ID => esc_html__( "Holidays or location closed", 'commonsbooking' ), + // self::OPENING_HOURS_ID => esc_html__("Opening Hours", 'commonsbooking'), + self::BOOKABLE_ID => esc_html__( 'Bookable', 'commonsbooking' ), + self::HOLIDAYS_ID => esc_html__( 'Holidays or location closed', 'commonsbooking' ), // Off Holidays disabled as its not implemented yet - //self::OFF_HOLIDAYS_ID => esc_html__("Official Holiday", 'commonsbooking'), - self::REPAIR_ID => esc_html__( "Blocked (not overbookable)", 'commonsbooking' ), - self::BOOKING_ID => esc_html__( "Booking", 'commonsbooking' ), + // self::OFF_HOLIDAYS_ID => esc_html__("Official Holiday", 'commonsbooking'), + self::REPAIR_ID => esc_html__( 'Blocked (not overbookable)', 'commonsbooking' ), + self::BOOKING_ID => esc_html__( 'Booking', 'commonsbooking' ), ]; return $typeOptions; @@ -140,8 +143,8 @@ public static function getTypes( bool $includeAll = false ): array { public static function getSimilarPostTypes() { return [ - Timeframe::$postType, - Booking::$postType + self::$postType, + Booking::$postType, ]; } @@ -158,7 +161,7 @@ public static function renderBookingCodeList( $field_args, $field ) { public static function renderDateSelector( $field_args, $field ) { ?>
        @@ -227,14 +230,15 @@ public static function isOverBookable( WP_Post $timeframe ) { /** * Returns view-class. + * * @return null */ public static function getView() { // @TODO implement view. } - - /** + + /** * Adds filter dropdown // filter by type (eg. bookable, repair etc.) in timeframe List * * @return void @@ -244,7 +248,7 @@ public static function addAdminTypeFilter() { static::$postType, esc_html__( 'Filter By Type ', 'commonsbooking' ), 'filter_type', - static::getTypesforSelectField(), + static::getTypesforSelectField(), ); } @@ -257,7 +261,7 @@ public static function addAdminItemFilter() { 'post_status' => 'any', 'orderby' => 'post_title', 'order' => 'asc', - 'nopaging' => true + 'nopaging' => true, ] ); if ( $items ) { @@ -284,7 +288,7 @@ public static function addAdminLocationFilter() { 'post_status' => 'any', 'orderby' => 'post_title', 'order' => 'asc', - 'nopaging' => true + 'nopaging' => true, ] ); if ( $locations ) { @@ -304,7 +308,6 @@ public static function addAdminLocationFilter() { /** * Adds filter dropdown // filter by location in booking list - * */ public static function addAdminStatusFilter() { $values = []; @@ -374,7 +377,7 @@ public static function filterAdminList( $query ) { } } - //post status filtering + // post status filtering $post_filters = [ 'post_status' => 'admin_filter_post_status', @@ -387,7 +390,7 @@ public static function filterAdminList( $query ) { $query->query_vars[ $key ] = sanitize_text_field( $_GET[ $filter ] ); } } - + // Timerange filtering // Start date if ( @@ -397,7 +400,7 @@ public static function filterAdminList( $query ) { $query->query_vars['meta_query'][] = array( 'key' => \CommonsBooking\Model\Timeframe::REPETITION_START, 'value' => strtotime( sanitize_text_field( $_GET['admin_filter_startdate'] ) ), - 'compare' => ">=", + 'compare' => '>=', ); } @@ -409,32 +412,38 @@ public static function filterAdminList( $query ) { $query->query_vars['meta_query'][] = array( 'key' => \CommonsBooking\Model\Timeframe::REPETITION_END, 'value' => strtotime( sanitize_text_field( $_GET['admin_filter_enddate'] ) ), - 'compare' => "<=", + 'compare' => '<=', ); } // Check if current user is allowed to see posts if ( ! commonsbooking_isCurrentUserAdmin() ) { $locations = \CommonsBooking\Repository\Location::getByCurrentUser(); - array_walk( $locations, function ( &$item, $key ) { - $item = $item->ID; - } ); + array_walk( + $locations, + function ( &$item, $key ) { + $item = $item->ID; + } + ); $items = \CommonsBooking\Repository\Item::getByCurrentUser(); - array_walk( $items, function ( &$item, $key ) { - $item = $item->ID; - } ); + array_walk( + $items, + function ( &$item, $key ) { + $item = $item->ID; + } + ); $query->query_vars['meta_query'][] = array( 'relation' => 'OR', array( 'key' => \CommonsBooking\Model\Timeframe::META_LOCATION_ID, 'value' => $locations, - 'compare' => 'IN' + 'compare' => 'IN', ), array( 'key' => \CommonsBooking\Model\Timeframe::META_ITEM_ID, 'value' => $items, - 'compare' => 'IN' + 'compare' => 'IN', ), ); } @@ -447,13 +456,12 @@ public static function filterAdminList( $query ) { public function registerMetabox() { $cmb = new_cmb2_box( [ - 'id' => static::getPostType() . "-custom-fields", + 'id' => static::getPostType() . '-custom-fields', 'title' => esc_html__( 'Timeframe', 'commonsbooking' ), 'object_types' => array( static::getPostType() ), ] ); - foreach ( $this->getCustomFields() as $customField ) { $cmb->add_field( $customField ); } @@ -461,31 +469,32 @@ public function registerMetabox() { /** * Returns custom (meta) fields for Costum Post Type Timeframe. + * * @return array */ protected function getCustomFields() { // We need static types, because german month names dont't work for datepicker - $dateFormat = "d/m/Y"; + $dateFormat = 'd/m/Y'; if ( strpos( get_locale(), 'de_' ) !== false ) { - $dateFormat = "d.m.Y"; + $dateFormat = 'd.m.Y'; } if ( strpos( get_locale(), 'en_' ) !== false ) { - $dateFormat = "m/d/Y"; + $dateFormat = 'm/d/Y'; } return array( array( - 'name' => esc_html__( "Comment", 'commonsbooking' ), + 'name' => esc_html__( 'Comment', 'commonsbooking' ), 'desc' => esc_html__( 'This comment is internal for timeframes like bookable, repair, holiday. If timeframe is a booking this comment can be set by users during the booking confirmation process.', 'commonsbooking' ), - 'id' => "comment", + 'id' => 'comment', 'type' => 'textarea_small', 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( 'name' => esc_html__( 'Type', 'commonsbooking' ), 'desc' => esc_html__( 'Select Type of this timeframe: Bookable or Location Closed. See Documentation for detailed information.', 'commonsbooking' ), - 'id' => "type", + 'id' => 'type', 'type' => 'select', 'options' => self::getTypesforSelectField(), 'default_cb' => 'commonsbooking_filter_from_cmb2', @@ -499,7 +508,7 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Location Category Selection", 'commonsbooking' ), + 'name' => esc_html__( 'Location Category Selection', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Timeframe::META_LOCATION_CATEGORY_IDS, 'type' => 'multicheck', 'options' => self::sanitizeOptions( \CommonsBooking\Repository\Location::getTerms() ), @@ -507,7 +516,7 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Location Selection", 'commonsbooking' ), + 'name' => esc_html__( 'Location Selection', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Timeframe::META_LOCATION_ID, 'type' => 'select', 'show_option_none' => esc_html__( 'Please select', 'commonsbooking' ), @@ -515,7 +524,7 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Select one or more locations", 'commonsbooking' ), + 'name' => esc_html__( 'Select one or more locations', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Timeframe::META_LOCATION_ID_LIST, 'type' => 'multicheck', 'options' => self::sanitizeOptions( \CommonsBooking\Repository\Location::getByCurrentUser() ), @@ -530,14 +539,14 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Select one or more items", 'commonsbooking' ), + 'name' => esc_html__( 'Select one or more items', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Timeframe::META_ITEM_ID_LIST, 'type' => 'multicheck', 'options' => self::sanitizeOptions( \CommonsBooking\Repository\Item::getByCurrentUser() ), 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Item Category Selection", 'commonsbooking' ), + 'name' => esc_html__( 'Item Category Selection', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Timeframe::META_ITEM_CATEGORY_IDS, 'type' => 'multicheck', 'options' => self::sanitizeOptions( \CommonsBooking\Repository\Item::getTerms() ), @@ -545,7 +554,7 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Item selection", 'commonsbooking' ), + 'name' => esc_html__( 'Item selection', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Timeframe::META_ITEM_ID, 'type' => 'select', 'show_option_none' => esc_html__( 'Please select', 'commonsbooking' ), @@ -553,8 +562,8 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Configure bookings", 'commonsbooking' ), - 'id' => "title-bookings-config", + 'name' => esc_html__( 'Configure bookings', 'commonsbooking' ), + 'id' => 'title-bookings-config', 'type' => 'title', ), array( @@ -570,9 +579,9 @@ protected function getCustomFields() { 'default_value' => 3, 'default_cb' => 'commonsbooking_filter_from_cmb2', ), - array( + array( 'name' => esc_html__( 'Lead time:', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML(__( 'Enter the number of days that should be blocked for bookings as a booking lead time (calculated from the current day).', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Enter the number of days that should be blocked for bookings as a booking lead time (calculated from the current day).', 'commonsbooking' ) ), 'id' => \CommonsBooking\Model\Timeframe::META_BOOKING_START_DAY_OFFSET, 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value 'type' => 'text_small', @@ -597,9 +606,9 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Allowed for", 'commonsbooking' ), + 'name' => esc_html__( 'Allowed for', 'commonsbooking' ), 'id' => \CommonsBooking\Model\Timeframe::META_ALLOWED_USER_ROLES, - 'desc' => commonsbooking_sanitizeHTML(__( '
        Select one or more user roles that will be allowed to book the item exclusively.
        Leave this blank to allow all users to book the item. ', 'commonsbooking' ) ), + 'desc' => commonsbooking_sanitizeHTML( __( '
        Select one or more user roles that will be allowed to book the item exclusively.
        Leave this blank to allow all users to book the item. ', 'commonsbooking' ) ), 'type' => 'pw_multiselect', 'options' => self::sanitizeOptions( UserRepository::getUserRoles() ), 'attributes' => array( @@ -608,31 +617,32 @@ protected function getCustomFields() { 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Configure timeframe", 'commonsbooking' ), - 'id' => "title-timeframe-config", + 'name' => esc_html__( 'Configure timeframe', 'commonsbooking' ), + 'id' => 'title-timeframe-config', 'type' => 'title', ), array( 'name' => esc_html__( 'Full day', 'commonsbooking' ), 'desc' => esc_html__( - 'If this option is selected, users can choose only whole days for pickup and return. No specific time slots for pickup or return are offered. Select this option if the pickup/return should be arranged personally between the location and the user. ' - , 'commonsbooking' ), - 'id' => "full-day", + 'If this option is selected, users can choose only whole days for pickup and return. No specific time slots for pickup or return are offered. Select this option if the pickup/return should be arranged personally between the location and the user. ', + 'commonsbooking' + ), + 'id' => 'full-day', 'type' => 'checkbox', 'default_value' => '', 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Grid", 'commonsbooking' ), + 'name' => esc_html__( 'Grid', 'commonsbooking' ), 'desc' => commonsbooking_sanitizeHTML( __( 'Choose whether users can only select the entire from/to time period when booking (full slot) or book within the time period in an hourly grid. See the documentation: Manage Booking Timeframes', 'commonsbooking' ) ), - 'id' => "grid", + 'id' => 'grid', 'type' => 'select', 'options' => self::getGridOptions(), 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Start time", 'commonsbooking' ), - 'id' => "start-time", + 'name' => esc_html__( 'Start time', 'commonsbooking' ), + 'id' => 'start-time', 'type' => 'text_time', 'show_on_cb' => 'cmb2_hide_if_no_cats', // function should return a bool value 'attributes' => array( @@ -643,15 +653,15 @@ protected function getCustomFields() { ) ), ), - 'time_format' => esc_html(get_option( 'time_format' )), + 'time_format' => esc_html( get_option( 'time_format' ) ), 'date_format' => $dateFormat, 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "End time", 'commonsbooking' ), - 'id' => "end-time", + 'name' => esc_html__( 'End time', 'commonsbooking' ), + 'id' => 'end-time', 'type' => 'text_time', - 'timeFormat' => 'HH:mm', + 'timeFormat' => 'HH:mm', 'attributes' => array( 'data-timepicker' => wp_json_encode( array( @@ -660,41 +670,43 @@ protected function getCustomFields() { ) ), ), - 'time_format' => esc_html(get_option( 'time_format' )), + 'time_format' => esc_html( get_option( 'time_format' ) ), 'date_format' => $dateFormat, 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( 'name' => esc_html__( 'Timeframe Repetition', 'commonsbooking' ), 'desc' => esc_html__( - 'Choose whether the time frame should repeat at specific intervals. The repetitions refer to the unit of a day. With the start and end date you define when the repetition interval starts and ends. If you choose "weekly", you can select specific days of the week below. Read the documentation for more information and examples.' - , 'commonsbooking' ), + 'Choose whether the time frame should repeat at specific intervals. The repetitions refer to the unit of a day. With the start and end date you define when the repetition interval starts and ends. If you choose "weekly", you can select specific days of the week below. Read the documentation for more information and examples.', + 'commonsbooking' + ), 'id' => \CommonsBooking\Model\Timeframe::META_REPETITION, 'type' => 'select', 'options' => self::getTimeFrameRepetitions(), 'default_cb' => 'commonsbooking_filter_from_cmb2', - 'default' => 'w', + 'default' => 'w', ), array( 'name' => esc_html__( 'Import holidays', 'commonsbooking' ), 'desc' => esc_html__( - 'Select the year and state to import holidays for (as of now only German holidays are supported)' - , 'commonsbooking' ), - 'id' => "_cmb2_holiday", - 'type' => 'holiday_get_fields' + 'Select the year and state to import holidays for (as of now only German holidays are supported)', + 'commonsbooking' + ), + 'id' => '_cmb2_holiday', + 'type' => 'holiday_get_fields', ), array( - 'name' => esc_html__( "Configure repetition", 'commonsbooking' ), + 'name' => esc_html__( 'Configure repetition', 'commonsbooking' ), 'desc' => esc_html__( 'Below you can make settings regarding the time frame repetition. ', 'commonsbooking' ), - 'id' => "title-timeframe-rep-config", + 'id' => 'title-timeframe-rep-config', 'type' => 'title', ), array( - 'name' => esc_html__( "Selected manual dates", 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __( "Enter the dates in the YYYY-MM-DD format here, the dates are separated by a comma.
        Example: 2023-05-24,2023-06-24
        You can also use the datepicker above to pick dates for this field.", 'commonsbooking' ) ), + 'name' => esc_html__( 'Selected manual dates', 'commonsbooking' ), + 'desc' => commonsbooking_sanitizeHTML( __( 'Enter the dates in the YYYY-MM-DD format here, the dates are separated by a comma.
        Example: 2023-05-24,2023-06-24
        You can also use the datepicker above to pick dates for this field.', 'commonsbooking' ) ), 'id' => \CommonsBooking\Model\Timeframe::META_MANUAL_SELECTION, 'type' => 'textarea_small', - 'before_row' => array( self::class, 'renderDateSelector' ) + 'before_row' => array( self::class, 'renderDateSelector' ), ), array( 'name' => esc_html__( 'Start date', 'commonsbooking' ), @@ -707,37 +719,47 @@ protected function getCustomFields() { ), array( 'name' => esc_html__( 'Weekdays', 'commonsbooking' ), - 'id' => "weekdays", + 'id' => 'weekdays', 'type' => 'multicheck', 'options' => [ - 1 => esc_html__( "Monday", 'commonsbooking' ), - 2 => esc_html__( "Tuesday", 'commonsbooking' ), - 3 => esc_html__( "Wednesday", 'commonsbooking' ), - 4 => esc_html__( "Thursday", 'commonsbooking' ), - 5 => esc_html__( "Friday", 'commonsbooking' ), - 6 => esc_html__( "Saturday", 'commonsbooking' ), - 7 => esc_html__( "Sunday", 'commonsbooking' ), + 1 => esc_html__( 'Monday', 'commonsbooking' ), + 2 => esc_html__( 'Tuesday', 'commonsbooking' ), + 3 => esc_html__( 'Wednesday', 'commonsbooking' ), + 4 => esc_html__( 'Thursday', 'commonsbooking' ), + 5 => esc_html__( 'Friday', 'commonsbooking' ), + 6 => esc_html__( 'Saturday', 'commonsbooking' ), + 7 => esc_html__( 'Sunday', 'commonsbooking' ), ], 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( 'name' => esc_html__( 'End date', 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __('Set the end date. If you have selected repetition, this is the end date of the interval. Leave blank if you do not want to set an end date. -
        Notice: If you want to select only one day (e.g. for holidays or blocked days) set the start and the end date to same day.', 'commonsbooking') ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'Set the end date. If you have selected repetition, this is the end date of the interval. Leave blank if you do not want to set an end date. +
        Notice: If you want to select only one day (e.g. for holidays or blocked days) set the start and the end date to same day.', + 'commonsbooking' + ) + ), 'id' => \CommonsBooking\Model\Timeframe::REPETITION_END, 'type' => 'text_date_timestamp', - 'time_format' => esc_html(get_option( 'time_format' )), + 'time_format' => esc_html( get_option( 'time_format' ) ), 'date_format' => $dateFormat, 'default_cb' => 'commonsbooking_filter_from_cmb2', ), array( - 'name' => esc_html__( "Booking Codes", 'commonsbooking' ), - 'desc' => commonsbooking_sanitizeHTML( __( 'You can automatically generate booking codes. Codes can be generated only with the following settings:
        + 'name' => esc_html__( 'Booking Codes', 'commonsbooking' ), + 'desc' => commonsbooking_sanitizeHTML( + __( + 'You can automatically generate booking codes. Codes can be generated only with the following settings:
        - Whole day is enabled
        - Timeframe is bookable
        More Information in the documentation - ', 'commonsbooking' ) ), - 'id' => "title-timeframe-booking-codes", + ', + 'commonsbooking' + ) + ), + 'id' => 'title-timeframe-booking-codes', 'type' => 'title', ), array( @@ -758,24 +780,24 @@ protected function getCustomFields() { 'name' => esc_html__( 'Booking Codes', 'commonsbooking' ), 'id' => 'direct-email-booking-codes-list', 'type' => 'title', - 'render_row_cb' => ['\CommonsBooking\View\BookingCodes','renderDirectEmailRow'], + 'render_row_cb' => [ '\CommonsBooking\View\BookingCodes', 'renderDirectEmailRow' ], ), array( 'name' => esc_html__( 'Send booking codes automated by email', 'commonsbooking' ), - 'desc_cb' => esc_html__("Enable automated sending of booking codes by email", 'commonsbooking' ), + 'desc_cb' => esc_html__( 'Enable automated sending of booking codes by email', 'commonsbooking' ), 'name_start' => esc_html__( 'Start Date', 'commonsbooking' ), - 'desc_start' => commonsbooking_sanitizeHTML( __('First day to send Codes (List starts at next month)
        (Same day will be used for subsequent messages) ', 'commonsbooking')) , + 'desc_start' => commonsbooking_sanitizeHTML( __( 'First day to send Codes (List starts at next month)
        (Same day will be used for subsequent messages) ', 'commonsbooking' ) ), 'date_format_start' => $dateFormat, - 'default_start' => strtotime("now"), - 'name_nummonth' => esc_html__( "Months to send", 'commonsbooking' ), + 'default_start' => strtotime( 'now' ), + 'name_nummonth' => esc_html__( 'Months to send', 'commonsbooking' ), 'desc_nummonth' => esc_html__( "Send booking codes for this amount of month's in one email", 'commonsbooking' ), - 'default_nummonth' => 1, - 'msg_next_email' => esc_html__( 'Next email planned for: ', 'commonsbooking' ), - 'msg_email_not_planned' => esc_html__( '(not planned)', 'commonsbooking' ), + 'default_nummonth' => 1, + 'msg_next_email' => esc_html__( 'Next email planned for: ', 'commonsbooking' ), + 'msg_email_not_planned' => esc_html__( '(not planned)', 'commonsbooking' ), 'id' => \CommonsBooking\View\BookingCodes::CRON_EMAIL_CODES, 'type' => 'booking_codes_email_fields', - 'sanitization_cb' => ['\CommonsBooking\View\BookingCodes','sanitizeCronEmailCodes'], - 'escape_cb' => ['\CommonsBooking\View\BookingCodes','escapeCronEmailCodes'], + 'sanitization_cb' => [ '\CommonsBooking\View\BookingCodes', 'sanitizeCronEmailCodes' ], + 'escape_cb' => [ '\CommonsBooking\View\BookingCodes', 'escapeCronEmailCodes' ], ), array( 'name' => esc_html__( 'Booking Codes', 'commonsbooking' ), @@ -787,7 +809,7 @@ protected function getCustomFields() { array( 'type' => 'hidden', 'id' => 'prevent_delete_meta_movetotrash', - 'default' => wp_create_nonce( plugin_basename( __FILE__ ) ) + 'default' => wp_create_nonce( plugin_basename( __FILE__ ) ), ), ); } @@ -801,11 +823,11 @@ protected function getCustomFields() { public static function getTypesforSelectField() { $types = self::getTypes(); - // remove unused types + // remove unused types unset( $types[ self::BOOKING_ID ], $types[ self::BOOKING_CANCELED_ID ], - //$types[ self::REPAIR_ID ], + // $types[ self::REPAIR_ID ], ); return $types; @@ -813,39 +835,42 @@ public static function getTypesforSelectField() { /** * Returns style of item / location selection + * * @return array */ public static function getSelectionOptions() { return [ - \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID => esc_html__( "Manual selection", 'commonsbooking' ), - \CommonsBooking\Model\Timeframe::SELECTION_CATEGORY_ID => esc_html__( "Select by category", 'commonsbooking' ), - \CommonsBooking\Model\Timeframe::SELECTION_ALL_ID => esc_html__( "All", 'commonsbooking' ), + \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID => esc_html__( 'Manual selection', 'commonsbooking' ), + \CommonsBooking\Model\Timeframe::SELECTION_CATEGORY_ID => esc_html__( 'Select by category', 'commonsbooking' ), + \CommonsBooking\Model\Timeframe::SELECTION_ALL_ID => esc_html__( 'All', 'commonsbooking' ), ]; } /** * Returns grid options. + * * @return array */ public static function getGridOptions() { return [ - 0 => esc_html__( "Full slot", 'commonsbooking' ), - 1 => esc_html__( "Hourly", 'commonsbooking' ), + 0 => esc_html__( 'Full slot', 'commonsbooking' ), + 1 => esc_html__( 'Hourly', 'commonsbooking' ), ]; } /** * Returns array with repetition options. + * * @return array */ public static function getTimeFrameRepetitions() { return [ - 'norep' => esc_html__( "No repetition", 'commonsbooking' ), - 'manual' => esc_html__( "Manual repetition", 'commonsbooking' ), - 'd' => esc_html__( "Daily", 'commonsbooking' ), - 'w' => esc_html__( "Weekly", 'commonsbooking' ), - 'm' => esc_html__( "Monthly", 'commonsbooking' ), - 'y' => esc_html__( "Yearly", 'commonsbooking' ), + 'norep' => esc_html__( 'No repetition', 'commonsbooking' ), + 'manual' => esc_html__( 'Manual repetition', 'commonsbooking' ), + 'd' => esc_html__( 'Daily', 'commonsbooking' ), + 'w' => esc_html__( 'Weekly', 'commonsbooking' ), + 'm' => esc_html__( 'Monthly', 'commonsbooking' ), + 'y' => esc_html__( 'Yearly', 'commonsbooking' ), ]; } @@ -866,7 +891,7 @@ public function savePost( $post_id, WP_Post $post ) { return; } - //assign the startDate and EndDate for manual repetition (needs to be done before validation in order for validation to work) + // assign the startDate and EndDate for manual repetition (needs to be done before validation in order for validation to work) try { $timeframe = new \CommonsBooking\Model\Timeframe( $post_id ); } catch ( Exception $e ) { @@ -883,20 +908,19 @@ public function savePost( $post_id, WP_Post $post ) { $isValid = self::validateTimeFrame( $timeframe ); if ( $isValid ) { - self::sanitizeRepetitionEndDate( $post_id ); // Update postmeta related to dynamic selection fields - Timeframe::manageTimeframeMeta( $post_id ); + self::manageTimeframeMeta( $post_id ); - //delete unused postmeta + // delete unused postmeta self::removeIrrelevantPostmeta( $timeframe ); if ( $timeframe->usesBookingCodes() && $timeframe->bookingCodesApplicable() ) { try { BookingCodes::generate( $timeframe ); } catch ( BookingCodeException $e ) { - //unset checkboxes if booking codes could not be generated + // unset checkboxes if booking codes could not be generated delete_post_meta( $post_id, \CommonsBooking\Model\Timeframe::META_CREATE_BOOKING_CODES ); delete_post_meta( $post_id, \CommonsBooking\Model\Timeframe::META_SHOW_BOOKING_CODES ); @@ -911,19 +935,18 @@ public function savePost( $post_id, WP_Post $post ) { } - public function updatedPostMeta($meta_id,$object_id,$meta_key,$meta_value) - { - //make sure, that action is only executed if timeframe is changed - if (get_post($object_id)->post_type !== Timeframe::getPostType()) { + public function updatedPostMeta( $meta_id, $object_id, $meta_key, $meta_value ) { + // make sure, that action is only executed if timeframe is changed + if ( get_post( $object_id )->post_type !== self::getPostType() ) { return; } - if ($meta_key == \CommonsBooking\Model\Timeframe::META_LOCATION_ID){ //Location ID was changed, the only evidence we still have is the item ID - $correspondingItems = get_post_meta( $object_id, \CommonsBooking\Model\Timeframe::META_ITEM_ID ); - $item_id = reset( $correspondingItems ); //value has to be reset in order to retrieve first value - $orphanedBookings = \CommonsBooking\Repository\Booking::getOrphaned(null,[$item_id]); - if ($orphanedBookings) { - foreach ($orphanedBookings as $booking) { - update_post_meta($booking->ID,\CommonsBooking\Model\Booking::META_LAST_TIMEFRAME,$object_id); + if ( $meta_key == \CommonsBooking\Model\Timeframe::META_LOCATION_ID ) { // Location ID was changed, the only evidence we still have is the item ID + $correspondingItems = get_post_meta( $object_id, \CommonsBooking\Model\Timeframe::META_ITEM_ID ); + $item_id = reset( $correspondingItems ); // value has to be reset in order to retrieve first value + $orphanedBookings = \CommonsBooking\Repository\Booking::getOrphaned( null, [ $item_id ] ); + if ( $orphanedBookings ) { + foreach ( $orphanedBookings as $booking ) { + update_post_meta( $booking->ID, \CommonsBooking\Model\Booking::META_LAST_TIMEFRAME, $object_id ); } set_transient( \CommonsBooking\Model\Timeframe::ORPHANED_TYPE, @@ -947,7 +970,7 @@ public function updatedPostMeta($meta_id,$object_id,$meta_key,$meta_value) * * @return void */ - private static function sanitizeRepetitionEndDate( $postId ) : void { + private static function sanitizeRepetitionEndDate( $postId ): void { $repetitionEnd = get_post_meta( $postId, \CommonsBooking\Model\Timeframe::REPETITION_END, true ); if ( $repetitionEnd ) { $repetitionEnd = strtotime( '+23 Hours +59 Minutes +59 Seconds', $repetitionEnd ); @@ -965,12 +988,12 @@ private static function sanitizeRepetitionEndDate( $postId ) : void { protected static function validateTimeFrame( $timeframe ): bool { try { $timeframe->isValid(); - } - catch (TimeframeInvalidException $e){ + } catch ( TimeframeInvalidException $e ) { set_transient( \CommonsBooking\Model\Timeframe::ERROR_TYPE, - commonsbooking_sanitizeHTML($e->getMessage()), - 45 ); + commonsbooking_sanitizeHTML( $e->getMessage() ), + 45 + ); // set post_status to draft if not valid $post = $timeframe->getPost(); if ( $post->post_status !== 'draft' ) { @@ -994,8 +1017,8 @@ public static function updateAllTimeframes() { [], [], [ - Timeframe::HOLIDAYS_ID, - Timeframe::REPAIR_ID + self::HOLIDAYS_ID, + self::REPAIR_ID, ] ); foreach ( $timeframes as $timeframe ) { @@ -1021,73 +1044,83 @@ public static function updateAllTimeframes() { * * @return void */ - public static function manageTimeframeMeta ( $post_id ) { - $postModel = get_post($post_id); + public static function manageTimeframeMeta( $post_id ) { + $postModel = get_post( $post_id ); // This is just for timeframes if ( $postModel->post_type !== static::getPostType() ) { return; } - $timeframe = new \CommonsBooking\Model\Timeframe( $post_id ); - $itemSelectionType = intval ( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::META_ITEM_SELECTION_TYPE ) ); - $locationSelectionType = intval ( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::META_LOCATION_SELECTION_TYPE ) ); + $timeframe = new \CommonsBooking\Model\Timeframe( $post_id ); + $itemSelectionType = intval( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::META_ITEM_SELECTION_TYPE ) ); + $locationSelectionType = intval( $timeframe->getMeta( \CommonsBooking\Model\Timeframe::META_LOCATION_SELECTION_TYPE ) ); - //we only need to update the timeframes which have the dynamic selection type + // we only need to update the timeframes which have the dynamic selection type if ( $itemSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID && $locationSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID ) { return; } - if ($itemSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_CATEGORY_ID) { + if ( $itemSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_CATEGORY_ID ) { $itemCategorySelection = $timeframe->getMeta( \CommonsBooking\Model\Timeframe::META_ITEM_CATEGORY_IDS ); - $taxQuery = array ( + $taxQuery = array( 'tax_query' => array( array( - 'taxonomy' => Item::getPostType() . 's_category', - 'field' => 'term_id', - 'terms' => $itemCategorySelection + 'taxonomy' => Item::getPostType() . 's_category', + 'field' => 'term_id', + 'terms' => $itemCategorySelection, ), - ) + ), + ); + $items = \CommonsBooking\Repository\Item::get( $taxQuery ); + // for some reason, the item ids need to be saved as strings + $itemIds = array_map( + function ( $item ) { + return strval( $item->ID ); + }, + $items ); - $items = \CommonsBooking\Repository\Item::get( $taxQuery ); - //for some reason, the item ids need to be saved as strings - $itemIds = array_map( function ( $item ) { - return strval ($item->ID); - }, $items ); update_post_meta( $post_id, \CommonsBooking\Model\Timeframe::META_ITEM_ID_LIST, $itemIds ); - } - else if ($itemSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_ALL_ID) { + } elseif ( $itemSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_ALL_ID ) { $items = \CommonsBooking\Repository\Item::get(); - //for some reason, the item ids need to be saved as strings - $itemIds = array_map( function ( $item ) { - return strval ($item->ID); - }, $items ); + // for some reason, the item ids need to be saved as strings + $itemIds = array_map( + function ( $item ) { + return strval( $item->ID ); + }, + $items + ); update_post_meta( $post_id, \CommonsBooking\Model\Timeframe::META_ITEM_ID_LIST, $itemIds ); } - if ($locationSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_CATEGORY_ID) { + if ( $locationSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_CATEGORY_ID ) { $locationCategorySelection = $timeframe->getMeta( \CommonsBooking\Model\Timeframe::META_LOCATION_CATEGORY_IDS ); - $taxQuery = array ( + $taxQuery = array( 'tax_query' => array( array( - 'taxonomy' => Location::getPostType() . 's_category', - 'field' => 'term_id', - 'terms' => $locationCategorySelection + 'taxonomy' => Location::getPostType() . 's_category', + 'field' => 'term_id', + 'terms' => $locationCategorySelection, ), - ) + ), + ); + $locations = \CommonsBooking\Repository\Location::get( $taxQuery ); + // for some reason, the location ids need to be saved as strings + $locationIds = array_map( + function ( $location ) { + return strval( $location->ID ); + }, + $locations ); - $locations = \CommonsBooking\Repository\Location::get( $taxQuery ); - //for some reason, the location ids need to be saved as strings - $locationIds = array_map( function ( $location ) { - return strval ($location->ID); - }, $locations ); update_post_meta( $post_id, \CommonsBooking\Model\Timeframe::META_LOCATION_ID_LIST, $locationIds ); - } - else if ($locationSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_ALL_ID) { + } elseif ( $locationSelectionType === \CommonsBooking\Model\Timeframe::SELECTION_ALL_ID ) { $locations = \CommonsBooking\Repository\Location::get(); - //for some reason, the location ids need to be saved as strings - $locationIds = array_map( function ( $location ) { - return strval ($location->ID); - }, $locations ); + // for some reason, the location ids need to be saved as strings + $locationIds = array_map( + function ( $location ) { + return strval( $location->ID ); + }, + $locations + ); update_post_meta( $post_id, \CommonsBooking\Model\Timeframe::META_LOCATION_ID_LIST, $locationIds ); } } @@ -1109,7 +1142,7 @@ public static function removeIrrelevantPostmeta( \CommonsBooking\Model\Timeframe \CommonsBooking\Model\Timeframe::META_CREATE_BOOKING_CODES, \CommonsBooking\Model\Timeframe::META_SHOW_BOOKING_CODES, ]; - //remove multi-select postmeta if not relevant (#507) + // remove multi-select postmeta if not relevant (#507) $onlyRelevantForHolidays = [ \CommonsBooking\Model\Timeframe::META_ITEM_ID_LIST, \CommonsBooking\Model\Timeframe::META_LOCATION_ID_LIST, @@ -1119,24 +1152,25 @@ public static function removeIrrelevantPostmeta( \CommonsBooking\Model\Timeframe \CommonsBooking\Model\Timeframe::META_LOCATION_SELECTION_TYPE, ]; - if ($timeframe->getType() != Timeframe::BOOKABLE_ID) { + if ( $timeframe->getType() != self::BOOKABLE_ID ) { foreach ( $onlyRelevantForBookable as $metaKey ) { delete_post_meta( $timeframe->ID, $metaKey ); } } - if ($timeframe->getType() != Timeframe::HOLIDAYS_ID) { + if ( $timeframe->getType() != self::HOLIDAYS_ID ) { foreach ( $onlyRelevantForHolidays as $metaKey ) { delete_post_meta( $timeframe->ID, $metaKey ); } - //reset to manual selection - update_post_meta($timeframe->ID, \CommonsBooking\Model\Timeframe::META_ITEM_SELECTION_TYPE, \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID); - update_post_meta($timeframe->ID, \CommonsBooking\Model\Timeframe::META_LOCATION_SELECTION_TYPE, \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID); + // reset to manual selection + update_post_meta( $timeframe->ID, \CommonsBooking\Model\Timeframe::META_ITEM_SELECTION_TYPE, \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID ); + update_post_meta( $timeframe->ID, \CommonsBooking\Model\Timeframe::META_LOCATION_SELECTION_TYPE, \CommonsBooking\Model\Timeframe::SELECTION_MANUAL_ID ); } } /** * Returns CPT arguments. + * * @return array */ public function getArgs() { @@ -1212,7 +1246,7 @@ public function getArgs() { // dieser Wert wird später in der URL stehen 'rewrite' => array( 'slug' => self::getPostType() ), - 'show_in_rest' => true + 'show_in_rest' => true, ); } @@ -1225,29 +1259,28 @@ public function getArgs() { public function setCustomColumnsData( $column, $post_id ) { // we alter the author column data and link the username to the user profile - if ( $column == "timeframe-author" ) { + if ( $column == 'timeframe-author' ) { $post = get_post( $post_id ); $timeframe_user = get_user_by( 'id', $post->post_author ); echo '' . commonsbooking_sanitizeHTML( $timeframe_user->user_login ) . ''; } - if ( $value = get_post_meta( $post_id, $column, true ) ) { switch ( $column ) { case 'location-id': case 'item-id': if ( $post = get_post( $value ) ) { if ( get_post_type( $post ) == Location::getPostType() || - get_post_type( $post ) == Item::getPostType() + get_post_type( $post ) == Item::getPostType() ) { - echo commonsbooking_sanitizeHTML($post->post_title); + echo commonsbooking_sanitizeHTML( $post->post_title ); break; } } echo '-'; break; case 'type': - $output = "-"; + $output = '-'; foreach ( $this->getCustomFields() as $customField ) { if ( $customField['id'] == 'type' ) { @@ -1258,14 +1291,14 @@ public function setCustomColumnsData( $column, $post_id ) { } } } - echo commonsbooking_sanitizeHTML($output); + echo commonsbooking_sanitizeHTML( $output ); break; case \CommonsBooking\Model\Timeframe::REPETITION_START: case \CommonsBooking\Model\Timeframe::REPETITION_END: echo date( 'd.m.Y', $value ); break; default: - echo commonsbooking_sanitizeHTML($value); + echo commonsbooking_sanitizeHTML( $value ); break; } } else { @@ -1277,10 +1310,10 @@ public function setCustomColumnsData( $column, $post_id ) { if ( property_exists( $post = get_post( $post_id ), $column ) && ( ! in_array( $column, $bookingColumns ) || - get_post_meta( $post_id, 'type', true ) == Timeframe::BOOKING_ID + get_post_meta( $post_id, 'type', true ) == self::BOOKING_ID ) ) { - echo commonsbooking_sanitizeHTML($post->{$column}); + echo commonsbooking_sanitizeHTML( $post->{$column} ); } } } @@ -1291,54 +1324,66 @@ public function setCustomColumnsData( $column, $post_id ) { * @return true|void returns true if inheriting method should set sort order, void if this method sets it */ public function setCustomColumnSortOrder( \WP_Query $query ) { - if (! parent::setCustomColumnSortOrder( $query ) ) { + if ( ! parent::setCustomColumnSortOrder( $query ) ) { return; } - switch ($query->get( 'orderby' )) { + switch ( $query->get( 'orderby' ) ) { case 'item-id': - add_filter('posts_join', function ($join) { - global $wp_query, $wpdb; + add_filter( + 'posts_join', + function ( $join ) { + global $wp_query, $wpdb; + + if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_ITEM_ID ) { + $join .= "LEFT JOIN $wpdb->postmeta joined_meta_items " + . "ON $wpdb->posts.ID = joined_meta_items.post_id AND joined_meta_items.meta_key = '" . \CommonsBooking\Model\Timeframe::META_ITEM_ID . "' "; + $join .= "JOIN $wpdb->posts joined_items ON joined_meta_items.meta_value = joined_items.ID "; + } - if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_ITEM_ID ) { - $join .= "LEFT JOIN $wpdb->postmeta joined_meta_items " - . "ON $wpdb->posts.ID = joined_meta_items.post_id AND joined_meta_items.meta_key = '" . \CommonsBooking\Model\Timeframe::META_ITEM_ID . "' "; - $join .= "JOIN $wpdb->posts joined_items ON joined_meta_items.meta_value = joined_items.ID "; + return $join; } + ); + add_filter( + 'posts_orderby', + function ( $orderby ) { + global $wp_query; - return $join; - }); - add_filter( 'posts_orderby', function ( $orderby ) { - global $wp_query; + if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_ITEM_ID ) { + $orderby = 'joined_items.post_title ' . $wp_query->query_vars['order']; + } - if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_ITEM_ID ) { - $orderby = 'joined_items.post_title ' . $wp_query->query_vars['order']; + return $orderby; } - - return $orderby; - }); + ); break; case 'location-id': - add_filter('posts_join', function ($join) { - global $wp_query, $wpdb; + add_filter( + 'posts_join', + function ( $join ) { + global $wp_query, $wpdb; + + if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_LOCATION_ID ) { + $join .= "LEFT JOIN $wpdb->postmeta joined_meta_locations " + . "ON $wpdb->posts.ID = joined_meta_locations.post_id AND joined_meta_locations.meta_key = '" . \CommonsBooking\Model\Timeframe::META_LOCATION_ID . "' "; + $join .= "JOIN $wpdb->posts joined_locations ON joined_meta_locations.meta_value = joined_locations.ID "; + } - if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_LOCATION_ID ) { - $join .= "LEFT JOIN $wpdb->postmeta joined_meta_locations " - . "ON $wpdb->posts.ID = joined_meta_locations.post_id AND joined_meta_locations.meta_key = '" . \CommonsBooking\Model\Timeframe::META_LOCATION_ID . "' "; - $join .= "JOIN $wpdb->posts joined_locations ON joined_meta_locations.meta_value = joined_locations.ID "; + return $join; } + ); + add_filter( + 'posts_orderby', + function ( $orderby ) { + global $wp_query; - return $join; - }); - add_filter( 'posts_orderby', function ( $orderby ) { - global $wp_query; + if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_LOCATION_ID ) { + $orderby = 'joined_locations.post_title ' . $wp_query->query_vars['order']; + } - if ( ! empty( $wp_query->query_vars['orderby'] ) && $wp_query->query_vars['orderby'] === \CommonsBooking\Model\Timeframe::META_LOCATION_ID ) { - $orderby = 'joined_locations.post_title ' . $wp_query->query_vars['order']; + return $orderby; } - - return $orderby; - }); + ); break; case 'type': $query->set( 'meta_key', 'type' ); @@ -1350,7 +1395,7 @@ public function setCustomColumnSortOrder( \WP_Query $query ) { $query->set( 'orderby', 'meta_value_num' ); break; default: - //this means, that further sorting is done by the inheriting method + // this means, that further sorting is done by the inheriting method return true; } } @@ -1363,17 +1408,17 @@ public function setCustomColumnSortOrder( \WP_Query $query ) { */ public function initHooks() { // Add custom cmb2 type for email booking codes by cron - add_action( 'cmb2_render_booking_codes_email_fields', ['\CommonsBooking\View\BookingCodes','renderCronEmailFields'], 10, 5 ); - add_action("cmb2_save_field_" . \CommonsBooking\View\BookingCodes::CRON_EMAIL_CODES,['\CommonsBooking\View\BookingCodes','cronEmailCodesSaved'],10,3); - + add_action( 'cmb2_render_booking_codes_email_fields', [ '\CommonsBooking\View\BookingCodes','renderCronEmailFields' ], 10, 5 ); + add_action( 'cmb2_save_field_' . \CommonsBooking\View\BookingCodes::CRON_EMAIL_CODES, [ '\CommonsBooking\View\BookingCodes','cronEmailCodesSaved' ], 10, 3 ); + // Add Meta Boxes add_action( 'cmb2_admin_init', array( $this, 'registerMetabox' ) ); // must be 'save_post' only because of priority in relation to cmb2 add_action( 'save_post', array( $this, 'savePost' ), 11, 2 ); - add_action('updated_post_meta',array($this, 'updatedPostMeta'),11,4); - + add_action( 'updated_post_meta', array( $this, 'updatedPostMeta' ), 11, 4 ); + // Add type filter to backend list view add_action( 'restrict_manage_posts', array( self::class, 'addAdminTypeFilter' ) ); add_action( 'restrict_manage_posts', array( self::class, 'addAdminItemFilter' ) ); @@ -1384,7 +1429,7 @@ public function initHooks() { // Listing of available items/locations add_shortcode( 'cb_items_table', array( Calendar::class, 'shortcode' ) ); - //rendering callback for field with id _cmb2_holiday - add_filter( 'cmb2_render_holiday_get_fields', array( Holiday::class, 'renderFields'), 10, 5 ); + // rendering callback for field with id _cmb2_holiday + add_filter( 'cmb2_render_holiday_get_fields', array( Holiday::class, 'renderFields' ), 10, 5 ); } } diff --git a/src/Wordpress/Options/AdminOptions.php b/src/Wordpress/Options/AdminOptions.php index 8f22ad01c..e30a1112b 100644 --- a/src/Wordpress/Options/AdminOptions.php +++ b/src/Wordpress/Options/AdminOptions.php @@ -20,7 +20,7 @@ class AdminOptions { */ public static function setOptionsDefaultValues() { - $options_array = include( COMMONSBOOKING_PLUGIN_DIR . '/includes/OptionsArray.php' ); + $options_array = include COMMONSBOOKING_PLUGIN_DIR . '/includes/OptionsArray.php'; $restored_fields = array(); foreach ( $options_array as $tab_id => $tab ) { @@ -31,7 +31,6 @@ public static function setOptionsDefaultValues() { $fields = $group['fields']; foreach ( $fields as $field ) { - $field_id = $field['id']; // set to current value from wp_options @@ -40,7 +39,7 @@ public static function setOptionsDefaultValues() { // we check if there is a default value set in OptionsArray.php and if the field type is not checkbox (cause checkboxes have empty values if unchecked ) if ( array_key_exists( 'default', $field ) && $field['type'] != 'checkbox' ) { // if field-value is not set already we add the default value to the options array - if ( empty ( $field_value ) ) { + if ( empty( $field_value ) ) { Settings::updateOption( $option_key, $field_id, $field['default'] ); $restored_fields[] = $field['name']; } @@ -50,9 +49,9 @@ public static function setOptionsDefaultValues() { } // maybe show admin notice if fields are restored to their default value - if ( ! empty($restored_fields) ) { - $message = commonsbooking_sanitizeHTML( __( 'Default values for following fields automatically set or restored, because they were empty:
        ', 'commonsbooking' ) ); - $message .= implode( "
        ", $restored_fields ); + if ( ! empty( $restored_fields ) ) { + $message = commonsbooking_sanitizeHTML( __( 'Default values for following fields automatically set or restored, because they were empty:
        ', 'commonsbooking' ) ); + $message .= implode( '
        ', $restored_fields ); new AdminMessage( $message ); } } diff --git a/src/Wordpress/Options/OptionsTab.php b/src/Wordpress/Options/OptionsTab.php index 9cbb78935..b5b9787cb 100644 --- a/src/Wordpress/Options/OptionsTab.php +++ b/src/Wordpress/Options/OptionsTab.php @@ -21,9 +21,9 @@ class OptionsTab { public $groups; // Error type for backend error output - public const ERROR_TYPE = "commonsbooking-options-error"; + public const ERROR_TYPE = 'commonsbooking-options-error'; - public const SUCCESS_TYPE = "commonsbooking-options-success"; + public const SUCCESS_TYPE = 'commonsbooking-options-success'; /** * @var \CMB2 */ @@ -38,7 +38,6 @@ public function __construct( string $id, array $content ) { add_action( 'cmb2_admin_init', array( $this, 'register' ) ); add_action( 'cmb2_save_options-page_fields', array( self::class, 'savePostOptions' ), 10 ); - } public function register() { @@ -58,16 +57,16 @@ public function registerOptionsTab() { 'option_key' => $this->option_key . '_' . $this->id, 'tab_group' => $this->option_key, 'tab_title' => $this->tab_title, - 'parent_slug' => $this->option_key + 'parent_slug' => $this->option_key, ); $top_level_args = array( 'option_key' => $this->option_key, - 'parent_slug' => 'options-general.php' + 'parent_slug' => 'options-general.php', ); /* set first option as top level parent */ - if ( isset ( $this->content['is_top_level'] ) && $this->content['is_top_level'] ) { + if ( isset( $this->content['is_top_level'] ) && $this->content['is_top_level'] ) { $args = array_merge( $default_args, $top_level_args ); } else { $args = $default_args; @@ -82,7 +81,6 @@ public function registerOptionsTab() { public function registerOptionsGroups() { foreach ( $this->groups as $group ) { - $group = $this->prependTitle( $group ); /* prepend title + description html */ // Add Fields @@ -103,13 +101,14 @@ public function registerOptionsGroups() { */ public static function prependTitle( array $metabox_group ): array { - if ( isset ( $metabox_group['title'] ) or isset ( $metabox_group['desc'] ) ) { - + if ( isset( $metabox_group['title'] ) or isset( $metabox_group['desc'] ) ) { $title = $metabox_group['title'] ?? ''; $desc = $metabox_group['desc'] ?? ''; $header_html = sprintf( - '

        %s

        %s', $title, $desc + '

        %s

        %s', + $title, + $desc ); $header_field = array( @@ -138,14 +137,13 @@ public static function savePostOptions() { // (CMB2-Hook 'cmb2_save_options-page_field') is too late for rendering of the admin page. // So if you want to refactor this, savePostOptions needs to be hooked into an action which fires earlier. - if ( array_key_exists( 'action', $_REQUEST ) && $_REQUEST['action'] == "commonsbooking_options_export" ) { + if ( array_key_exists( 'action', $_REQUEST ) && $_REQUEST['action'] == 'commonsbooking_options_export' ) { // Check for export action - if ( array_key_exists( 'export-filepath', $_REQUEST ) && $_REQUEST['export-filepath'] !== "" ) { - + if ( array_key_exists( 'export-filepath', $_REQUEST ) && $_REQUEST['export-filepath'] !== '' ) { if ( ! is_dir( $_REQUEST['export-filepath'] ) ) { set_transient( self::ERROR_TYPE, - commonsbooking_sanitizeHTML( __( "The export path does not exist or is not readable.", 'commonsbooking' ) ), + commonsbooking_sanitizeHTML( __( 'The export path does not exist or is not readable.', 'commonsbooking' ) ), 45 ); } @@ -153,32 +151,34 @@ public static function savePostOptions() { if ( ! is_writable( $_REQUEST['export-filepath'] ) ) { set_transient( self::ERROR_TYPE, - commonsbooking_sanitizeHTML( __( "The export path is not writeable.", 'commonsbooking' ) ), - 45 ); + commonsbooking_sanitizeHTML( __( 'The export path is not writeable.', 'commonsbooking' ) ), + 45 + ); } } - } elseif ( array_key_exists( 'action', $_REQUEST ) && $_REQUEST['action'] == "commonsbooking_options_advanced-options" ) { - //Check for request to clear cache - if ( array_key_exists( 'submit-cmb', $_REQUEST ) && $_REQUEST['submit-cmb'] == "clear-cache" ) { + } elseif ( array_key_exists( 'action', $_REQUEST ) && $_REQUEST['action'] == 'commonsbooking_options_advanced-options' ) { + // Check for request to clear cache + if ( array_key_exists( 'submit-cmb', $_REQUEST ) && $_REQUEST['submit-cmb'] == 'clear-cache' ) { try { Plugin::clearCache(); set_transient( self::SUCCESS_TYPE, - commonsbooking_sanitizeHTML( __( "Cache cleared.", 'commonsbooking' ) ), - 45 ); + commonsbooking_sanitizeHTML( __( 'Cache cleared.', 'commonsbooking' ) ), + 45 + ); } catch ( Exception $e ) { if ( WP_DEBUG ) { error_log( $e->getMessage() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } set_transient( self::ERROR_TYPE, - commonsbooking_sanitizeHTML( __( "Error while clearing the cache.", 'commonsbooking' ) ), - 45 ); + commonsbooking_sanitizeHTML( __( 'Error while clearing the cache.', 'commonsbooking' ) ), + 45 + ); } } } - // we set transient to be able to flush rewrites at an ini hook in Plugin.php to set permalinks properly set_transient( 'commonsbooking_options_saved', 1 ); } diff --git a/src/Wordpress/PostStatus/PostStatus.php b/src/Wordpress/PostStatus/PostStatus.php index 1ac0c0028..4c1b925bf 100644 --- a/src/Wordpress/PostStatus/PostStatus.php +++ b/src/Wordpress/PostStatus/PostStatus.php @@ -24,7 +24,7 @@ class PostStatus { * * @param $name * @param $label - * @param bool $public + * @param bool $public */ public function __construct( $name, $label, bool $public = true ) { $this->name = $name; @@ -39,14 +39,17 @@ public function __construct( $name, $label, bool $public = true ) { * Registers current post status. */ public function registerPostStatus() { - register_post_status( $this->name, array( - 'label' => $this->label, - 'public' => $this->public, - 'label_count' => _n_noop( - $this->label . ' (%s)', - $this->label . ' (%s)' + register_post_status( + $this->name, + array( + 'label' => $this->label, + 'public' => $this->public, + 'label_count' => _n_noop( + $this->label . ' (%s)', + $this->label . ' (%s)' + ), ) - ) ); + ); } /** @@ -63,7 +66,7 @@ public function addActions() { public function addOption() { global $post; - $active = ""; + $active = ''; if ( $post ) { if ( $post->post_status == $this->name ) { $active = "jQuery( '#post-status-display' ).text( '" . $this->label . "' ); jQuery( 'select[name=\"post_status\"]' ).val('" . $this->name . "');"; @@ -71,10 +74,10 @@ public function addOption() { echo ""; + '; } } @@ -84,9 +87,8 @@ public function addOption() { public function addQuickedit() { echo ""; } - } diff --git a/src/Wordpress/Widget/UserWidget.php b/src/Wordpress/Widget/UserWidget.php index e62c62f2a..14c7ace02 100644 --- a/src/Wordpress/Widget/UserWidget.php +++ b/src/Wordpress/Widget/UserWidget.php @@ -15,46 +15,46 @@ function __construct() { parent::__construct( 'commonsbooking-user-widget', // Base ID 'CommonsBooking User Widget', // Name - array( 'description' => esc_html__( 'Shows links to My Bookings, Login, Logout. Please set the Bookings Page in CommonsBooking Settings (General-Tab)', 'commonsbooking' ), ) + array( 'description' => esc_html__( 'Shows links to My Bookings, Login, Logout. Please set the Bookings Page in CommonsBooking Settings (General-Tab)', 'commonsbooking' ) ) ); - add_action( 'widgets_init', function () { - register_widget( '\CommonsBooking\Wordpress\Widget\UserWidget' ); - } ); - + add_action( + 'widgets_init', + function () { + register_widget( '\CommonsBooking\Wordpress\Widget\UserWidget' ); + } + ); } public $args = array( 'before_title' => '

        ', 'after_title' => '

        ', 'before_widget' => '
        ', - 'after_widget' => '
        ' + 'after_widget' => '', ); public function widget( $args, $instance ) { - echo commonsbooking_sanitizeHTML($args['before_widget']); + echo commonsbooking_sanitizeHTML( $args['before_widget'] ); if ( ! empty( $instance['title'] ) ) { - echo commonsbooking_sanitizeHTML($args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title']); + echo commonsbooking_sanitizeHTML( $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'] ); } echo '
        '; - echo commonsbooking_sanitizeHTML($this->renderWidgetContent()); + echo commonsbooking_sanitizeHTML( $this->renderWidgetContent() ); echo '
        '; - echo commonsbooking_sanitizeHTML($args['after_widget']); - + echo commonsbooking_sanitizeHTML( $args['after_widget'] ); } public function renderWidgetContent() { - $content = ""; + $content = ''; if ( is_user_logged_in() ) { - $current_user = wp_get_current_user(); $bookings_page_url = get_permalink( Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_general', 'bookings_page' ) ); @@ -63,7 +63,7 @@ public function renderWidgetContent() { } // user name or email - if (!empty($current_user->first_name)) { + if ( ! empty( $current_user->first_name ) ) { $loginname = $current_user->first_name; } else { $loginname = $current_user->user_email; @@ -79,20 +79,17 @@ public function renderWidgetContent() { // translators: $s = wp logout url $content .= sprintf( __( '
      • Log out
      • ', 'commonsbooking' ), wp_logout_url() ); $content .= '
      '; - } else { - - $content = __( 'You are not logged in.', 'commonsbooking' ); - $content .= "
        "; + $content = __( 'You are not logged in.', 'commonsbooking' ); + $content .= '
          '; // translators: $s = wp login url $content .= sprintf( __( '
        • Login
        • ', 'commonsbooking' ), wp_login_url() ); // translators: $s = wp registration url $content .= sprintf( __( '
        • Register
        • ', 'commonsbooking' ), wp_registration_url() ); - $content .= "
        "; + $content .= '
      '; } return $content; - } /** @@ -105,22 +102,21 @@ public function form( $instance ) { $title = ! empty( $instance['title'] ) ? $instance['title'] : esc_html__( '', 'commonsbooking' ); $text = ! empty( $instance['text'] ) ? $instance['text'] : esc_html__( '', 'commonsbooking' ); ?> -

      - - -

      -

      - - -

      +

      + + +

      +

      + + +

      canCancel() ) { - $form_post_status = 'canceled'; + $form_post_status = 'canceled'; $icalbutton_label = esc_html__( 'Add to Calendar', 'commonsbooking' ); - $button_label = esc_html__( 'Cancel Booking', 'commonsbooking' ); + $button_label = esc_html__( 'Cancel Booking', 'commonsbooking' ); } if ( isset( $form_post_status ) ) { - ?> - ID ) { - ?> -
      - - - - - - - - - - - - + ?> + ID ) { + ?> + + + + + + + + + + + + + - - + +
      - - + diff --git a/templates/booking-single-notallowed.php b/templates/booking-single-notallowed.php index 62fafc025..b5419b4bd 100644 --- a/templates/booking-single-notallowed.php +++ b/templates/booking-single-notallowed.php @@ -6,15 +6,16 @@ ?>
      - '; - if ( ! is_user_logged_in() ) { - printf( '%s', - esc_url( wp_login_url()), - esc_html__('Login to your account', 'commonsbooking') - ); - } - ?> + '; + if ( ! is_user_logged_in() ) { + printf( + '%s', + esc_url( wp_login_url() ), + esc_html__( 'Login to your account', 'commonsbooking' ) + ); + } + ?>
      diff --git a/templates/booking-single.php b/templates/booking-single.php index 74c1b0fef..3c94b2e72 100644 --- a/templates/booking-single.php +++ b/templates/booking-single.php @@ -71,16 +71,16 @@ formattedAddressOneLine(); - if (!empty($location_address)){ + if ( ! empty( $location_address ) ) { ?>
      - formattedPickupInstructionsOneLine(); - if (!empty($location_pickup_instructions)){ + if ( ! empty( $location_pickup_instructions ) ) { ?>
      @@ -90,13 +90,13 @@ } // show contact details only after booking is confirmed or if options are set to show contactinfo even on unconfirmed booking status if ( $post->post_status == 'confirmed' or $show_contactinfo_unconfirmed == 'on' ) { - ?> + ?>
      formattedContactInfoOneLine() ); ?>
      @@ -104,7 +104,7 @@
      @@ -114,37 +114,39 @@

      - -
      -
      -
      user_login . " (" . $booking_admin->first_name . " " . $booking_admin->last_name . ")" ); - ?> -
      + +
      +
      +
      + user_login . ' (' . $booking_admin->first_name . ' ' . $booking_admin->last_name . ')' ); + ?> +
      +
      + + @@ -158,7 +160,7 @@ $bookingCommentDescription = Settings::getOption( 'commonsbooking_options_general', 'booking-comment-description' ); if ( $post->post_status == 'unconfirmed' ) { - ?> + ?>

      @@ -167,14 +169,13 @@
      + name="comment">returnComment() ); ?>
      returnComment() ) { - ?> + } elseif ( $booking->returnComment() ) { + ?>

      @@ -184,7 +185,6 @@
      post_status() == 'unconfirmed' ) { - $form_action = 'delete_unconfirmed'; - include COMMONSBOOKING_PLUGIN_DIR . 'templates/booking-single-form.php'; + $form_action = 'delete_unconfirmed'; + include COMMONSBOOKING_PLUGIN_DIR . 'templates/booking-single-form.php'; } else { // if booking is confirmed we display the cancel booking button $form_action = 'cancel'; diff --git a/templates/calendar-key.php b/templates/calendar-key.php index 66f325249..4a8485675 100644 --- a/templates/calendar-key.php +++ b/templates/calendar-key.php @@ -2,16 +2,15 @@ /** * Template: calendar-key - * - * This template part is used by timeframe-calendar and the item table * + * This template part is used by timeframe-calendar and the item table */ - ?> +?>
      - :
      -
      | -
      | -
      | -

      + :
      +
      | +
      | +
      | +

      \ No newline at end of file diff --git a/templates/dashboard-index.php b/templates/dashboard-index.php index 2fe2b0604..61bb78c31 100644 --- a/templates/dashboard-index.php +++ b/templates/dashboard-index.php @@ -1,26 +1,26 @@

      Dashboard

      - +

      .

      + echo esc_html__( 'Welcome to CommonsBooking', 'commonsbooking' );?>.
      - +

      -

      +

        -
      • -
      • -
      • +
      • +
      • +
      -

      +

      @@ -28,35 +28,35 @@
      -

      +

      - +
      -

      +

      -

      -
        - -
      • +

        +
      @@ -66,29 +66,29 @@
      -

      - +
      -

      - +
      diff --git a/templates/item-calendar-header.php b/templates/item-calendar-header.php index 950d194ac..d15640d7a 100644 --- a/templates/item-calendar-header.php +++ b/templates/item-calendar-header.php @@ -1,15 +1,15 @@ thumbnail('cb_listing_medium')); // div.thumbnail is printed by function + echo commonsbooking_sanitizeHTML( $item->thumbnail( 'cb_listing_medium' ) ); // div.thumbnail is printed by function ?>
      -

      post_title); ?>

      +

      post_title ); ?>

      \ No newline at end of file diff --git a/templates/item-single-meta.php b/templates/item-single-meta.php index 2e479f9f8..a4df19fa9 100644 --- a/templates/item-single-meta.php +++ b/templates/item-single-meta.php @@ -1,12 +1,10 @@ property - * item Model methods are available as $item->myMethod() - * + * item Model methods are available as $item->myMethod() */ global $templateData; $item = $templateData['item']; -?> diff --git a/templates/item-single.php b/templates/item-single.php index ebb4ad908..2765ea19f 100644 --- a/templates/item-single.php +++ b/templates/item-single.php @@ -1,50 +1,53 @@ ' . esc_html__( $bookThisItemText, 'commonsbooking') . ''; - commonsbooking_get_template_part( 'location', 'calendar-header' ); // file: item-calendar-header.php - commonsbooking_get_template_part( 'timeframe', 'calendar' ); // file: timeframe-calendar.php - } + // Single Item View +if ( array_key_exists( 'location', $templateData ) && $templateData['location'] ) { // item selected, so we display the booking calendar + echo '

      ' . esc_html__( $bookThisItemText, 'commonsbooking' ) . '

      '; + commonsbooking_get_template_part( 'location', 'calendar-header' ); // file: item-calendar-header.php + commonsbooking_get_template_part( 'timeframe', 'calendar' ); // file: timeframe-calendar.php +} + + // Multi item view +if ( array_key_exists( 'locations', $templateData ) && $templateData['locations'] ) { + foreach ( $templateData['locations'] as $location ) { + $templateData['location'] = $location; + commonsbooking_get_template_part( 'item', 'withlocation' ); // file: location-withitem.php + } // end foreach $timeframes +} // $item_is_selected - // Multi item view - if(array_key_exists('locations', $templateData) && $templateData['locations']) { - foreach ($templateData['locations'] as $location ) { - $templateData['location'] = $location; - commonsbooking_get_template_part( 'item', 'withlocation' ); // file: location-withitem.php - } // end foreach $timeframes - } // $item_is_selected - // item not available if no valid location reference found - if( !array_key_exists('location', $templateData) && empty( $templateData['locations'] ) ) { ?> -
      +
      + -
      -login or register.', 'commonsbooking' ) ), - esc_url( wp_login_url( $current_url ) ), esc_url( wp_registration_url() ) - ); -?> -
      - +
      + login or register.', 'commonsbooking' ) ), + esc_url( wp_login_url( $current_url ) ), + esc_url( wp_registration_url() ) + ); + ?> +
      + ID, get_the_permalink($item->ID) ); // booking link set to item detail page with location ID +$permalink = add_query_arg( 'cb-location', $location->ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID -$timeframes = $location->getBookableTimeframesByItem($item->ID, true); +$timeframes = $location->getBookableTimeframesByItem( $item->ID, true ); ?> -thumbnail('cb_listing_small')); // div.thumbnail is printed by function ?> +thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function ?>
      -

      post_title); ?>

      - -
      - formattedBookableDate()); ?> -
      - +

      post_title ); ?>

      + +
      + formattedBookableDate() ); ?> +
      +
      - +
      diff --git a/templates/location-calendar-header.php b/templates/location-calendar-header.php index eed77d487..516ab6995 100644 --- a/templates/location-calendar-header.php +++ b/templates/location-calendar-header.php @@ -1,39 +1,41 @@ thumbnail('cb_listing_small')); // div.thumbnail is printed by function + echo commonsbooking_sanitizeHTML( $location->thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function ?>
      -

      - - post_title); ?> - -

      +

      + + post_title ); ?> + +

      formattedAddressOneLine(); - if (!empty($locationAddress)){ + if ( ! empty( $locationAddress ) ) { ?>
      - hasMap() ) { - \CommonsBooking\View\Location::renderLocationMap( $location ); - } + if ( $location->hasMap() ) { + \CommonsBooking\View\Location::renderLocationMap( $location ); + } ?> -
      formattedPickupInstructionsOneLine()) { - ?> -formattedPickupInstructionsOneLine()); ?> - -
      +
      + formattedPickupInstructionsOneLine() ) { + ?> + + formattedPickupInstructionsOneLine() ); ?> + +
      - diff --git a/templates/location-single-meta.php b/templates/location-single-meta.php index 30ada9f2b..a8722bd66 100644 --- a/templates/location-single-meta.php +++ b/templates/location-single-meta.php @@ -4,53 +4,53 @@ * * WP Post properties for location are available as $location->property * location Model methods are available as $location->myMethod() - * */ global $templateData; $location = $templateData['location']; -$location_address = $location->formattedAddressOneLine(); -$location_contact = $location->formattedContactInfoOneLine(); -$pickup_instructions = $location->formattedPickupInstructions(); -$show_contactinfo_unconfirmed = \CommonsBooking\Settings\Settings::getOption('commonsbooking_options_templates', 'show_contactinfo_unconfirmed'); -$text_hidden_contactinfo = \CommonsBooking\Settings\Settings::getOption('commonsbooking_options_templates', 'text_hidden-contactinfo'); +$location_address = $location->formattedAddressOneLine(); +$location_contact = $location->formattedContactInfoOneLine(); +$pickup_instructions = $location->formattedPickupInstructions(); +$show_contactinfo_unconfirmed = \CommonsBooking\Settings\Settings::getOption( 'commonsbooking_options_templates', 'show_contactinfo_unconfirmed' ); +$text_hidden_contactinfo = \CommonsBooking\Settings\Settings::getOption( 'commonsbooking_options_templates', 'text_hidden-contactinfo' ); ?>
      -
      -
      formattedAddressOneLine()); ?>
      - hasMap() ) { - \CommonsBooking\View\Location::renderLocationMap( $location ); - } +
      +
      formattedAddressOneLine() ); ?>
      + hasMap() ) { + \CommonsBooking\View\Location::renderLocationMap( $location ); + } ?>
      -
      - -
      formattedContactInfoOneLine()); ?>
      - -
      - +
      + +
      formattedContactInfoOneLine() ); ?>
      + +
      +
      - +
      -
      -
      formattedPickupInstructionsOneLine()); ?>
      -
      +
      +
      formattedPickupInstructionsOneLine() ); ?>
      +
      diff --git a/templates/location-single.php b/templates/location-single.php index faeeb1229..1b2c0476d 100644 --- a/templates/location-single.php +++ b/templates/location-single.php @@ -1,49 +1,51 @@ ' . esc_html__( $bookThisItemText, 'commonsbooking') . ''; - commonsbooking_get_template_part( 'item', 'calendar-header' ); // file: item-calendar-header.php - commonsbooking_get_template_part( 'timeframe', 'calendar' ); // file: timeframe-calendar.php - } + // Single Item View +if ( array_key_exists( 'item', $templateData ) && $templateData['item'] ) { // item selected, so we display the booking calendar + echo '

      ' . esc_html__( $bookThisItemText, 'commonsbooking' ) . '

      '; + commonsbooking_get_template_part( 'item', 'calendar-header' ); // file: item-calendar-header.php + commonsbooking_get_template_part( 'timeframe', 'calendar' ); // file: timeframe-calendar.php +} - // Multi item view - if(array_key_exists('items', $templateData) && $templateData['items']) { - foreach ($templateData['items'] as $item ) { - $templateData['item'] = $item; - commonsbooking_get_template_part( 'location', 'withitem' ); // file: location-withitem.php - } // end foreach $timeframes - } // $item_is_selected + // Multi item view +if ( array_key_exists( 'items', $templateData ) && $templateData['items'] ) { + foreach ( $templateData['items'] as $item ) { + $templateData['item'] = $item; + commonsbooking_get_template_part( 'location', 'withitem' ); // file: location-withitem.php + } // end foreach $timeframes +} // $item_is_selected - if(!array_key_exists('item', $templateData) && !array_key_exists('items', $templateData)) { ?> -
      -
      -login or register.', 'commonsbooking' ) ), - esc_url( wp_login_url( $current_url ) ), esc_url( wp_registration_url() ) - ); -?> -
      - +
      + +
      + login or register.', 'commonsbooking' ) ), + esc_url( wp_login_url( $current_url ) ), + esc_url( wp_registration_url() ) + ); + ?> +
      + ID, get_the_permalink($item->ID) ); // booking link set to item detail page with location ID +$item = $templateData['item']; +$button_label = Settings::getOption( 'commonsbooking_options_templates', 'label-booking-button' ); +$permalink = add_query_arg( 'cb-location', $location->ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID -$timeframes = $item->getBookableTimeframesByLocation($location->ID, true); +$timeframes = $item->getBookableTimeframesByLocation( $location->ID, true ); ?> -thumbnail('cb_listing_medium')); // div.thumbnail is printed by function ?> +thumbnail( 'cb_listing_medium' ) ); // div.thumbnail is printed by function ?>
      -

      post_title); ?>

      - -
      - formattedBookableDate()); ?> -
      - +

      post_title ); ?>

      + +
      + formattedBookableDate() ); ?> +
      +
      - +
      diff --git a/templates/massoperations-index.php b/templates/massoperations-index.php index a9757550a..e84eead2b 100644 --- a/templates/massoperations-index.php +++ b/templates/massoperations-index.php @@ -3,16 +3,19 @@
      -

      .

      +

      + + .

      - +
      - +
      - +

      diff --git a/templates/shortcode-bookings.php b/templates/shortcode-bookings.php index 0799faca1..1980c35ac 100644 --- a/templates/shortcode-bookings.php +++ b/templates/shortcode-bookings.php @@ -4,90 +4,90 @@ * Model: Booking * View: Booking::shortcode * $templateData is set in + * * @see \CommonsBooking\View\Booking::getBookingListData() * * List all allowed bookings with filter - * */ global $templateData; -if ( !is_user_logged_in() ) { - $current_url = $_SERVER['REQUEST_URI']; - $noResultText = sprintf( commonsbooking_sanitizeHTML( __('Please login to see your bookings.', 'commonsbooking') ), wp_login_url( $current_url ) ); -} else { - $noResultText = commonsbooking_sanitizeHTML( __("No bookings available.", "commonsbooking") ); +if ( ! is_user_logged_in() ) { + $current_url = $_SERVER['REQUEST_URI']; + $noResultText = sprintf( commonsbooking_sanitizeHTML( __( 'Please login to see your bookings.', 'commonsbooking' ) ), wp_login_url( $current_url ) ); +} else { + $noResultText = commonsbooking_sanitizeHTML( __( 'No bookings available.', 'commonsbooking' ) ); } $response = ''; -if ($templateData && $templateData['total'] > 0) { - $showFilters = !commonsbooking_isCurrentUserSubscriber(); +if ( $templateData && $templateData['total'] > 0 ) { + $showFilters = ! commonsbooking_isCurrentUserSubscriber(); - $response .= ' + $response .= '
      '; $response .= $templateData['menu'] ?? ''; - $response .= ' -
      + $response .= ' +
      - +
      - +
      '; - foreach ($templateData['filters'] as $label => $values) { - $response .= ' + foreach ( $templateData['filters'] as $label => $values ) { + $response .= '
      - +
      '; - } + } - $response .= ' + $response .= '
      - +
      - +
      '; - $response .= ' + $response .= '
      @@ -95,11 +95,10 @@
      '; - // Remove line breaks and whitespaces between tags - $response = preg_replace( "/\r|\n/", "", $response); - $response = preg_replace('/\>\s+\<', $response); - echo commonsbooking_sanitizeHTML($response); - + // Remove line breaks and whitespaces between tags + $response = preg_replace( "/\r|\n/", '', $response ); + $response = preg_replace( '/\>\s+\<', $response ); + echo commonsbooking_sanitizeHTML( $response ); } else { - echo commonsbooking_sanitizeHTML($noResultText); + echo commonsbooking_sanitizeHTML( $noResultText ); } diff --git a/templates/shortcode-items.php b/templates/shortcode-items.php index baa0f6220..4ddbfc0a3 100644 --- a/templates/shortcode-items.php +++ b/templates/shortcode-items.php @@ -8,13 +8,12 @@ * * WP Post properties for locations are available as $item->property * location Model methods are available as $item->myMethod() - * */ global $templateData; -$item = new \CommonsBooking\Model\Item($templateData['item']); -$hasTimeFrames = (array_key_exists('data', $templateData) && count($templateData['data'])); +$item = new \CommonsBooking\Model\Item( $templateData['item'] ); +$hasTimeFrames = ( array_key_exists( 'data', $templateData ) && count( $templateData['data'] ) ); // the item-not-available message (if item ist currently not available) can be defined via plugin options -> message templates $noResultText = \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'item-not-available' ); @@ -22,27 +21,27 @@ ?>
      - thumbnail('cb_listing_medium')); ?> -
      -

      titleLink() ); ?>

      - excerpt()); ?> - -
      - -
      + thumbnail( 'cb_listing_medium' ) ); ?> +
      +

      titleLink() ); ?>

      + excerpt() ); ?> + +
      + +
      $data ) { - $location = new \CommonsBooking\Model\Location($locationId); - set_query_var( 'item', $item ); - set_query_var( 'location', $location ); - set_query_var( 'data', $data ); - commonsbooking_get_template_part( 'timeframe', 'withlocation' ); - } - }; // end if ($timeframes) ?> \ No newline at end of file + foreach ( $templateData['data'] as $locationId => $data ) { + $location = new \CommonsBooking\Model\Location( $locationId ); + set_query_var( 'item', $item ); + set_query_var( 'location', $location ); + set_query_var( 'data', $data ); + commonsbooking_get_template_part( 'timeframe', 'withlocation' ); + } +} // end if ($timeframes) ?> \ No newline at end of file diff --git a/templates/shortcode-items_table.php b/templates/shortcode-items_table.php index 43d7a7e55..a47194b38 100644 --- a/templates/shortcode-items_table.php +++ b/templates/shortcode-items_table.php @@ -5,8 +5,6 @@ * Model: Calendar * * Shows an availability table for items - * - * */ @@ -16,7 +14,7 @@ ?>
      - +
      diff --git a/templates/shortcode-locations.php b/templates/shortcode-locations.php index 342c08c54..40148abd4 100644 --- a/templates/shortcode-locations.php +++ b/templates/shortcode-locations.php @@ -7,32 +7,32 @@ * * WP Post properties for locations are available as $location->property * location Model methods are available as $location->myMethod() - * */ global $templateData; -$location = new \CommonsBooking\Model\Location($templateData['location']); +$location = new \CommonsBooking\Model\Location( $templateData['location'] ); // the location without items message is shown if there are currently no available items at this location. Can be defined via plugin options -> message templates $noResultText = \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'location-without-items' ); ?>
      - thumbnail('cb_listing_medium')); ?> -
      -

      titleLink() ); ?>

      - excerpt()); ?> -
      + thumbnail( 'cb_listing_medium' ) ); ?> +
      +

      titleLink() ); ?>

      + excerpt() ); ?> +
      $data ) { - $item = new \CommonsBooking\Model\Item($itemId); - set_query_var( 'item', $item ); - set_query_var( 'location', $location ); - set_query_var( 'data', $data ); - commonsbooking_get_template_part( 'timeframe', 'withitem' ); // file: timeframe-withlocation.php - } -} else { ?> -
      +if ( array_key_exists( 'data', $templateData ) && count( $templateData['data'] ) ) { + foreach ( $templateData['data'] as $itemId => $data ) { + $item = new \CommonsBooking\Model\Item( $itemId ); + set_query_var( 'item', $item ); + set_query_var( 'location', $location ); + set_query_var( 'data', $data ); + commonsbooking_get_template_part( 'timeframe', 'withitem' ); // file: timeframe-withlocation.php + } +} else { + ?> +
      diff --git a/templates/timeframe-calendar-day.php b/templates/timeframe-calendar-day.php index de679a307..13b22e921 100644 --- a/templates/timeframe-calendar-day.php +++ b/templates/timeframe-calendar-day.php @@ -1,42 +1,44 @@
    • -
      - getFormattedDate('d')); ?> - getFormattedDate('M')); ?>> -
      +
      + getFormattedDate( 'd' ) ); ?> + getFormattedDate( 'M' ) ); ?>> +
      - $slot) { - if(array_key_exists('timeframe', $slot) && $slot['timeframe']) { - if($slot['timeframe']['type'] == '2') { ?> -
      - - {{ slot.timestart }} - {{ slot.timeend }} - - {% if backend != 'true' %} -
      - {{ wp_nonce|raw }} - - - - - - - - -
      - {% endif %} -
      - -
      - - {{ slot.timestart }} - {{ slot.timeend }} - -
      - + $slot ) { + if ( array_key_exists( 'timeframe', $slot ) && $slot['timeframe'] ) { + if ( $slot['timeframe']['type'] == '2' ) { + ?> +
      + + {{ slot.timestart }} - {{ slot.timeend }} + + {% if backend != 'true' %} +
      + {{ wp_nonce|raw }} + + + + + + + + +
      + {% endif %} +
      + +
      + + {{ slot.timestart }} - {{ slot.timeend }} + +
      +
    • diff --git a/templates/timeframe-calendar.php b/templates/timeframe-calendar.php index 0fedf00ba..25448a752 100644 --- a/templates/timeframe-calendar.php +++ b/templates/timeframe-calendar.php @@ -7,154 +7,154 @@ * We recommend not to edit this file as it might be modified and enhancend during updates */ - global $templateData; + global $templateData; - // we check if template is used not used in backend ... + // we check if template is used not used in backend ... if ( ! array_key_exists( 'backend', $templateData ) || $templateData['backend'] != true ) { - do_action( 'commonsbooking_before_timeframe-calendar' ); - ?> - - -
      + do_action( 'commonsbooking_before_timeframe-calendar' ); + ?> + + +
      - -
      -
      - + +
      + + - - - - - - + + + + + + -
      - - - -
      - -
      - - - +
      + + + +
      + +
      + + + -
      -
      -
      - -
      - - - -
      -
      +
      +
      +
      + +
      + + + +
      +
      -
      - : - - -
        - isActive() ) { - echo '
      • '; - echo commonsbooking_sanitizeHTML( - sprintf( - // translators: %1$s = Start date and time formatted - __( 'From %1$s', 'commonsbooking' ), - $restriction->getFormattedStartDateTime() - ) - ); + $restrictions = $templateData['restrictions']; + if ( count( $restrictions ) ) { + ?> +
        + : + + +
          + isActive() ) { + echo '
        • '; + echo commonsbooking_sanitizeHTML( + sprintf( + // translators: %1$s = Start date and time formatted + __( 'From %1$s', 'commonsbooking' ), + $restriction->getFormattedStartDateTime() + ) + ); - // If there's - if ( $restriction->hasEnddate() ) { - echo ' ' . commonsbooking_sanitizeHTML( - sprintf( - // translators: %1$s = End date and time formatted - __( 'until probably %1$s:', 'commonsbooking' ), - $restriction->getFormattedEndDateTime() - ) - ); - echo '
          '; - } else { - echo ':
          '; - } + // If there's + if ( $restriction->hasEnddate() ) { + echo ' ' . commonsbooking_sanitizeHTML( + sprintf( + // translators: %1$s = End date and time formatted + __( 'until probably %1$s:', 'commonsbooking' ), + $restriction->getFormattedEndDateTime() + ) + ); + echo '
          '; + } else { + echo ':
          '; + } - echo '' . commonsbooking_sanitizeHTML( $restriction->getHint() ) . ''; - echo '
        • '; - } - } - ?> -
        -
        - -
        - -
      + echo '' . commonsbooking_sanitizeHTML( $restriction->getHint() ) . ''; + echo ''; + } + } + ?> +
    + + + + + - + ?> + - - -
    - maxDays ) ); - ?> - - advanceBookingDays ) ); - ?> -
    -
    - + +
    + maxDays ) ); + ?> + + advanceBookingDays ) ); + ?> +
    +
    + -
      - getDays() as $day ) { - if ( $day->getDayOfWeek() == $dayNr ) { - include __DIR__ . 'timeframe-calendar-day.php'; - } - } - } - ?> -
    + foreach ( $templateData['calendar']['weeks'] as $week ) { + ?> +
      + getDays() as $day ) { + if ( $day->getDayOfWeek() == $dayNr ) { + include __DIR__ . 'timeframe-calendar-day.php'; + } + } + } + ?> +
    - '; - if ( ! is_user_logged_in() ) { - printf( '%s', - esc_url( wp_login_url()), - esc_html__('Login to your account', 'commonsbooking') - ); - } - ?> + '; + if ( ! is_user_logged_in() ) { + printf( + '%s', + esc_url( wp_login_url() ), + esc_html__( 'Login to your account', 'commonsbooking' ) + ); + } + ?>
    diff --git a/templates/timeframe-withitem.php b/templates/timeframe-withitem.php index 9571f9e17..071231cde 100644 --- a/templates/timeframe-withitem.php +++ b/templates/timeframe-withitem.php @@ -1,31 +1,31 @@ ID, get_the_permalink($item->ID) ); // booking link set to item detail page with location ID +$button_label = Settings::getOption( 'commonsbooking_options_templates', 'label-booking-button' ); +$permalink = add_query_arg( 'cb-location', $location->ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID ?> -thumbnail('cb_listing_small')); // div.thumbnail is printed by function ?> +thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function ?>
    -

    - - post_title); ?> - -

    -
    - '; - } - } - ?> -
    +

    + + post_title ); ?> + +

    +
    + '; + } + } + ?> +
    - +
    diff --git a/templates/timeframe-withlocation.php b/templates/timeframe-withlocation.php index c642f3351..241cff508 100644 --- a/templates/timeframe-withlocation.php +++ b/templates/timeframe-withlocation.php @@ -2,7 +2,7 @@ /** * Template: timeframe-withlocation - * + * * This template is included in parent template shortcode-items or shortcode-locations * * $data is set in parent template @@ -11,37 +11,37 @@ use CommonsBooking\Settings\Settings; -$button_label = \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'label-booking-button'); -$permalink = add_query_arg ( 'cb-location', $location->ID, get_the_permalink($item->ID) ); // booking link set to item detail page with location ID +$button_label = \CommonsBooking\Settings\Settings::getOption( COMMONSBOOKING_PLUGIN_SLUG . '_options_templates', 'label-booking-button' ); +$permalink = add_query_arg( 'cb-location', $location->ID, get_the_permalink( $item->ID ) ); // booking link set to item detail page with location ID ?> -thumbnail('cb_listing_small')); // div.thumbnail is printed by function ?> +thumbnail( 'cb_listing_small' ) ); // div.thumbnail is printed by function ?>
    -

    - - post_title); ?> - -

    -
    - '; - } - } - ?> -
    +

    + + post_title ); ?> + +

    +
    + '; + } + } + ?> +
    - +
    diff --git a/tests/php/Messages/MessageTest.php b/tests/php/Messages/MessageTest.php index 6fb078587..b09cc88fd 100644 --- a/tests/php/Messages/MessageTest.php +++ b/tests/php/Messages/MessageTest.php @@ -107,7 +107,7 @@ public function testGetPost() { } public function testSendNotificationMail() { - $this->message->SendNotificationMail(); + $this->message->sendNotificationMail(); /** @var \PHPMailer\PHPMailer\PHPMailer $mailer */ $mailer = $this->getMockMailer(); $this->assertEmpty($mailer->ErrorInfo); @@ -162,7 +162,7 @@ public function test_1433() { $fromMail = self::FROM_MAIL; $fromHeader = 'From: ' . $fromName . ' <' . $fromMail . '>'; $subject = 'Test ' . $specialChar . ' Subject'; - + $this->message = $this->getMockBuilder(Message::class) ->onlyMethods(['sendMessage']) ->setConstructorArgs([$this->postID, self::ACTION]) @@ -175,7 +175,7 @@ public function test_1433() { $subject, $fromHeader, ] ); - $this->message->SendNotificationMail(); + $this->message->sendNotificationMail(); /** @var \PHPMailer\PHPMailer\PHPMailer $mailer */ $mailer = $this->getMockMailer(); $this->assertEquals($fromMail, $mailer->From); diff --git a/tests/php/Repository/TimeframeTest.php b/tests/php/Repository/TimeframeTest.php index b0f5d2004..c7e40e0ae 100644 --- a/tests/php/Repository/TimeframeTest.php +++ b/tests/php/Repository/TimeframeTest.php @@ -31,14 +31,14 @@ class TimeframeTest extends CustomPostTypeTest { protected array $allTimeframes; /** - * Create a completely seperate item, location and timeframe. + * Create a completely separate item, location and timeframe. * @return void */ private function createOtherTimeframe( $start = null, $end = null ) { - if ( $start = null ) { + if ( $start === null ) { $start = $this->repetition_start; } - if ( $end = null ) { + if ( $end === null ) { $end = $this->repetition_end; } $this->otherItemId = $this->createItem( "Other Item" );