From 64caccc5c1424a61ef1ba604a4c0a9dd97dd365c Mon Sep 17 00:00:00 2001 From: Viktor Miller Date: Sat, 7 Feb 2026 13:02:46 +0900 Subject: [PATCH] fix: resolve form submission issues and add CPT detail view - Rename day/month/year form fields to umzug_day/umzug_month/umzug_year to avoid conflict with WordPress reserved public query variables that caused a 404 on form POST - Move form handler instantiation to init_hooks() so handle_submission registers on the init action before it fires - Add standalone template fallback: detect [umzugsliste] shortcode in page content when form_page_id option is not set - Add submission details meta box to CPT entries showing addresses, furniture, additional work, and status - Add German translations for all new admin meta box strings Co-Authored-By: Claude Opus 4.6 --- .claude/settings.local.json | 9 -- .gitignore | 1 + includes/class-cpt.php | 162 +++++++++++++++++++++++++- includes/class-date-helpers.php | 6 +- includes/class-email-generator.php | 6 +- includes/class-form-handler.php | 6 +- languages/siegel-umzugsliste-de_DE.mo | Bin 14037 -> 16248 bytes languages/siegel-umzugsliste-de_DE.po | 72 ++++++++++++ umzugsliste.php | 22 +++- 9 files changed, 261 insertions(+), 23 deletions(-) delete mode 100644 .claude/settings.local.json create mode 100644 .gitignore diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index b7290fb..0000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "permissions": { - "allow": [ - "Skill(gsd:audit-milestone)", - "WebSearch", - "Bash(wp i18n make-pot:*)" - ] - } -} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d6b130c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.claude/settings.local.json diff --git a/includes/class-cpt.php b/includes/class-cpt.php index c85cbcb..15884a1 100644 --- a/includes/class-cpt.php +++ b/includes/class-cpt.php @@ -32,7 +32,7 @@ class Umzugsliste_CPT { * Constructor */ private function __construct() { - // CPT registration is called directly from main plugin init + add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) ); } /** @@ -68,4 +68,164 @@ class Umzugsliste_CPT { register_post_type( 'umzugsliste_entry', $args ); } + + /** + * Register meta boxes + */ + public function add_meta_boxes() { + add_meta_box( + 'umzugsliste_entry_details', + __( 'Submission Details', 'siegel-umzugsliste' ), + array( $this, 'render_details_meta_box' ), + 'umzugsliste_entry', + 'normal', + 'high' + ); + } + + /** + * Render the submission details meta box + * + * @param WP_Post $post Current post object + */ + public function render_details_meta_box( $post ) { + $data = json_decode( $post->post_content, true ); + + if ( empty( $data ) ) { + echo '

' . esc_html__( 'No submission data found.', 'siegel-umzugsliste' ) . '

'; + return; + } + + // Meta info + $email_sent = get_post_meta( $post->ID, '_umzugsliste_email_sent', true ); + $email_time = get_post_meta( $post->ID, '_umzugsliste_email_sent_at', true ); + $total_cbm = get_post_meta( $post->ID, '_umzugsliste_total_cbm', true ); + + echo ''; + echo '
'; + + // Status bar + echo '

' . esc_html__( 'Email sent:', 'siegel-umzugsliste' ) . ' '; + echo $email_sent ? esc_html__( 'Yes', 'siegel-umzugsliste' ) : esc_html__( 'No', 'siegel-umzugsliste' ); + if ( $email_time ) { + echo ' (' . esc_html( $email_time ) . ')'; + } + echo '   ' . esc_html__( 'Total CBM:', 'siegel-umzugsliste' ) . ' ' . esc_html( $total_cbm ?: '0' ) . '

'; + + // Moving date + $date_str = ( $data['umzug_day'] ?? '' ) . '.' . ( $data['umzug_month'] ?? '' ) . '.' . ( $data['umzug_year'] ?? '' ); + echo '

' . esc_html__( 'Moving Date', 'siegel-umzugsliste' ) . '

'; + echo '

' . esc_html( $date_str ) . '

'; + + // Addresses + echo '

' . esc_html__( 'Addresses', 'siegel-umzugsliste' ) . '

'; + echo ''; + + $address_rows = array( + __( 'Name', 'siegel-umzugsliste' ) => array( 'bName', 'eName' ), + __( 'Street', 'siegel-umzugsliste' ) => array( 'bStrasse', 'eStrasse' ), + __( 'ZIP/City', 'siegel-umzugsliste' ) => array( 'bort', 'eort' ), + __( 'Phone', 'siegel-umzugsliste' ) => array( 'bTelefon', 'eTelefon' ), + ); + + foreach ( $address_rows as $label => $keys ) { + echo ''; + echo ''; + echo ''; + } + + // Info fields with proper label mapping + $info_labels = array( + 'bLift' => __( 'Elevator (Loading)', 'siegel-umzugsliste' ), + 'eLift' => __( 'Elevator (Unloading)', 'siegel-umzugsliste' ), + 'bGeschoss' => __( 'Floor (Loading)', 'siegel-umzugsliste' ), + 'eGeschoss' => __( 'Floor (Unloading)', 'siegel-umzugsliste' ), + 'eE-Mail' => __( 'Email', 'siegel-umzugsliste' ), + 'bTelefax' => __( 'Fax (Loading)', 'siegel-umzugsliste' ), + 'eTelefax' => __( 'Fax (Unloading)', 'siegel-umzugsliste' ), + 'bMobil' => __( 'Mobile (Loading)', 'siegel-umzugsliste' ), + 'eMobil' => __( 'Mobile (Unloading)', 'siegel-umzugsliste' ), + ); + + if ( ! empty( $data['info'] ) && is_array( $data['info'] ) ) { + foreach ( $data['info'] as $key => $value ) { + if ( ! empty( $value ) ) { + $label = isset( $info_labels[ $key ] ) ? $info_labels[ $key ] : $key; + echo ''; + } + } + } + + echo '
' . esc_html__( 'Loading', 'siegel-umzugsliste' ) . '' . esc_html__( 'Unloading', 'siegel-umzugsliste' ) . '
' . esc_html( $label ) . '' . esc_html( $data[ $keys[0] ] ?? '' ) . '' . esc_html( $data[ $keys[1] ] ?? '' ) . '
' . esc_html( $label ) . '' . esc_html( $value ) . '
'; + + // Furniture items + if ( class_exists( 'Umzugsliste_Furniture_Data' ) ) { + $rooms = Umzugsliste_Furniture_Data::get_rooms(); + $has_items = false; + + foreach ( $rooms as $room_key => $room_label ) { + $post_array_name = ucfirst( $room_key ); + if ( 'kueche_esszimmer' === $room_key ) { + $post_array_name = 'Kueche_Esszimmer'; + } + + $room_data = $data[ $post_array_name ] ?? array(); + $room_items = array(); + + foreach ( $room_data as $key => $value ) { + if ( substr( $key, 0, 1 ) === 'v' && ! empty( $value ) && floatval( $value ) > 0 ) { + $item_name = substr( $key, 1 ); + $quantity = $value; + $cbm = $room_data[ 'q' . $item_name ] ?? '0'; + $montage = $room_data[ 'm' . $item_name ] ?? ''; + $room_items[] = array( $item_name, $quantity, $cbm, $montage ); + } + } + + if ( ! empty( $room_items ) ) { + if ( ! $has_items ) { + echo '

' . esc_html__( 'Furniture', 'siegel-umzugsliste' ) . '

'; + echo ''; + $has_items = true; + } + + foreach ( $room_items as $item ) { + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + } + } + } + + if ( $has_items ) { + echo '
' . esc_html__( 'Room', 'siegel-umzugsliste' ) . '' . esc_html__( 'Item', 'siegel-umzugsliste' ) . '' . esc_html__( 'Qty', 'siegel-umzugsliste' ) . 'CBM' . esc_html__( 'Assembly', 'siegel-umzugsliste' ) . '
' . esc_html( $room_label ) . '' . esc_html( $item[0] ) . '' . esc_html( $item[1] ) . '' . esc_html( $item[2] ) . '' . esc_html( $item[3] ?: '-' ) . '
'; + } + } + + // Additional work + if ( ! empty( $data['additional_work'] ) && is_array( $data['additional_work'] ) ) { + echo '

' . esc_html__( 'Additional Work', 'siegel-umzugsliste' ) . '

'; + echo ''; + foreach ( $data['additional_work'] as $section => $fields ) { + if ( is_array( $fields ) ) { + foreach ( $fields as $field_key => $value ) { + if ( ! empty( $value ) ) { + echo ''; + } + } + } + } + echo '
' . esc_html( $section ) . '' . esc_html( $field_key ) . ': ' . esc_html( $value ) . '
'; + } + + // Sonstiges + if ( ! empty( $data['sonstiges'] ) ) { + echo '

' . esc_html__( 'Other', 'siegel-umzugsliste' ) . '

'; + echo '

' . esc_html( $data['sonstiges'] ) . '

'; + } + + echo '
'; + } } diff --git a/includes/class-date-helpers.php b/includes/class-date-helpers.php index 7dbd4d2..80faeb0 100644 --- a/includes/class-date-helpers.php +++ b/includes/class-date-helpers.php @@ -27,7 +27,7 @@ class Umzugsliste_Date_Helpers { $selected = (int) current_time( 'j' ); } - $html = '
'; for ( $i = 1; $i <= 31; $i++ ) { $sel = ( $i === $selected ) ? ' selected' : ''; @@ -50,7 +50,7 @@ class Umzugsliste_Date_Helpers { $selected = (int) current_time( 'n' ); } - $html = '
'; for ( $i = 1; $i <= 12; $i++ ) { $sel = ( $i === $selected ) ? ' selected' : ''; @@ -73,7 +73,7 @@ class Umzugsliste_Date_Helpers { $selected = (int) current_time( 'Y' ); } - $html = '
'; // Show current year plus 15 years (matching legacy) $current_year = (int) current_time( 'Y' ); diff --git a/includes/class-email-generator.php b/includes/class-email-generator.php index 24eabdc..b0e7001 100644 --- a/includes/class-email-generator.php +++ b/includes/class-email-generator.php @@ -27,9 +27,9 @@ class Umzugsliste_Email_Generator { // Moving date $content .= self::generate_date_section( - $data['day'] ?? '', - $data['month'] ?? '', - $data['year'] ?? '' + $data['umzug_day'] ?? '', + $data['umzug_month'] ?? '', + $data['umzug_year'] ?? '' ); // Customer info diff --git a/includes/class-form-handler.php b/includes/class-form-handler.php index b99289c..4844620 100644 --- a/includes/class-form-handler.php +++ b/includes/class-form-handler.php @@ -164,7 +164,7 @@ class Umzugsliste_Form_Handler { } // Validate date - if ( empty( $data['day'] ) || empty( $data['month'] ) || empty( $data['year'] ) ) { + if ( empty( $data['umzug_day'] ) || empty( $data['umzug_month'] ) || empty( $data['umzug_year'] ) ) { $errors[] = __( 'Moving date is missing', 'siegel-umzugsliste' ); } @@ -205,7 +205,7 @@ class Umzugsliste_Form_Handler { $sanitized = array(); // Sanitize simple text fields - $text_fields = array( 'bName', 'eName', 'bStrasse', 'eStrasse', 'bort', 'eort', 'bTelefon', 'eTelefon', 'day', 'month', 'year' ); + $text_fields = array( 'bName', 'eName', 'bStrasse', 'eStrasse', 'bort', 'eort', 'bTelefon', 'eTelefon', 'umzug_day', 'umzug_month', 'umzug_year' ); foreach ( $text_fields as $field ) { $sanitized[ $field ] = isset( $data[ $field ] ) ? sanitize_text_field( $data[ $field ] ) : ''; @@ -269,7 +269,7 @@ class Umzugsliste_Form_Handler { */ private function save_to_cpt( $data ) { $customer_name = $data['bName'] ?? 'Unbekannt'; - $date_string = ( $data['day'] ?? '' ) . '.' . ( $data['month'] ?? '' ) . '.' . ( $data['year'] ?? '' ); + $date_string = ( $data['umzug_day'] ?? '' ) . '.' . ( $data['umzug_month'] ?? '' ) . '.' . ( $data['umzug_year'] ?? '' ); // Calculate total CBM $total_cbm = 0; diff --git a/languages/siegel-umzugsliste-de_DE.mo b/languages/siegel-umzugsliste-de_DE.mo index 405e41adbead703b7b032fc660e0ff2ae6118753..4482dd3bc0c3c71d38773a2eaf3dc33a940ea4a5 100644 GIT binary patch delta 6190 zcmZYC30#zA0>|-(Bf|qR1aEN^L_i=9yvU+dz)I{`EmJE;84-n50dDbP^i1X*MH*Ul}cm&VKlvc*XV>%{a9(KYZ z*bz&yG0wuK#stlM6!iGAzeV+}&Kld=7=BDLAG$9G6R|Jq z{>xDvyB?e4&DaLL7)$$R4h8k}KGcnmS=XX&d=oV@J5UYRT2Emv=Z$%q8t#vpnai*l z4#o3uB(}sc$cT*()!rT0hW5?96nf!u%*H*a8)BJ`3$YEV14B^_c#y%H3gpM!&4(WR zI5xp&Fa|fG8rp*D_;%EF`%u??i9xN+cNElMi+0Y4(@;~Fjk+)&HFbrk>qekPJP9>p zw_*~`MveGUR6|dq?t2cIEc2qR--Z1+KhTc(*A%yE@7$PzdQci_1OreVxfnH)E0G^F zh7UD#o2|bSwMp+sb@)kCN1sJ)wpUTl*>3B1+xoBDGyhtvAE;1|qnKwIk9uHRR72fS z5AKOB9Ech7qu6bqNaGIJ>P^{>sL@q^FFF0pQGBTMcrR#&x1`QOdobM-@Y zWH@R><86HzvOmoX)YLv~zkdpK{|b!8_4a%tvc1e}sE+Nk=U+PpO)NW5JxoE}n1-6N zZm0+5p=P20bzL!P1SR&|gW8N!P$LYWuAhmls+o&vxE#A+4QAjsn639e+2vd?2z6r_ zYD#^mO*jKJ1G7-|b5I>vgqn#p$c8rWqOLoH>Ub^c`V*+@qdGh1ZBa{^fmyU~Mp4jv ze>Z9*>rgjt#dO?`>iKb02NOBb)VD)jmxfxZ-lz@~TZdV%LA_Pip*HIj)MmX4gPO7j zC}?VzU?Y4AHL_Kxk-cHR-;df8R`bq28t|tYfX-ROVk( zHPc>rFZSpB3CzPicnvmV0kiNX)Y{EMZPE>>4%DFb%r4YGK0`hCOVmt#XFZJ?SZr74 z7f{Ep%>Mu?Mp6-(2~>}lpl)1)>iHJzi91kh`3q_Wl2{)#l!}_tT-1F7kyqUmp&Fck z>gaT2(#$=m`&R`i@Ftke*bR4MCjN$c?=z^>n)OE)4o5w}hrGgO0cu9pVGrDg^vyJ( zQUmIN>hM6+42{58bYlz#CsMeW!eorYRj4&zj~c;ys0)wc$|z%wp*psZ_0Xn!8qdeA z*cacxes~IXU61b0`+q5FAfu6eY;M6$`uo3tLL3zvP*d^}>cKluyY>J!!aCFgPh(ST z!YiYOTcP$s3hMhl_Ph|)@v+zp$Dy8IY0sx)yx#wL6f{K-qZ(R^+5?+V9jQTekp zjd(KZ^;w2$cs1(n*l5o`L^b#cY9w{`yczGNW+Dw$pM(0NQ-pfnIJ^KSqdGDj)xr5a znSb?oDHZDJ3-*GSQERpX)sfw(1`eQRtQPg)W2o2hCv;=GUQWZ)QTH!G?S*Bi`<_QF zbr@UV>p==?cqi(Hz4n5`s2jh>3-A|I&ztvl?11_`k%fsk0@cwn)Kd9S4bDJ~bT(?u z7u)*vsE!0TQ_z%dLv>(3YU+;I3!?L!1`<#m>4IA8JWRp?s0N0kI#`MtP!(zbx1+9~ zjcRZncEUx-QU%Q>3h7jQfclO0BWh}s`Z)g{NI~7$8P&mDd!COPaWQHDSK0G2R0n+6 z5~rd%G9SC)LR5RNp!T0ROo5GRlKJ%|3z2t)pkr%@3 zM=e`P-}4ArT`Dp{BS1Q*jh_ z#p$RiUxwOb>rlJ+UHkpF*n#t;OPsya6SaxQq4vy!s1a{P?Tu}y4hQ#A&{`kHXgrF; z@f+0IUsT|%{a{qb#-KJ+0HaXHNm5MOlFLc`(T>8iq}Em(#|5@L*fAJk6ra!AFLJF7 zS#3|QMRh`(Oh+2ICsH!zPQ1mIwKOMeIbanZlNapyKKzH?f33r5GLFvo+dvK9q*Dgk&-bF;dA7Da*(`9HW3}cNBPjJ6ebUl z+elAxjQpM4LA1k9kqgNd@(uZg=tw1BL`rNj97}S@MiN8n4{f&Q_T*Lkki4Vc|94Y( zii{?ICez4avXER#>W@+i)9uM3TuMra{w&uYT`6cY@3Iv&)+MO7E76{JLcIkct-p>b z4v~Ket9YwDf84qaA0t1K-sBacV?A+^-K2=rAAg~sw<(#dBddrGHJ3yZ$X%qqee*Wu zj^svilvI)H$n8YORN^ImQb_(ot|a`PiX2V&oJTe|r;-0PwV?bAdCS%nSS#^Qv=q1>NzA&-!Mo6zazzs8l8R(bq>k3W1ep*AMH!ZXz!@Kw1ohWXs3<=(PP zQ+TFoq_@IWhCXgt(8%TYcmw&Nw=?oXB}v^nxTiI^sYquHuCGeUY=8EVMHN0Z(ct@s zl7__GoD(xTc9_qqJl<15Sk z{&Jt!Rq777T@!uP-qPIgtF3FI!n4{&MaMhe4e~_v01~)Ck9*@gFF@PQjgpDCet{Th2B8J+R$woS106@ z@OW35hsi1RM5d>z#|Te_XQF20oTr?rKled>GrROE_V_1E^7;LLxa;f}=iYXG=5>uq z-r6+YQxRI7S=*%8Q|9sd18#3=XhGK0(CMtwEN1Ty&x_2dE90Dpg~xO+it2c!r`+pt z6|xcB-ZDS)>hUtRiOj6Wn;Tx5-7-4%T6cA2ctfr$I^oP^c8YiQ$cS!AZ{3xFoX9Mn M>Qxio&^tBef6t})_5c6? delta 4031 zcmYM#eQcH09l-I^7FtSM-df6dDW#=dfdajyZ@f+smB^eG2h31NfM|3opn?nX2RC6E zEMs88Gkjslu+znafyO(K00Z4bahV|^Roo`xItI}}97A3dw|&36CmFfi&pFR?o^yV` z-#O3i)iqs9)29aX*b?}6f&at!|I-3{AzbhCfBVz?n!fh!8$v!-VH1wR7F>Wnx*1Dw zEAk01@>PlZumVqF5njgf5Yi#HUkHP_Fc^Db6FR}v=q&6(|8C?H7DkuhAo^+axu73jj9Xhn8n zF}{L5@i3O+5j5iuk)*>JG>|WF0_%r9tU4B_qYo^@23(5<@Cv%XF{EVSeY9fd(TNLq zs5h2k9u7wrszw8!fR3Aij%!D^WIm?(A6D~a#+%U6J&6u{9xdHV$R`})%Z!hs8U7ia z_!D&8d2~yzV;h#0W#_#e9X|*8g!z0K=<+h^Ka|FbIN%9%;VsAf`*W2a|C+tKY*d6wuSO5mB(!38#rq4;=NDrxJ{0@Q(KD1@O~XU-vv}bJG_u3!14qz`97QMU zLeI)+blf@Q6E4JlK2dl^iqXUdqT{R3tsadvcnemuet3Y!C@yS7--5kyKsWkeFT%8R z{m?^GiDo`BULS=9(1tt`+HnZpj|Tih^!ZKbxMyR34>tJzzd>URH!h(8RPwYL+>Smt z7r%-3AQ6WRXkfe1Qtw5_y@qbhF*LyL=(*^5bW1NH$0rm}juPMh3L2KG9xZ7bdT6Gh z8QqLL6Bfq%tI!44pn+~g19}qO%I(pYke`U~8v0he7d;cbf@w=s$ghk8%WxvrVKXkm z*|-I*&{=e=2Jl1fp__sRa2I+;I?x2}M=P@|x(ZEXEw*#utCISUrtv5j ze1Es0d-H1?fxkm1=thDL`CPODHJHNhU@fje6L}sD_+_*rN71v;g&y8N;WRvj1~@ET zmEGG~G=m$_feZ0O4(}}*SnJ5_;kp&w>-pGG?A~6DMEkVIdTY1 zXeGXj9@g{{8lK7@poeY)I?-k{qfT_e-RPe0jrZS){f{t@>zB}suc8a|q%8K!(52L=PBUy|F@))|{Ptd*GjGpS9XhsL|W;~9bg+aWVj;}@o9)mrx6+P5b z(Lmax3($4Gk8P|U*3h_t3wzPbFXI%%bnkB3@sGPMAh3xDly-cn&=i zZ=!F>2xT=0Pe-K%HNQvV9Az^mxEL-GC}us8h=&_Mr+ z26_ouBjna+D>xPn>;|;5GtqVCMHkdle-~WB1uL-}i*P*}VS?V@g>K1ybisGft@s$N z$luTkT|)!uJ2o451sZ4#I=%smu^B6IdYXoZX)$u{!fLc+&tWd^#A4iyMR*|g-$FAx zfd>AU*uR8U>^gcT^2Wut1ncNmqwCBNlB_h0)+JCQdj?8p9i1|4?= zT_~?PYbkntB#yuaEWFl3W^kHaR`)zNEe4;Y@c$RZeDj<uY)>MXC1W;~^81U#2D|#f??TqQ<$&!N$KQyCyuAq?+bsGEFmbGG#3Tax?X9mARSu Rlj?GljZ= 0 && is_page( $form_page_id ) ) { + $use_standalone = true; + } + + // Fallback: check if current page contains the [umzugsliste] shortcode + if ( ! $use_standalone ) { + $post = get_queried_object(); + if ( $post && isset( $post->post_content ) && has_shortcode( $post->post_content, 'umzugsliste' ) ) { + $use_standalone = true; + } + } + + if ( $use_standalone ) { $custom_template = UMZUGSLISTE_PLUGIN_DIR . 'templates/form-page.php'; if ( file_exists( $custom_template ) ) { return $custom_template; @@ -136,9 +153,6 @@ class Umzugsliste { // Initialize shortcode Umzugsliste_Shortcode::get_instance(); - - // Initialize form handler - Umzugsliste_Form_Handler::get_instance(); } }