| 1 |
<?php |
| 2 |
// phpcs:set WordPress.Security.ValidatedSanitizedInput customSanitizingFunctions[] ph_clean |
| 3 |
// ph_clean() recursively sanitizes text; presence, shape and unslashing checks remain separate. |
| 4 |
|
| 5 |
if ( ! defined( 'ABSPATH' ) ) { |
| 6 |
exit; |
| 7 |
} |
| 8 |
$propertyhive_ph_key_date_input = array(); |
| 9 |
foreach ( array( 'description', 'status', 'due_date_time', 'type', 'date_post_id' ) as $propertyhive_ph_input_key ) { |
| 10 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only AJAX controls; the save action separately verifies the nonce and CRM permissions. |
| 11 |
$propertyhive_ph_key_date_input[$propertyhive_ph_input_key] = isset( $_POST[$propertyhive_ph_input_key] ) && is_string( $_POST[$propertyhive_ph_input_key] ) ? sanitize_text_field( wp_unslash( $_POST[$propertyhive_ph_input_key] ) ) : ''; |
| 12 |
} |
| 13 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Read-only AJAX control; sanitize and escape its displayed contents. |
| 14 |
$propertyhive_ph_key_date_input['notes'] = isset( $_POST['notes'] ) && is_string( $_POST['notes'] ) ? sanitize_textarea_field( wp_unslash( $_POST['notes'] ) ) : ''; |
| 15 |
?><td colspan="5"> |
| 16 |
<div class="propertyhive_meta_box"> |
| 17 |
<div class="options_group"> |
| 18 |
<p class="form-field"> |
| 19 |
<label for="date_description">Description</label> |
| 20 |
<input type="text" id="date_description" class="short" value="<?php |
| 21 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 22 |
echo esc_attr( $propertyhive_ph_key_date_input['description'] ); ?>"> |
| 23 |
</p> |
| 24 |
<p class="form-field"> |
| 25 |
<label for="key_date_status">Status</label> |
| 26 |
<?php |
| 27 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 28 |
$output = '<select id="key_date_status" name="key_date_status">'; |
| 29 |
|
| 30 |
foreach ( array( 'pending', 'booked', 'complete', 'on_hold', 'cancelled' ) as $status ) |
| 31 |
{ |
| 32 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound, WordPress.Security.NonceVerification.Missing -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 33 |
$selected_value = strtolower( $propertyhive_ph_key_date_input['status'] ); |
| 34 |
if ( in_array($selected_value, array('overdue', 'upcoming') ) ) |
| 35 |
{ |
| 36 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 37 |
$selected_value = 'pending'; |
| 38 |
} |
| 39 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 40 |
$output .= '<option value="' . esc_attr($status) . '"'; |
| 41 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 42 |
$output .= selected($status, $selected_value, false ); |
| 43 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 44 |
$output .= '>' . esc_html(ucwords(str_replace("_", " ", $status))) . '</option>'; |
| 45 |
} |
| 46 |
|
| 47 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 48 |
$output .= '</select>'; |
| 49 |
|
| 50 |
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Select options are escaped when assembled; selected() emits WordPress's fixed selected attribute. |
| 51 |
echo $output; |
| 52 |
?> |
| 53 |
</p> |
| 54 |
<p class="form-field"> |
| 55 |
<?php |
| 56 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound, WordPress.Security.NonceVerification.Missing -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 57 |
$due_date_time = strtotime( $propertyhive_ph_key_date_input['due_date_time'] ); |
| 58 |
?> |
| 59 |
<label for="date_due_quick_edit">Due Date</label> |
| 60 |
<input type="date" class="small" name="date_due_quick_edit" id="date_due_quick_edit" value="<?php echo esc_attr( $due_date_time !== false ? gmdate( 'Y-m-d', $due_date_time ) : '' ); ?>" placeholder=""> |
| 61 |
|
| 62 |
<select id="date_due_hours_quick_edit" name="date_due_hours_quick_edit" class="select short" style="width:55px">'; |
| 63 |
<?php |
| 64 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 65 |
for ( $i = 0; $i < 23; ++$i ) |
| 66 |
{ |
| 67 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 68 |
$j = str_pad($i, 2, '0', STR_PAD_LEFT); |
| 69 |
echo '<option value="' . esc_attr($j) . '"'; |
| 70 |
if ( gmdate('H', $due_date_time) == $j ) { echo ' selected'; } |
| 71 |
echo '>' . esc_html($j) . '</option>'; |
| 72 |
} |
| 73 |
?> |
| 74 |
</select> |
| 75 |
: |
| 76 |
<select id="date_due_minutes_quick_edit" name="date_due_minutes_quick_edit" class="select short" style="width:55px"> |
| 77 |
<?php |
| 78 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 79 |
for ( $i = 0; $i < 60; $i+=5 ) |
| 80 |
{ |
| 81 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 82 |
$j = str_pad($i, 2, '0', STR_PAD_LEFT); |
| 83 |
echo '<option value="' . esc_attr($j) . '"'; |
| 84 |
if ( gmdate('i', $due_date_time) == $j ) { echo ' selected'; } |
| 85 |
echo '>' . esc_html($j) . '</option>'; |
| 86 |
} |
| 87 |
?> |
| 88 |
</select> |
| 89 |
</p> |
| 90 |
<p class="form-field"> |
| 91 |
<label for="date_type"><?php echo esc_html(__('Key Date Type', 'propertyhive')); ?></label> |
| 92 |
<select id="date_type" name="date_type" class="select short"> |
| 93 |
<?php |
| 94 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 95 |
$key_date_type_terms = get_terms( array_merge( wp_parse_args( array( |
| 96 |
'hide_empty' => false, |
| 97 |
'parent' => 0 |
| 98 |
) ), array( 'taxonomy' => 'management_key_date_type' ) ) ); |
| 99 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 100 |
$recurrence_rules = get_option( 'propertyhive_key_date_type', array() ); |
| 101 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 102 |
$recurrence_rules = is_array( $recurrence_rules ) ? $recurrence_rules : array(); |
| 103 |
|
| 104 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 105 |
$parent_post_type = get_post_type( $post_id ); |
| 106 |
if ( !empty( $key_date_type_terms ) && !is_wp_error( $key_date_type_terms ) ) |
| 107 |
{ |
| 108 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 109 |
foreach ($key_date_type_terms as $key_date_type_term) |
| 110 |
{ |
| 111 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 112 |
$recurrence_type = isset($recurrence_rules[$key_date_type_term->term_id]) ? $recurrence_rules[$key_date_type_term->term_id]['recurrence_type'] : ''; |
| 113 |
if ( $parent_post_type == 'tenancy' || ( $parent_post_type == 'property' && $recurrence_type == 'property_management' ) ) |
| 114 |
{ |
| 115 |
echo '<option value="' . esc_attr($key_date_type_term->term_id) . '"'; |
| 116 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 117 |
if ( $propertyhive_ph_key_date_input['type'] !== '' && $propertyhive_ph_key_date_input['type'] == $key_date_type_term->term_id ) { echo ' selected'; } |
| 118 |
echo '>' . esc_html($key_date_type_term->name) . '</option>'; |
| 119 |
} |
| 120 |
} |
| 121 |
} |
| 122 |
?> |
| 123 |
</select> |
| 124 |
</p> |
| 125 |
<p class="form-field"> |
| 126 |
<label for="date_notes_quick_edit">Notes</label> |
| 127 |
<textarea id="date_notes_quick_edit" class="short"><?php |
| 128 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 129 |
echo esc_textarea( $propertyhive_ph_key_date_input['notes'] !== '-' ? $propertyhive_ph_key_date_input['notes'] : '' ); ?></textarea> |
| 130 |
</p> |
| 131 |
<?php |
| 132 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 133 |
if ( isset($recurrence_rules[$propertyhive_ph_key_date_input['type']]) && isset( $recurrence_rules[$propertyhive_ph_key_date_input['type']]['recurrence_rule'] ) ) |
| 134 |
{ |
| 135 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 136 |
$recurrence = array(); |
| 137 |
|
| 138 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound, WordPress.Security.NonceVerification.Missing -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 139 |
foreach (explode(';', $recurrence_rules[$propertyhive_ph_key_date_input['type']]['recurrence_rule']) as $key_value_pair){ |
| 140 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 141 |
list($key, $value) = explode('=', $key_value_pair); |
| 142 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 143 |
$recurrence[strtolower($key)] = $value; |
| 144 |
} |
| 145 |
|
| 146 |
if ( isset($recurrence['freq']) && $recurrence['freq'] != 'ONCE' ) |
| 147 |
{ |
| 148 |
?> |
| 149 |
<p id="next_key_date_checkbox" class="form-field hidden"> |
| 150 |
<label for="book_next_key_date"><?php |
| 151 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 152 |
echo /* translators: %s: Key date description. */ esc_html( sprintf( __( 'Book Next %s?', 'propertyhive' ), $propertyhive_ph_key_date_input['description'] !== '' ? $propertyhive_ph_key_date_input['description'] : __( 'Key Date', 'propertyhive' ) ) ); ?></label> |
| 153 |
<input type="checkbox" id="book_next_key_date" > |
| 154 |
</p> |
| 155 |
<?php |
| 156 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 157 |
$next_key_date = ''; |
| 158 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 159 |
$next_key_date_hours = '00'; |
| 160 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 161 |
$next_key_date_minutes = '00'; |
| 162 |
|
| 163 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 164 |
$interval = isset($recurrence['interval']) ? $recurrence['interval'] : '1'; |
| 165 |
switch( $recurrence['freq'] ) |
| 166 |
{ |
| 167 |
case 'DAILY': |
| 168 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 169 |
$frequency = 'day'; |
| 170 |
break; |
| 171 |
case 'WEEKLY': |
| 172 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 173 |
$frequency = 'week'; |
| 174 |
break; |
| 175 |
case 'MONTHLY': |
| 176 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 177 |
$frequency = 'month'; |
| 178 |
break; |
| 179 |
case 'YEARLY': |
| 180 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 181 |
$frequency = 'year'; |
| 182 |
break; |
| 183 |
} |
| 184 |
|
| 185 |
if ( isset($frequency) ) |
| 186 |
{ |
| 187 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 188 |
$next_key_timestamp = strtotime('+' . $interval . ' ' . $frequency, $due_date_time); |
| 189 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 190 |
$next_key_date = gmdate('Y-m-d', $next_key_timestamp); |
| 191 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 192 |
$next_key_date_hours = gmdate('H', $next_key_timestamp); |
| 193 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 194 |
$next_key_date_minutes = gmdate('i', $next_key_timestamp); |
| 195 |
} |
| 196 |
?> |
| 197 |
<p id="next_key_date_field" class="form-field hidden"> |
| 198 |
<label for="next_key_date"> </label> |
| 199 |
<input type="date" class="small" name="next_key_date" id="next_key_date" value="<?php echo esc_attr($next_key_date); ?>" placeholder=""> |
| 200 |
|
| 201 |
<select id="next_key_date_hours" name="next_key_date_hours" class="select short" style="width:55px">'; |
| 202 |
<?php |
| 203 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 204 |
for ( $i = 0; $i < 23; ++$i ) |
| 205 |
{ |
| 206 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 207 |
$j = str_pad($i, 2, '0', STR_PAD_LEFT); |
| 208 |
echo '<option value="' . esc_attr($j) . '"'; |
| 209 |
if ( $next_key_date_hours == $j ) { echo ' selected'; } |
| 210 |
echo '>' . esc_html($j) . '</option>'; |
| 211 |
} |
| 212 |
?> |
| 213 |
</select> |
| 214 |
: |
| 215 |
<select id="next_key_date_minutes" name="next_key_date_minutes" class="select short" style="width:55px"> |
| 216 |
<?php |
| 217 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 218 |
for ( $i = 0; $i < 60; $i+=5 ) |
| 219 |
{ |
| 220 |
// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound -- Template-local variable in an admin view; PHPCS analyzes the view file standalone even though WordPress includes it inside a method/function scope. |
| 221 |
$j = str_pad($i, 2, '0', STR_PAD_LEFT); |
| 222 |
echo '<option value="' . esc_attr($j) . '"'; |
| 223 |
if ( $next_key_date_minutes == $j ) { echo ' selected'; } |
| 224 |
echo '>' . esc_html($j) . '</option>'; |
| 225 |
} |
| 226 |
?> |
| 227 |
</select> |
| 228 |
</p> |
| 229 |
<?php |
| 230 |
} |
| 231 |
} |
| 232 |
?> |
| 233 |
<button type="button" id="<?php |
| 234 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 235 |
echo esc_attr( (int) $propertyhive_ph_key_date_input['date_post_id'] ); ?>" class="button button-primary save-quick-edit">Update</button> |
| 236 |
<button type="button" id="<?php |
| 237 |
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- This authorized AJAX template only renders controls; key-date writes separately verify their nonce and CRM capability. |
| 238 |
echo esc_attr( (int) $propertyhive_ph_key_date_input['date_post_id'] ); ?>" class="button cancel-quick-edit">Cancel</button> |
| 239 |
</div> |
| 240 |
</div> |
| 241 |
</td> |
| 242 |
|