Changeset 3369834
- Timestamp:
- 09/29/2025 03:16:26 PM (5 months ago)
- Location:
- mon-laboratoire/trunk
- Files:
-
- 12 edited
-
Admin/Forms/class-forms-view.php (modified) (38 diffs)
-
Admin/Forms/class-generic-forms-view.php (modified) (7 diffs)
-
Admin/Forms/class-options-forms-view.php (modified) (51 diffs)
-
Admin/Forms/class-wp-post-forms-view.php (modified) (18 diffs)
-
Admin/class-admin-menu.php (modified) (2 diffs)
-
Admin/class-admin-page.php (modified) (1 diff)
-
Admin/class-admin-table-view.php (modified) (2 diffs)
-
Admin/class-wordpress-page.php (modified) (1 diff)
-
Lib/class-privacy.php (modified) (9 diffs)
-
mon-laboratoire.php (modified) (2 diffs)
-
readme.txt (modified) (3 diffs)
-
todo.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
mon-laboratoire/trunk/Admin/Forms/class-forms-view.php
r3361909 r3369834 9 9 * 10 10 * This class provides methods to create various form elements like text fields, 11 * selects, checkboxes, radio buttons11 * selects, checkboxes, and radio buttons. 12 12 * 13 13 * Methods : … … 39 39 * 40 40 * @package MonLabo\Admin\Forms 41 */41 */ 42 42 class Forms_View extends Generic_Forms_View { 43 43 … … 45 45 * Generates HTML code for a generic form field of specified type. 46 46 * 47 * @param string $type_of_fieldThe unique type/name identifier for the field.48 * @param bool $is_mandatoryWhether the field is required.49 * @param string $legendLabel text displayed before the field.50 * @param string $descriptionHelp text displayed after the field.51 * @param mixed $initial_valueInitial field value (string|int|null|array).52 * @param string $css_idCSS identifier for the field.53 * @return string Generated HTML for the form field.47 * @param string $type_of_field The unique type/name identifier for the field. 48 * @param bool $is_mandatory Whether the field is required. 49 * @param string $legend Label text displayed before the field. 50 * @param string $description Help text displayed after the field. 51 * @param mixed $initial_value Initial field value (string|int|null|array). 52 * @param string $css_id CSS identifier for the field. 53 * @return string Generated HTML for the form field. 54 54 */ 55 55 public function field( … … 61 61 string $css_id = '' 62 62 ): string { 63 if ( is_null( $initial_value ) ) { $initial_value = ''; } 63 if ( is_null( $initial_value ) ) { 64 $initial_value = ''; 65 } 66 $field_name = 'submit_' . $type_of_field; 67 if( is_array( $initial_value ) ) { 68 switch ( $type_of_field ) { 69 case 'wp_post_ids': 70 $multipost_forms_view = new Wp_Post_Forms_View(); 71 return $multipost_forms_view->multi_post_addr_field( $is_mandatory, $legend, $field_name, $description, $initial_value, $css_id ); 72 case 'person_wp_post_ids': 73 $multipost_forms_view = new Wp_Post_Forms_View(); 74 return $multipost_forms_view->person_multi_post_addr_field( $is_mandatory, $legend, 'submit_wp_post_ids', $description, $initial_value, $css_id ); 75 default: 76 return ''; //ERROR 77 } 78 } 79 80 $initial_value = strval( $initial_value ); 64 81 switch ( $type_of_field ) { 65 82 case 'descartes_publi_author_id': 66 return $this->_number_field( $is_mandatory, $legend, 'submit_' . $type_of_field, $description, strval( $initial_value ), $css_id ); 67 //case 'alternate_image': 83 return $this->_number_field( $is_mandatory, $legend, $field_name, $description, $initial_value, $css_id ); 68 84 case 'external_url': 69 return $this->_url_field( $is_mandatory, $legend, 'submit_' . $type_of_field, $description, $initial_value, $css_id ); 70 /* 71 //Non utilisé 72 case 'title': 73 return generate_text_form_small( $is_mandatory, $legend, 'submit_' . $type_of_field, $description, $initial_value, $css_id );*/ 85 return $this->_url_field( $is_mandatory, $legend, $field_name, $description, $initial_value, $css_id ); 74 86 case 'color': 75 return $this->_color_field( $is_mandatory, $legend, 'submit_' . $type_of_field, $description, $initial_value, $css_id );87 return $this->_color_field( $is_mandatory, $legend, $field_name, $description, $initial_value, $css_id ); 76 88 case 'logo': 77 return $this->_square_image_selector( 'submit_' . $type_of_field, $description, $initial_value );89 return $this->_square_image_selector( $field_name, $description, $initial_value ); 78 90 case 'image': 79 return $this->_person_image_selector( 'submit_' . $type_of_field, $description, $initial_value );91 return $this->_person_image_selector( $field_name, $description, $initial_value ); 80 92 case 'adresse': 81 93 case 'external_mentors': … … 84 96 case 'contact': 85 97 case 'contact_alt': 86 return $this->_textarea( $is_mandatory, 'submit_' . $type_of_field, $description, $initial_value, $css_id );98 return $this->_textarea( $is_mandatory, $field_name, $description, $initial_value, $css_id ); 87 99 case 'explicit_disabled': 88 100 return $this->_explicit_disabled_field( $legend, $description ); 89 case 'wp_post_ids':90 $multipost_forms_view = new Wp_Post_Forms_View();91 return $multipost_forms_view->multi_post_addr_field( $is_mandatory, $legend, 'submit_' . $type_of_field, $description, $initial_value, $css_id );92 case 'person_wp_post_ids':93 $multipost_forms_view = new Wp_Post_Forms_View();94 return $multipost_forms_view->person_multi_post_addr_field( $is_mandatory, $legend, 'submit_wp_post_ids', $description, $initial_value, $css_id );95 101 default: 96 return $this->_large_text_field( $is_mandatory, $legend, 'submit_' . $type_of_field, $description, $initial_value, $css_id );102 return $this->_large_text_field( $is_mandatory, $legend, $field_name, $description, $initial_value, $css_id ); 97 103 } 98 104 } … … 100 106 /** 101 107 * Begins a form with proper nonce field. 102 * @param string $form_id ID of the form 103 * @return string HTML code 104 */ 105 public function begin_form( string $form_id ) : string { 108 * 109 * @param string $form_id ID of the form. 110 * @return string HTML code for form opening tag. 111 */ 112 public function begin_form( string $form_id ): string { 106 113 $tab = sanitize_key( $_GET['tab'] ?? 'tab_adv' ); 107 114 $url = add_query_arg( … … 122 129 * @return string HTML code for hidden input fields. 123 130 */ 124 public function silent_transmit_ids( string $form_id, array $table_of_ids ) : string {131 public function silent_transmit_ids( string $form_id, array $table_of_ids ): string { 125 132 if ( empty( $table_of_ids ) ) { 126 133 return ''; 127 134 } 128 // Be sure to get a list of int135 // Be sure to get a list of int. 129 136 $table_to_encode = array_values( array_map( 'intval', $table_of_ids ) ); 130 // Transmit silently this list137 // Transmit silently this list. 131 138 return $this->hidden_field( 132 139 esc_attr( $form_id ) . '_submit_ids', … … 137 144 /** 138 145 * Silently transmits text through a hidden form field. 139 * @param string $form_id ID of the form 140 * @param string $text Text to transmit. 146 * 147 * @param string $form_id ID of the form. 148 * @param string $text Text to transmit. 141 149 * @return string HTML for hidden input field. 142 150 */ 143 public function silent_transmit_text( string $form_id, string $text ) : string {151 public function silent_transmit_text( string $form_id, string $text ): string { 144 152 return $this->hidden_field( $form_id . '_submit_text', $text ); 145 153 } … … 147 155 /** 148 156 * Retrieves silently transmitted IDs from POST data. 149 * @param string $post_index ID of the form 150 * @param int[] $destination structure received from POST 157 * 158 * @param string $post_index ID of the form. 159 * @param int[] $destination Reference to destination array. 151 160 * @return void 152 161 */ … … 169 178 * @return string HTML code 170 179 */ 171 public function silent_transmit_array_of_struct( string $form_id, array $table_of_struct ) : string {180 public function silent_transmit_array_of_struct( string $form_id, array $table_of_struct ): string { 172 181 if ( empty( $table_of_struct ) ) { 173 182 return ''; … … 201 210 /** 202 211 * Generates end of form with submit button. 203 * @param string $form_id ID of the form 204 * @param string $submit_button_text Text inside the submit button 205 * @param string $dashicon [OPTIONAL] Code of dashicon to display (https://developer.wordpress.org/resource/dashicons/#plugins-checked) 206 * @param string $type [OPTIONAL] Type of button as Bootstrap defines (https://getbootstrap.com/docs/4.0/components/buttons/) 207 * @param bool $disabled [OPTIONAL] Does the button is disabled ? 208 * @return string HTML code 209 */ 210 public function end_form( string $form_id, string $submit_button_text, $dashicon = '', $type = 'primary', $disabled = false ) : string { 212 * 213 * @param string $form_id ID of the form. 214 * @param string $submit_button_text Text inside the submit button. 215 * @param string $dashicon Optional. Code of dashicon to display. 216 * @param string $type Optional. Type of button (primary, secondary, etc.). Default 'primary'. 217 * @param bool $disabled Optional. Whether the button is disabled. Default false. 218 * @return string HTML code for form closing. 219 */ 220 public function end_form( string $form_id, string $submit_button_text, $dashicon = '', $type = 'primary', $disabled = false ): string { 211 221 $output = wp_nonce_field( $form_id . '_form', $form_id . '_form_wpnonce', true, false ); 212 222 $output .= $this->submit_button( $submit_button_text, 'submit_' . $form_id, '', $dashicon, $type, '', '', $disabled ); … … 216 226 217 227 /** 218 * Generate an HTML code for a generic simple choice drop-down list form field 219 * @param string $name see _select_generic 220 * @param array<string|int,string>|array<string|int,array<string,string>> $values see _select_generic 221 * @param bool $is_mandatory see _select_generic 222 * @param string $legend see _select_generic 223 * @param string $description see _select_generic 224 * @param string|string[]|null $initial_value see _select_generic 225 * @param string $onchange see _select_generic 226 * @param string $prefix prefix to add to name 227 * @return string HTML code of the drop-down list form field 228 * Generate a single-choice select dropdown field. 229 * 230 * @param string $name Name of the dropdown list. 231 * @param array<string|int,string>|array<string|int,array<string,string>> $values Array of values for each option. 232 * @param bool $is_mandatory Whether selection is required. 233 * @param string $legend Label text before the field. 234 * @param string $description Help text after the field. 235 * @param string|string[]|null $initial_value Pre-selected value(s). 236 * @param string $onchange JavaScript onchange handler. 237 * @param string $prefix Prefix to add to name. Default 'submit_'. 238 * @return string HTML code for the dropdown field. 228 239 */ 229 240 public function select( … … 241 252 242 253 /** 243 * Generates multi-select dropdown field. 244 * @param string $name see _select_generic 245 * @param array<string|int,string>|array<string|int,array<string,string>> $values see _select_generic 246 * @param bool $is_mandatory see _select_generic 247 * @param string $legend see _select_generic 248 * @param string $description see _select_generic 249 * @param string|string[]|int|int[]|null $initial_value see _select_generic 250 * @param string $onchange see _select_generic 251 * @param string $prefix prefix to add to name 252 * @return string HTML code of the drop-down list form field 254 * Generate a multiple-choice select dropdown field. 255 * 256 * @param string $name Name of the dropdown list. 257 * @param array<string|int,string>|array<string|int,array<string,string>> $values Array of values for each option. 258 * @param bool $is_mandatory Whether selection is required. 259 * @param string $legend Label text before the field. 260 * @param string $description Help text after the field. 261 * @param string|string[]|int|int[]|null $initial_value Pre-selected value(s). 262 * @param string $onchange JavaScript onchange handler. 263 * @param string $prefix Prefix to add to name. Default 'submit_'. 264 * @return string HTML code for the dropdown field. 253 265 */ 254 266 public function select_multiple( … … 266 278 267 279 /** 268 * Generates radio button group. 269 * @param string $name name of the form field 270 * @param string[] $values array of value of each radio button 271 * Thus each item of the array is 'value' => 'legend' 272 * @param bool $is_mandatory if true, select a button is mandatory. 273 * @param string $legend text that is displayed just before the field 274 * @param string $description text that is displayed after the field 275 * @param string|null $initial_value Pre-select buttons 276 * @param string $onchange JavaScript code to execute when changing the 277 * radio buttons states 278 * @return string HTML code of the radio buttons form field 280 * Generate radio button group. 281 * 282 * @param string $name Name of the form field. 283 * @param string[] $values Array of values for each radio button. 284 * @param bool $is_mandatory Whether selection is required. 285 * @param string $legend Label text before the field. 286 * @param string $description Help text after the field. 287 * @param string|null $initial_value Pre-selected value. 288 * @param string $onchange JavaScript onchange handler. 289 * @return string HTML code for radio button group. 279 290 */ 280 291 public function radio_buttons( … … 297 308 $is_mandatory ? ' required="required"' : '', 298 309 $onchange ? ' onchange="' . esc_js( $onchange ) . '"' : '', 299 strlen( $initial_value ) ? checked( $initial_value, $value, false ) : '',310 strlen( $initial_value ) ? checked( $initial_value, $value, false ) : '', 300 311 esc_html( $value ) 301 312 ); … … 306 317 307 318 /** 308 * Generate an HTML code for checkboxes form field 309 * @param string $name name of the form field 310 * @param string[] $values array of value of each checkbox 311 * Thus each item of the array is 'value' => 'legend' 312 * @param bool $is_mandatory if true, check a box is mandatory. 313 * @param string $legend text that is displayed just before the field 314 * @param string $description text that is displayed after the field 315 * @param string[]|null $initial_value Pre-select box 316 * @param string $onchange JavaScript code to execute when changing the checkboxes 317 * state 318 * @return string HTML code of the checkboxes form field 319 * Generate checkboxes group. 320 * 321 * @param string $name Name of the form field. 322 * @param string[] $values Array of values for each checkbox. 323 * @param bool $is_mandatory Whether selection is required. 324 * @param string $legend Label text before the field. 325 * @param string $description Help text after the field. 326 * @param string[]|null $initial_value Pre-selected values. 327 * @param string $onchange JavaScript onchange handler. 328 * @return string HTML code for checkboxes group. 319 329 */ 320 330 public function checkboxes( … … 345 355 346 356 /** 347 * Generate an HTML code for a submitting button of a form 348 * @param string $text id of the person 349 * @param string $css_id CSS ID of the buttonGENERATION D’ELEMENTS 350 * @param string $onclick Javascrit code to launch when button is clicked on 351 * @param string $dashicon Code of dashicon to display (https://developer.wordpress.org/resource/dashicons/#plugins-checked) 352 * @param string $type Type of button as Bootstrap defines (https://getbootstrap.com/docs/4.0/components/buttons/) 353 * @param string $name property 'name' of the button 354 * @param string $class class of the button 355 * @param bool $disabled do the button is disabled ? 356 * @return string HTML code 357 * Generate submit button. 358 * 359 * @param string $text Button text. 360 * @param string $css_id CSS ID for the button. 361 * @param string $onclick JavaScript onclick handler. 362 * @param string $dashicon Dashicon code. 363 * @param string $type Button type (primary, secondary, etc.). Default 'primary'. 364 * @param string $name Name attribute of the button. 365 * @param string $class Additional CSS classes. 366 * @param bool $disabled Whether button is disabled. Default false. 367 * @return string HTML code for submit button. 357 368 */ 358 369 public function submit_button( … … 367 378 ): string { 368 379 $button_attrs = array( 369 'onclick' => $onclick, // already cleaned by esc_js()370 'name' => esc_attr( $name ),371 'type' => 'submit',380 'onclick' => $onclick, // Already cleaned by esc_js(). 381 'name' => esc_attr( $name ), 382 'type' => 'submit', 372 383 'class' => esc_attr( 'btn btn-' . $type . ( $class ? ' ' . $class : '' ) ), 373 'id' => esc_attr( $css_id ),374 ); 375 // Remove empty attributes 384 'id' => esc_attr( $css_id ), 385 ); 386 // Remove empty attributes. 376 387 $button_attrs = array_filter( $button_attrs ); 388 377 389 if ( $disabled ) { 378 390 $button_attrs['disabled'] = 'disabled'; … … 382 394 $attrs_html .= sprintf( ' %s="%s"', $key, $value ); 383 395 } 384 $button_content = $dashicon ? $this->_html->dashicon( $dashicon ) . ' ' : '';396 $button_content = $dashicon ? $this->_html->dashicon( $dashicon ) . ' ' : ''; 385 397 $button_content .= wp_kses_post( $text ); 386 398 return sprintf( '<button%s>%s</button>', $attrs_html, $button_content ); … … 388 400 389 401 /** 390 * Generate an HTML code for a hidden field 391 * @param string $name name of the form field 392 * @param string $value value 393 * @param string $id id 394 * @return string HTML code of form field 395 */ 396 public function hidden_field( string $name, string $value, string $id = '' ): string { 402 * Generate hidden field. 403 * 404 * @param string $name Name of the field. 405 * @param string $value Value of the field. 406 * @param string $id ID of the field. Default empty. 407 * @return string HTML code for hidden field. 408 */ 409 public function hidden_field( string $name, string $value, string $id = '' ): string { 397 410 return sprintf( 398 411 '<input type="hidden" name="%1$s"%3$s value="%2$s" />', 399 412 esc_attr( $name ), 400 413 esc_attr( $value ), 401 empty( $id ) ? '' : ' id="' . $id. '"'414 empty( $id ) ? '' : ' id="' . esc_attr( $id ) . '"' 402 415 ); 403 416 } … … 408 421 409 422 /** 410 * Generates generic select/multi-select field. 411 * @param string $name name of the drop-down list 412 * @param array<string|int,string>|array<string|int,array<string,string>> $values array of value of each line of the list 423 * Generate generic select/multi-select field. 424 * 425 * @param string $name Name of the dropdown list. 426 * @param array<string|int,string>|array<string|int,array<string,string>> $values Array of values for each option. 413 427 * Items can be simple array of values or array of array of values for 414 428 * grouping items (<optgroup>). Thus each item can be either: … … 419 433 * .... 420 434 * ] 421 * @param bool $is_mandatory if true, select a value is mandatory. 422 * @param string $legend text that is displayed just before the field 423 * @param string $description text that is displayed after the field 424 * @param bool $select_multiple if true, this is a multiple-select list. 425 * if false, user can only select one value. 426 * @param string|string[]|int|int[]|null $initial_value Pre-select items of the list 435 * @param bool $is_mandatory Whether selection is required. 436 * @param string $legend Label text before the field. 437 * @param string $description Help text after the field. 438 * @param bool $select_multiple Whether multiple selection is allowed. 439 * @param string|string[]|int|int[]|null $initial_value Pre-selected value(s). 427 440 * - Single choice drop-down list: the item to pre-select 428 441 * - Multiple choice drop-down list : array of items to pre-select 429 * @param string $onchange JavaScript code to execute when changing the selection 430 * of the drop-down list. 431 * @param string $prefix prefix to add to name 432 * @return string HTML code of the drop-down list form field 442 * @param string $onchange JavaScript onchange handler. 443 * @param string $prefix Prefix to add to name. 444 * @return string HTML code for select field. 433 445 * @access private 434 446 * @SuppressWarnings(PHPMD.ElseExpression) … … 450 462 $select_attrs = array( 451 463 'multiple' => $select_multiple ? 'multiple' : null, 452 'class' => 'form-control',453 'name' => esc_attr( $prefix . $name . ( $select_multiple ? '[]' : '' ) ),454 'id' => esc_attr( $prefix . $name ),464 'class' => 'form-control', 465 'name' => esc_attr( $prefix . $name . ( $select_multiple ? '[]' : '' ) ), 466 'id' => esc_attr( $prefix . $name ), 455 467 'required' => $is_mandatory ? 'required' : null, 456 'onchange' => $onchange ?: null, // already escaped468 'onchange' => $onchange ?: null, // Already escaped. 457 469 ); 458 470 // Remove null attributes 459 471 $select_attrs = array_filter( $select_attrs ); 472 460 473 $attrs_html = ''; 461 474 foreach ( $select_attrs as $key => $value ) { … … 494 507 495 508 /** 496 * Check sif an option should be selected.509 * Check if an option should be selected. 497 510 * 498 511 * @param string|int $key Option key to check. … … 502 515 * @access private 503 516 */ 504 private function _is_option_selected( $key, $initial_value, $select_multiple ){517 private function _is_option_selected( $key, $initial_value, bool $select_multiple ): bool { 505 518 if ( $select_multiple ) { 506 519 return is_array( $initial_value ) && in_array( $key, $initial_value, true ); … … 510 523 511 524 /** 512 * Generate an HTML code for a disabled form field 513 * @param string $legend text that is displayed just before the field 514 * @param string $description text that is displayed after the field 515 * @return string HTML code of form field 516 * @access private 517 */ 518 private function _explicit_disabled_field( 519 string $legend, 520 string $description 521 ): string { 525 * Generate disabled field display. 526 * 527 * @param string $legend Label text. 528 * @param string $description Help text. 529 * @return string HTML code for disabled field. 530 * @access private 531 */ 532 private function _explicit_disabled_field( string $legend, string $description ): string { 522 533 return sprintf( 523 '<div class="input-group"><div class="input-group-addon"></div><label>%1$s</label> ',534 '<div class="input-group"><div class="input-group-addon"></div><label>%1$s</label>%2$s</div>', 524 535 esc_html( $legend ), 525 ) . $this->description( $description ) . '</div>'; 526 } 527 528 /** 529 * Generates textarea form field. 530 * @param bool $is_mandatory if true, fill this area is mandatory. 531 * @param string $name name of the form field 532 * @param string $description text that is displayed after the field 533 * @param string $initial_value text area initial value 534 * @param string $css_id CSS id for the input-group tag. 535 * @return string HTML code of the text area form field 536 $this->description( $description ) 537 ); 538 } 539 540 /** 541 * Generate textarea field. 542 * 543 * @param bool $is_mandatory Whether field is required. 544 * @param string $name Name of the field. 545 * @param string $description Help text. 546 * @param string $initial_value Initial value. 547 * @param string $css_id CSS ID for the field. 548 * @return string HTML code for textarea. 536 549 * @access private 537 550 */ … … 562 575 563 576 /** 564 * Generate an HTML code for an URL input form field 565 * @param bool $is_mandatory if true, fill this field is mandatory. 566 * @param string $legend text that is displayed just before the field 567 * @param string $name name of the form field 568 * @param string $description text that is displayed after the field 569 * @param string $initial_value initial value 570 * @param string $css_id CSS id for the <input> tag. 571 * @return string HTML code of form field 572 * @access private 573 */ 577 * Generate URL input field. 578 * 579 * @param bool $is_mandatory Whether field is required. 580 * @param string $legend Label text. 581 * @param string $name Name of the field. 582 * @param string $description Help text. 583 * @param string $initial_value Initial value. 584 * @param string $css_id CSS ID for the field. 585 * @return string HTML code for URL field. 586 * @access private 587 */ 574 588 private function _url_field( 575 589 bool $is_mandatory, … … 585 599 586 600 /** 587 * Generate an HTML code for a number input form field 588 * @param bool $is_mandatory if true, fill this field is mandatory. 589 * @param string $legend text that is displayed just before the field 590 * @param string $name name of the form field 591 * @param string $description text that is displayed after the field 592 * @param string $initial_value initial value 593 * @param string $css_id CSS id for the <input> tag. 594 * @return string HTML code of form field 595 * @access private 596 */ 601 * Generate number input field. 602 * 603 * @param bool $is_mandatory Whether field is required. 604 * @param string $legend Label text. 605 * @param string $name Name of the field. 606 * @param string $description Help text. 607 * @param string $initial_value Initial value. 608 * @param string $css_id CSS ID for the field. 609 * @return string HTML code for number field. 610 * @access private 611 */ 597 612 private function _number_field( 598 613 bool $is_mandatory, … … 603 618 string $css_id = '' 604 619 ): string { 605 return $this->_input_field( $is_mandatory, $legend, 'number', $name, $description, 'input-group-normal nopadding-input', $css_id,620 return $this->_input_field( $is_mandatory, $legend, 'number', $name, $description, 'input-group-normal nopadding-input', $css_id, 606 621 $initial_value ); 607 622 } 608 623 609 624 /** 610 * Generate an HTML code for a color input form field 611 * @param bool $is_mandatory if true, fill this field is mandatory. 612 * @param string $legend text that is displayed just before the field 613 * @param string $name name of the form field 614 * @param string $description text that is displayed after the field 615 * @param string $initial_value initial value 616 * @param string $css_id CSS id for the <input> tag. 617 * @return string HTML code of form field 618 * @access private 619 */ 625 * Generate color input field. 626 * 627 * @param bool $is_mandatory Whether field is required. 628 * @param string $legend Label text. 629 * @param string $name Name of the field. 630 * @param string $description Help text. 631 * @param string $initial_value Initial value. 632 * @param string $css_id CSS ID for the field. 633 * @return string HTML code for color field. 634 * @access private 635 */ 620 636 private function _color_field( 621 637 bool $is_mandatory, … … 626 642 string $css_id = '' 627 643 ): string { 628 return $this->_input_field( $is_mandatory, $legend, 'text', $name, $description, 'input-group-normal nopadding-input', $css_id, 629 $initial_value, 'my-color-field', 'data-default-color="#effeff"' ); 630 } 631 632 /** 633 * Generate an HTML code for the choice of a square image 634 * @param string $name name of the form 635 * @param string $description comment displayed just above the form 636 * @param string $initial_value Initial value of the form 637 * @return string HTML code 644 return $this->_input_field( 645 $is_mandatory, 646 $legend, 647 'text', 648 $name, 649 $description, 650 'input-group-normal nopadding-input', 651 $css_id, 652 $initial_value, 653 'my-color-field', 654 'data-default-color="#effeff"' 655 ); 656 } 657 658 /** 659 * Generate square image selector. 660 * 661 * @param string $name Name of the field. 662 * @param string $description Help text. 663 * @param string $initial_value Initial value. 664 * @return string HTML code for image selector. 638 665 * @access private 639 666 */ … … 648 675 wp_kses_post( $description ) 649 676 ); 650 // "None" button 677 // "None" button. 651 678 $output .= sprintf( 652 679 '<input id="%1$s_no_logo_button" class="button" value="%2$s" onclick="MonLabo.selectNoPicture(\'%1$s-image-preview\', \'%1$s\');" type="button" />', … … 654 681 _x( 'None', 'logo', 'mon-laboratoire' ) 655 682 ); 656 // Media selection button 683 // Media selection button. 657 684 $output .= sprintf( 658 685 ' <input id="%1$s-upload-image-button" type="button" class="button" value="%2$s" onclick="MonLabo.imageMediaMenu(\'%3$s\', \'%4$s\', \'%1$s-image-preview\', \'%1$s\');" />', … … 662 689 __( 'use this picture', 'mon-laboratoire' ) 663 690 ); 664 // Hidden input for value 691 // Hidden input for value. 665 692 $output .= $this->hidden_field( $name, $initial_value, $name ) . ' '; 666 // Image preview 693 // Image preview. 667 694 $output .= sprintf( 668 695 '<a href="#" class="hover-zoom-square30"><img width="30" height="30" id="%1$s-image-preview" class="wp-image-8 wp-post-image%2$s" src="%3$s" alt="%4$s"></a>', … … 677 704 678 705 /** 679 * Generate an HTML code for the choice of an image for a person 680 * @param string $name name of the form 681 * @param string $description comment displayed just above the form 682 * @param string $initial_value Initial value of the form 683 * @return string HTML code 706 * Generate person image selector. 707 * 708 * @param string $name Name of the field. 709 * @param string $description Help text. 710 * @param string $initial_value Initial value. 711 * @return string HTML code for image selector. 684 712 * @access private 685 713 */ … … 689 717 string $initial_value 690 718 ): string { 691 $options2 = get_option( 'MonLabo_settings_group2' );719 $options2 = get_option( 'MonLabo_settings_group2' ); 692 720 $default_image = $this->_html->image_from_id_or_url( $options2['MonLabo_img_par_defaut'] ); 693 721 $output = sprintf( … … 696 724 wp_kses_post( $description ) 697 725 ); 698 // "None" button 726 // "None" button. 699 727 $output .= sprintf( 700 728 '<input id="%1$s_no_logo_button" class="button" value="%2$s" onclick="MonLabo.selectDefaultPicture(\'%1$s-image-preview\', \'%1$s\', \'%3$s\');" type="button" />', … … 703 731 esc_js( $default_image ) 704 732 ); 705 // Media selection button 733 // Media selection button. 706 734 $output .= sprintf( 707 735 ' <input id="%1$s-upload-image-button" type="button" class="button" value="%2$s" onclick="MonLabo.imageMediaMenu(\'%3$s\', \'%4$s\', \'%1$s-image-preview\', \'%1$s\');" />', … … 711 739 esc_js( __( 'use this picture', 'mon-laboratoire' ) ) 712 740 ); 713 // Hidden input for value 741 // Hidden input for value. 714 742 $output .= $this->hidden_field( $name, $initial_value, $name ) . ' '; 715 // Image preview 743 // Image preview. 716 744 $url = $this->_html->image_from_id_or_url( $initial_value ); 717 745 if ( empty( $initial_value ) || 'DEFAULT' === $initial_value ) { -
mon-laboratoire/trunk/Admin/Forms/class-generic-forms-view.php
r3361909 r3369834 2 2 namespace MonLabo\Admin\Forms; 3 3 4 use MonLabo\Frontend\ {Html};4 use MonLabo\Frontend\Html; 5 5 6 6 defined( 'ABSPATH' ) || die( 'No direct script access allowed' ); 7 7 8 8 /** 9 * Class \MonLabo\Admin\Generic_Forms_View 10 * Facade class providing unified form view 9 * Class \MonLabo\Admin\Forms\Generic_Forms_View 10 * 11 * Facade class providing unified form view functionality for the admin interface. 11 12 * 12 * Methods : 13 * This abstract class serves as a facade for generating form elements 14 * with consistent styling and behavior across the plugin's admin forms. 15 * It provides methods for creating various types of form fields with 16 * proper HTML escaping and accessibility features. 17 * 18 * Methods: 19 * _input_field( bool $is_mandatory, string $legend, string $input_type, 20 * string $name, string $description, string $input_group_class, 21 * string $input_id, string $initial_value, string $input_class, 22 * string $input_custom ) 23 * _large_text_field( bool $is_mandatory, string $legend, string $name, 24 * string $description, string $initial_value, string $css_id ) 25 * _maybe_add_field_label( string $name, string $legend, bool $is_mandatory ) 26 * description( string $description ) 13 27 * 14 * _input_field( $is_mandatory, $legend, $input_type, $name, $description, $input_group_class, $input_id, $initial_value, $input_class, $input_custom)15 * _large_text_field( $is_mandatory, $legend, $name, $description, $initial_value, $css_id)16 * _maybe_add_field_label( $name, $legend, $is_mandatory )17 * description( string $description )18 19 *20 28 * @package MonLabo\Admin\Forms 21 29 */ … … 24 32 /** 25 33 * Instance of the Html helper class. 26 * @access protected 27 * @var Html 34 * 35 * Provides HTML generation utilities for form elements. 36 * 37 * @access protected 38 * @var Html Instance of the Html helper class. 28 39 */ 29 40 protected $_html = null; … … 31 42 /** 32 43 * Constructor. 44 * 45 * Initializes the Html helper instance. 46 * 33 47 * @access public 34 48 */ … … 37 51 } 38 52 39 40 /** 41 * Generate an HTML code for a generic input form field 42 * @param bool $is_mandatory if true, fill this field is mandatory. 43 * @param string $legend text that is displayed just before the field 44 * @param string $input_type type of the form field (text, url...) 45 * @param string $name name of the form field 46 * @param string $description text that is displayed after the field 47 * @param string $input_group_class CSS class of the input-group <div> tag 48 * @param string $input_id CSS id for the <input> tag. 49 * @param string $initial_value text initial value 50 * @param string $input_class additional CSS class for the <input> tag. 51 * @param string $input_custom additional custom things for the <input> tag. 52 * @return string HTML code of form field 53 * @access protected 54 */ 53 /** 54 * Generates HTML for a generic input form field. 55 * 56 * Creates an input field with Bootstrap-style input group wrapper, 57 * including proper HTML escaping and optional field requirements. 58 * 59 * 60 * @param bool $is_mandatory Whether the field is required. 61 * @param string $legend Label text displayed as placeholder. 62 * @param string $input_type HTML input type (text, url, email, etc). 63 * @param string $name Field name attribute. 64 * @param string $description Help text displayed below the field. 65 * @param string $input_group_class Additional CSS classes for the wrapper div. Default ''. 66 * @param string $input_id HTML ID attribute for the input element. Default ''. 67 * @param string $initial_value Initial field value. Default ''. 68 * @param string $input_class Additional CSS classes for the input element. Default ''. 69 * @param string $input_custom Additional custom HTML attributes. Default ''. 70 * @return string Generated HTML for the form field. 71 * @access protected 72 */ 55 73 protected function _input_field( 56 74 bool $is_mandatory, … … 65 83 string $input_custom = '' 66 84 ): string { 67 $output = sprintf( '<div class="input-group%s">', $input_group_class ? ' ' . esc_attr( $input_group_class ) : '' ); 85 // Open wrapper div with optional additional classes. 86 $output = '<div class="input-group'; 87 if ( ! empty( $input_group_class ) ) { 88 $output .= ' ' . esc_attr( $input_group_class ); 89 } 90 $output .= '">'; 91 92 // Add input group addon for Bootstrap styling. 68 93 $output .= '<div class="input-group-addon"></div>'; 94 95 // Modify legend for optional fields. 69 96 if ( ! $is_mandatory ) { 70 97 $legend .= ' (' . __( 'optional', 'mon-laboratoire' ) . ')'; 71 98 } 99 100 // Build input attributes array. 72 101 $input_attrs = array( 73 'type' => esc_attr( $input_type ),74 'class' => 'form-control' . ( $input_class ? ' ' . esc_attr( $input_class ) : '' ),75 'name' => esc_attr( $name),76 'placeholder' => esc_attr( $legend ),77 'id' => esc_attr( $input_id ),78 'value' => strval( esc_attr( $initial_value ) ),79 'required' => $is_mandatory ? 'required' : null,102 'type' => esc_attr( $input_type ), 103 'class' => 'form-control', 104 'name' => esc_attr( $name ), 105 'placeholder' => esc_attr( $legend ), 106 'id' => esc_attr( $input_id ), 107 'value' => '__EMPTY__', 108 'required' => $is_mandatory ? 'required' : null, 80 109 ); 110 111 // Add optional attributes if provided. 112 if ( ! empty( $input_class ) ) { 113 $input_attrs['class'] .= ' ' . esc_attr( $input_class ); 114 } 115 81 116 // Remove empty attributes 82 if ( '0' === $input_attrs['value'] ) {83 $input_attrs['value'] = 'ZERO_TO_KEEP';84 }85 117 $input_attrs = array_filter( $input_attrs ); 86 if ( isset( $input_attrs['value'] ) && 'ZERO_TO_KEEP' === $input_attrs['value'] ) { 87 $input_attrs['value'] = '0'; 88 } 118 // Handle initial value, including special case for '0'. 119 if ( '' !== $initial_value ) { 120 $input_attrs['value'] = esc_attr( $initial_value ); 121 } 122 if ( '__EMPTY__' === $input_attrs['value'] ) { 123 unset( $input_attrs['value'] ); 124 } 125 126 // Build HTML attributes string. 89 127 $attrs_html = ''; 90 128 foreach ( $input_attrs as $key => $value ) { 91 $attrs_html .= sprintf( ' %s="%s"', $key, $value ); 92 } 93 if ( $input_custom ) { 129 $attrs_html .= sprintf( ' %s="%s"', $key, $value ); 130 } 131 132 // Add custom attributes if provided. 133 if ( ! empty( $input_custom ) ) { 94 134 $attrs_html .= ' ' . $input_custom; 95 135 } 136 137 // Build final HTML output. 96 138 $output .= sprintf( '<input%s />', $attrs_html ); 97 139 $output .= $this->description( $description ) . '</div>'; … … 100 142 101 143 /** 102 * Generates large text field. 103 * @param bool $is_mandatory if true, fill this field is mandatory. 104 * @param string $legend text that is displayed just before the field 105 * @param string $name name of the form field 106 * @param string $description text that is displayed after the field 107 * @param string $initial_value initial value 108 * @param string $css_id CSS id for the <input> tag. 109 * @return string HTML code of form field 110 * @access protected 111 */ 144 * Generates a large text input field. 145 * 146 * Creates a text input field with larger styling applied via the 147 * 'input-group-large' CSS class. This is a convenience wrapper around 148 * the _input_field method. 149 * 150 * @param bool $is_mandatory Whether the field is required. 151 * @param string $legend Label text displayed as placeholder. 152 * @param string $name Field name attribute. 153 * @param string $description Help text displayed below the field. 154 * @param string $initial_value Initial field value. Default ''. 155 * @param string $css_id HTML ID attribute for the input element. Default ''. 156 * @return string Generated HTML for the large text field. 157 * @access protected 158 */ 112 159 protected function _large_text_field( 113 160 bool $is_mandatory, … … 118 165 string $css_id = '' 119 166 ): string { 120 return $this->_input_field( $is_mandatory, $legend, 'text', $name, $description, 'input-group-large', $css_id, 121 $initial_value ); 122 } 123 124 /** 125 * Adds a label to a form field if needed. 126 * 127 * @param string $name Field name attribute. 128 * @param string $legend Label text. 129 * @param bool $is_mandatory Whether the field is required. 130 * @return string Generated HTML for the label. 131 * @access protected 132 */ 133 protected function _maybe_add_field_label( $name, $legend, $is_mandatory ) { 167 return $this->_input_field( 168 $is_mandatory, 169 $legend, 170 'text', 171 $name, 172 $description, 173 'input-group-large', 174 $css_id, 175 $initial_value 176 ); 177 } 178 179 /** 180 * Generates a label element for a form field. 181 * 182 * Creates an HTML label element with proper accessibility attributes 183 * and optional indicator for non-required fields. 184 * 185 * @param string $name Field name attribute (used for 'for' attribute). 186 * @param string $legend Label text content. 187 * @param bool $is_mandatory Whether the field is required. 188 * @return string Generated HTML for the label, or empty string if not needed. 189 * @access protected 190 */ 191 protected function _maybe_add_field_label( string $name, string $legend, bool $is_mandatory ): string { 192 // Don't generate label if legend is empty and field is mandatory. 134 193 if ( empty( $legend ) && $is_mandatory ) { 135 194 return ''; 136 195 } 137 196 $output = sprintf( '<label for="%s">%s', esc_attr( $name ), esc_html( $legend ) ); 138 $output .= ! $is_mandatory ? sprintf( ' <small>(%s)</small>', __( 'optional', 'mon-laboratoire' ) ) : ''; 197 198 // Add optional indicator for non-mandatory fields. 199 if ( ! $is_mandatory ) { 200 $output .= sprintf( ' <small>(%s)</small>', __( 'optional', 'mon-laboratoire' ) ); 201 } 202 139 203 $output .= '</label>'; 204 140 205 return $output; 141 206 } 142 207 143 208 /** 144 * Generate an HTML code for description 145 * @param string $description text 146 * @return string HTML code 209 * Generates HTML for a field description. 210 * 211 * Creates a properly escaped description div element for form field 212 * help text. Returns empty string if no description is provided. 213 * 214 * @param string $description The description text to display. 215 * @return string Generated HTML for the description, or empty string. 147 216 */ 148 217 public function description( string $description ): string { 149 return empty( $description ) ? 150 '' : sprintf( '<div class="description">%s</div>', wp_kses_post( $description ) ); 151 } 152 218 if ( empty( $description ) ) { 219 return ''; 220 } 221 222 return sprintf( '<div class="description">%s</div>', wp_kses_post( $description ) ); 223 } 153 224 } 154 225 ?> -
mon-laboratoire/trunk/Admin/Forms/class-options-forms-view.php
r3361909 r3369834 11 11 * Class \MonLabo\Admin\Options_Forms_View 12 12 * 13 * Handles rendering of settings fields in the WordPress admin 13 * Handles rendering of settings fields in the WordPress admin. 14 14 * 15 15 * This class provides methods for rendering various types of form fields … … 27 27 * add() 28 28 * select_generic_render( array $args ) 29 * _get_multisite_items() 29 30 * radio_generic_render( array $args ) 31 * _get_radio_items( string $option_name ) 32 * _get_publication_server_items() 33 * _get_language_config_items( $translate, $html, $polylang_interface ) 30 34 * hidden_generic_render( array $args ) 31 35 * text_field_generic_render( array $args ) … … 41 45 * button_test_send_email_generic_render( array $args ) 42 46 * button_create_default_parent_page_generic_render( array $args ) 47 * _create_parent_page( string $option_name, array &$options ) 43 48 * checkbox_generic_render( array $args ) 44 49 * checkbox2_generic_render( array $args ) 50 * hidden_order_generic_render( array $args ) 45 51 * number_generic_render( array $args ) 46 52 * select_page_generic_render( array $args ) … … 51 57 52 58 /** 53 * Current instance of Forms_View 59 * Current instance of Forms_View. 60 * 54 61 * @access protected 55 * @var Forms_View62 * @var Forms_View 56 63 */ 57 64 protected $_forms_view; 58 65 59 66 /** 60 * Cache of WordPress options 61 * 62 * Stores retrieved option values to avoid repeated database calls.67 * Cache of WordPress options. 68 * 69 * Stores retrieved option values to avoid repeated database calls. 63 70 * 64 71 * @access private 65 * @var array<string, string[]> Key is option group, value is array of options72 * @var array<string, string[]> Key is option group, value is array of options. 66 73 */ 67 74 private $_options = array(); 68 75 69 76 /** 70 * Constructor for Options_Forms_View class 77 * Constructor for Options_Forms_View class. 71 78 * 72 79 * Initializes the options cache by loading all option groups … … 81 88 82 89 /** 83 * Display a <SELECT> option list form field90 * Add a settings field to the admin page. 84 91 * Called with "add_field( 'select' ... " 85 * @param string $type Type of the field 86 * @param string $title Text before the form field 87 * @param string $page Current section of a menu 88 * @param string $section Current page of a menu 92 * 93 * @param string $type Type of the field (select, radio, text_field, etc.). 94 * @param string $title Text before the form field. 95 * @param string $page Current page of a menu. 96 * @param string $section Current section of a menu. 89 97 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : 90 98 * - $args['settings_group'] : Group of option to update … … 117 125 'hidden_order', 118 126 ); 119 if ( isset( $args['settings_group'] ) 120 and isset( $args['option_name'] ) 121 and isset( $args['description'] ) 122 and isset( $args['disable'] ) 123 and in_array( $type, $valid_types ) 127 128 if ( ! isset( $args['settings_group'], $args['option_name'], $args['description'], $args['disable'] ) ) { 129 return $this; 130 } 131 if ( ! in_array( $type, $valid_types ) ) { 132 return $this; 133 } 134 135 // $args['class'] can complete $args['option_name'] as a class. 136 $class = $args['class'] ?? ''; 137 $option_name = $args['option_name']; 138 139 if ( $option_name !== $class ) { 140 $class = empty( $class ) ? $option_name : $option_name . ' ' . $class; 141 } 142 143 $hideclass = ''; 144 if ( ( isset( $args['hide'] ) && true === $args['hide'] ) 145 || ( isset( $args['disable'] ) && true === $args['disable'] ) 124 146 ) { 125 //$args['class'] can complete $args['option_name'] ass a class 126 $class = $args['class'] ?? ''; 127 $option_name = $args['option_name']; 128 if ( $option_name !== $class ) { 129 $class = empty( $class ) ? $option_name : $option_name . ' ' . $class; 130 } 131 $hideclass = ''; 132 if ( 133 ( isset( $args['hide'] ) && $args['hide'] === true ) 134 || ( isset( $args['disable'] ) && $args['disable'] === true ) 135 ) { 136 $hideclass = ' MonLabo_hide'; 137 } 138 $title_text = empty( $class . $hideclass ) ? '' : '<span class="' . $class . $hideclass . '">'. $title . '</span>'; 139 $title_text2 = empty( $title ) ? '' : $title_text; 140 add_settings_field( 141 $args['option_name'], 142 $title_text2 , 143 array( &$this, $type . '_generic_render' ), 144 $page, 145 $section, 146 $args 147 ); 148 } 149 return $this; 150 } 151 152 153 /** 154 * Display a <SELECT> option list form field 147 $hideclass = ' MonLabo_hide'; 148 } 149 $title = ( '' === $title ? ' ' : $title ); 150 $title_text = empty( $class . $hideclass ) ? '' : '<span class="' . $class . $hideclass . '">' . $title . '</span>'; 151 $title_text2 = empty( $title ) ? '' : $title_text; 152 153 add_settings_field( 154 $args['option_name'], 155 $title_text2, 156 array( &$this, $type . '_generic_render' ), 157 $page, 158 $section, 159 $args 160 ); 161 162 return $this; 163 } 164 165 /** 166 * Render a select dropdown field. 155 167 * Called with "add_field( 'select' ... " 156 168 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string,on_change?:string} $args … … 161 173 * - $args['disable'] : true if disabled form 162 174 * - $args['on_change'] : Optional. JavaScript for onchange. 163 * @return Options_Forms_View For method chaining.175 * @return Options_Forms_View Returns self for method chaining. 164 176 */ 165 177 public function select_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 167 179 return $this->hidden_generic_render( $args ); 168 180 } 169 170 181 switch ( $args['option_name'] ) { 171 182 case 'MonLabo_hal_publi_style': … … 173 184 break; 174 185 case 'MonLabo_DescartesPubmed_format': 175 $items = array( 'html_default'=>'html_default', 'html_hal'=>'html_hal' );186 $items = array( 'html_default' => 'html_default', 'html_hal' => 'html_hal' ); 176 187 break; 177 188 case 'MonLabo_multisite_db_to_use': 178 $items = array( 179 '___no_change___' => __( '--- No change ---', 'mon-laboratoire' ), 180 '___manual_edit___' => __( '--- Manual edit (use field "Prefix" below) ---', 'mon-laboratoire' ), 181 ); 182 if ( is_multisite() 183 && function_exists( 'get_sites' ) 184 && class_exists( 'WP_Site_Query' ) //WP version >= 4.6 185 ) { 186 //get_main_site_id 187 $sites = get_sites(); 188 if ( !empty( $sites ) ) { 189 $actual_site = get_site(); 190 foreach ( $sites as $site ) { 191 $suffix = ''; 192 if ( $site->blog_id === $actual_site->blog_id ) { 193 $suffix = ' — '. __( 'Current site', 'mon-laboratoire' ); 194 } 195 global $wpdb; 196 $prefix = $wpdb->get_blog_prefix( $site->blog_id ); 197 $items[$prefix] = $prefix . ' : ' . $site->__get('blogname') . ' (' . $site->__get('siteurl') . ')' . $suffix; 198 } 199 } 200 } 201 break; 189 $items = $this->_get_multisite_items(); 190 break; 202 191 default: 203 192 return $this; /* error */ 204 193 } 205 $name = $args['settings_group'] . '[' . $args['option_name'] . ']';206 $onchange = empty( $args['on_change'] ) ? '' : esc_attr( $args['on_change'] );194 $name = $args['settings_group'] . '[' . $args['option_name'] . ']'; 195 $onchange = empty( $args['on_change'] ) ? '' : esc_attr( $args['on_change'] ); 207 196 $initial_value = $this->_options[ $args['settings_group'] ][ $args['option_name'] ]; 208 echo $this->_forms_view->select( $name, $items, true, '', '', $initial_value, $onchange, '' ); 209 return $this; 210 } 211 212 /** 213 * Renders a radio button group field. 197 echo $this->_forms_view->select( $name, $items, true, '', '', $initial_value, $onchange, '' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped //output escaping is handled by called methods 198 return $this; 199 } 200 201 /** 202 * Get multisite database items for select field. 203 * 204 * @return array<string,string> Array of multisite options. 205 * @access private 206 */ 207 private function _get_multisite_items(): array { 208 $items = array( 209 '___no_change___' => __( '--- No change ---', 'mon-laboratoire' ), 210 '___manual_edit___' => __( '--- Manual edit (use field "Prefix" below) ---', 'mon-laboratoire' ), 211 ); 212 if ( 213 ! is_multisite() 214 || ! function_exists( 'get_sites' ) 215 || ! class_exists( 'WP_Site_Query' ) //WP version < 4.6 216 ) { 217 return $items; 218 } 219 //get_main_site_id 220 $sites = get_sites(); 221 if ( empty( $sites ) ) { 222 return $items; 223 } 224 $actual_site = get_site(); 225 global $wpdb; 226 foreach ( $sites as $site ) { 227 $suffix = ''; 228 if ( $site->blog_id === $actual_site->blog_id ) { 229 $suffix = ' — ' . __( 'Current site', 'mon-laboratoire' ); 230 } 231 $prefix = $wpdb->get_blog_prefix( $site->blog_id ); 232 $items[ $prefix ] = $prefix . ' : ' . $site->__get( 'blogname' ) . ' (' . $site->__get( 'siteurl' ) . ')' . $suffix; 233 } 234 return $items; 235 } 236 237 /** 238 * Render a radio button group field. 239 * 214 240 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string,on_change?:string} $args 215 241 * Field configuration options. … … 219 245 * - $args['disable'] : true if disabled form 220 246 * - $args['hide'] : true if CSS display is hide 221 * - $args['on_change'] : Optional. JavaScript for onchange .222 * @return Options_Forms_View For method chaining.247 * - $args['on_change'] : Optional. JavaScript for onchange event. 248 * @return Options_Forms_View Returns self for method chaining. 223 249 */ 224 250 public function radio_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 226 252 return $this->hidden_generic_render( $args ); 227 253 } 228 $translate = new Translate(); 229 $html = new Html(); 230 $Polylang_Interface = new Polylang_Interface(); 231 switch ( $args['option_name'] ) { 232 case 'MonLabo_publication_server_type': 233 $items = array( 'hal' => '<a href="https://hal.science/"><img width="61" height="30" class="wp-image-8 alignleft wp-post-image" '. 'src="' . plugins_url( 'images/logoHAL.png', __DIR__ ) . '" alt="'. __( 'logo of HAL', 'mon-laboratoire' ) . '" /></a> '. __( 'HAL (Public API open to all)', 'mon-laboratoire' ), 234 'DescartesPubli'=> '<img width="61" height="34" class="wp-image-8 alignleft wp-post-image" src="' . plugins_url( 'images/DescartesPubli.logo.png', __DIR__ ) . '" alt="'. __( 'logo of Descartes publi', 'mon-laboratoire' ) . '" /> '. __( 'Descartes Publi (API reserved for the University of ParisDescartes)', 'mon-laboratoire' ), 235 'both' => __( 'Both! (HAL is used by default if the option <i>base</i> is not specified in <i>[publication_list]</i>)', 'mon-laboratoire' ), 236 'aucun' => _x( 'None', 'option-langage', 'mon-laboratoire' ) ); 237 break; 238 239 case 'MonLabo_trusted_visitors': 240 $items = array( 241 App::PRIVACY_TRUST_EVERYBODY => __( 'Everybody', 'mon-laboratoire' ), 242 App::PRIVACY_TRUST_LOGGED_IN_USERS => __( 'Logged-in users', 'mon-laboratoire' ), 243 App::PRIVACY_TRUST_IP_ZONE => __( 'Logged-in users and visitors from trusted IP addresses', 'mon-laboratoire' ), 244 ); 245 break; 246 247 case 'MonLabo_email_privacy': 248 $items = array( 249 App::PRIVACY_SHOW => __( 'Always show', 'mon-laboratoire' ), 250 App::PRIVACY_HIDE => __( 'Always hide', 'mon-laboratoire' ), 251 App::PRIVACY_LOCAL_SHOW => __( 'Only show to trusted visitors', 'mon-laboratoire' ), 252 App::PRIVACY_FORM_LOCAL_SHOW => __( 'Only show to trusted visitors, replace with contact form for others', 'mon-laboratoire' ) 253 ); 254 break; 255 256 case 'MonLabo_phone_privacy': 257 $items = array( 258 App::PRIVACY_SHOW => __( 'Always show', 'mon-laboratoire' ), 259 App::PRIVACY_HIDE => __( 'Always hide', 'mon-laboratoire' ), 260 App::PRIVACY_LOCAL_SHOW => __( 'Only show to trusted visitors', 'mon-laboratoire' ), 261 App::PRIVACY_SWITCHBOARD_LOCAL_SHOW => __( 'Only show to trusted visitors, replace with switchboard for others', 'mon-laboratoire' ) 262 ); 263 break; 264 265 case 'MonLabo_room_privacy': 266 case 'MonLabo_photo_privacy': 267 $items = array( 268 App::PRIVACY_SHOW => __( 'Always show', 'mon-laboratoire' ), 269 App::PRIVACY_HIDE => __( 'Always hide', 'mon-laboratoire' ), 270 App::PRIVACY_LOCAL_SHOW => __( 'Only show to trusted visitors', 'mon-laboratoire' ) 271 ); 272 break; 273 274 case 'MonLabo_language_config': 275 $items = array( 'en' => __( 'English', 'mon-laboratoire' ) . ' ' . $html->get_translation_flag( 'en' ), 276 'fr' => __( 'French', 'mon-laboratoire' ). ' ' . $html->get_translation_flag( 'fr' ), 277 'browser' => __( 'Visitor\'s browser language', 'mon-laboratoire' ) . ' <small>(' . __( 'here', 'mon-laboratoire' ) . ' : <em>' .$translate->get_browser_language() . '</em>)</small>', 278 'Polylang' => __( 'Multilingual, using the Polylang translation plugin', 'mon-laboratoire' ) . ' <small>(' . __( 'Polylang plugin status', 'mon-laboratoire' ). ' : <em>' . $Polylang_Interface->get_polylang_plugin_status( "translated" ) . '</em>)</small>' , 279 'WordPress' => 280 sprintf( 281 __( 'Language configured %1$s in WordPress %2$s or by a translation plugin' , 'mon-laboratoire' ) 282 , '<a href="' . admin_url( 'options-general.php' ) . '">' 283 , '</a>' 284 ) 285 . ' <small>(' . __( 'currently', 'mon-laboratoire' ) . ' : <em>' 286 . ( 'activated' === $Polylang_Interface->get_polylang_plugin_status() 287 ? __( 'defined by Polylang', 'mon-laboratoire' ) 288 : get_locale() 289 ) 290 . '</em>)</small>', 291 ); 292 break; 293 default: 294 return $this; /* Error */ 295 } 296 $hideclass = ( isset($args['hide']) && $args['hide'] === true ) ? ' class="MonLabo_hide"' : ''; 297 echo( '<fieldset' . $hideclass . '>'); 298 if (! empty( trim( $args['description'])) ){ 254 $items = $this->_get_radio_items( $args['option_name'] ); 255 256 if ( empty( $items ) ) { 257 return $this; 258 } 259 260 $hideclass = ( isset( $args['hide'] ) && true === $args['hide'] ) ? ' class="MonLabo_hide"' : ''; 261 echo( '<fieldset' . $hideclass . '>' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 262 if ( ! empty( trim( $args['description'] ) ) ) { 299 263 echo( '<legend>' . wp_kses_post( $args['description'] ) . '</legend>' ); 300 264 } 301 foreach ( $items as $item Key => $item ) {265 foreach ( $items as $item_key => $item ) { 302 266 $checked = ( isset( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ) ) 303 ? checked( $this->_options[ $args['settings_group'] ][ $args['option_name'] ], $item Key, false )267 ? checked( $this->_options[ $args['settings_group'] ][ $args['option_name'] ], $item_key, false ) 304 268 : ''; 305 269 $input_id = uniqid(); 306 270 echo( '<div class="MonLabo_radio">' 307 .'<input type="radio"' 308 .' id="' . $input_id . '"' 309 .' name="' . esc_attr( $args['settings_group'] . '[' . $args['option_name'] . ']' ) . '"' 310 .' value="' . wp_kses_post( $itemKey ) . '"' 311 . $checked . ' />' 312 . '<label for="' . $input_id . '">' . $item . '</label>' 313 .'</div>' ); 314 271 . '<input type="radio"' 272 . ' id="' . $input_id . '"' 273 . ' name="' . esc_attr( $args['settings_group'] . '[' . $args['option_name'] . ']' ) . '"' 274 . ' value="' . wp_kses_post( $item_key ) . '"' 275 . $checked . ' />' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 276 . '<label for="' . $input_id . '">' . $item . '</label>' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEs 277 . '</div>' ); 315 278 } 316 279 echo '</fieldset>'; 317 280 return $this; 281 } 282 283 /** 284 * Get radio button items based on option name. 285 * 286 * @param string $option_name Name of the option. 287 * @return array<string,string> Array of radio items. 288 * @access private 289 */ 290 private function _get_radio_items( string $option_name ): array { 291 $translate = new Translate(); 292 $html = new Html(); 293 $polylang_interface = new Polylang_Interface(); 294 switch ( $option_name ) { 295 case 'MonLabo_publication_server_type': 296 return $this->_get_publication_server_items(); 297 298 case 'MonLabo_trusted_visitors': 299 return array( 300 App::PRIVACY_TRUST_EVERYBODY => __( 'Everybody', 'mon-laboratoire' ), 301 App::PRIVACY_TRUST_LOGGED_IN_USERS => __( 'Logged-in users', 'mon-laboratoire' ), 302 App::PRIVACY_TRUST_IP_ZONE => __( 'Logged-in users and visitors from trusted IP addresses', 'mon-laboratoire' ), 303 ); 304 305 case 'MonLabo_email_privacy': 306 return array( 307 App::PRIVACY_SHOW => __( 'Always show', 'mon-laboratoire' ), 308 App::PRIVACY_HIDE => __( 'Always hide', 'mon-laboratoire' ), 309 App::PRIVACY_LOCAL_SHOW => __( 'Only show to trusted visitors', 'mon-laboratoire' ), 310 App::PRIVACY_FORM_LOCAL_SHOW => __( 'Only show to trusted visitors, replace with contact form for others', 'mon-laboratoire' ), 311 ); 312 313 case 'MonLabo_phone_privacy': 314 return array( 315 App::PRIVACY_SHOW => __( 'Always show', 'mon-laboratoire' ), 316 App::PRIVACY_HIDE => __( 'Always hide', 'mon-laboratoire' ), 317 App::PRIVACY_LOCAL_SHOW => __( 'Only show to trusted visitors', 'mon-laboratoire' ), 318 App::PRIVACY_SWITCHBOARD_LOCAL_SHOW => __( 'Only show to trusted visitors, replace with switchboard for others', 'mon-laboratoire' ), 319 ); 320 321 case 'MonLabo_room_privacy': 322 case 'MonLabo_photo_privacy': 323 return array( 324 App::PRIVACY_SHOW => __( 'Always show', 'mon-laboratoire' ), 325 App::PRIVACY_HIDE => __( 'Always hide', 'mon-laboratoire' ), 326 App::PRIVACY_LOCAL_SHOW => __( 'Only show to trusted visitors', 'mon-laboratoire' ), 327 ); 328 329 case 'MonLabo_language_config': 330 return $this->_get_language_config_items( $translate, $html, $polylang_interface ); 331 332 default: 333 return array(); /* Error */ 334 } 335 } 336 337 /** 338 * Get publication server type items for radio field. 339 * 340 * @return array<string,string> Array of publication server options. 341 * @access private 342 */ 343 private function _get_publication_server_items(): array { 344 return array( 345 'hal' => '<a href="https://hal.science/"><img width="61" height="30" class="wp-image-8 alignleft wp-post-image" ' 346 . 'src="' . plugins_url( 'images/logoHAL.png', __DIR__ ) . '" alt="' . __( 'logo of HAL', 'mon-laboratoire' ) . '" /></a> ' 347 . __( 'HAL (Public API open to all)', 'mon-laboratoire' ), 348 'DescartesPubli' => '<img width="61" height="34" class="wp-image-8 alignleft wp-post-image" src="' 349 . plugins_url( 'images/DescartesPubli.logo.png', __DIR__ ) . '" alt="' . __( 'logo of Descartes publi', 'mon-laboratoire' ) . '" /> ' 350 . __( 'Descartes Publi (API reserved for the University of ParisDescartes)', 'mon-laboratoire' ), 351 'both' => __( 'Both! (HAL is used by default if the option <i>base</i> is not specified in <i>[publication_list]</i>)', 'mon-laboratoire' ), 352 'aucun' => _x( 'None', 'option-langage', 'mon-laboratoire' ), 353 ); 354 } 355 356 /** 357 * Get language configuration items for radio field. 358 * 359 * @param Translate $translate Translate instance. 360 * @param Html $html HTML helper instance. 361 * @param Polylang_Interface $polylang_interface Polylang interface instance. 362 * @return array<string,string> Array of language configuration options. 363 * @access private 364 */ 365 private function _get_language_config_items( $translate, $html, $polylang_interface ): array { 366 return array( 367 'en' => __( 'English', 'mon-laboratoire' ) . ' ' . $html->get_translation_flag( 'en' ), 368 'fr' => __( 'French', 'mon-laboratoire' ) . ' ' . $html->get_translation_flag( 'fr' ), 369 'browser' => __( 'Visitor\'s browser language', 'mon-laboratoire' ) . ' <small>(' . __( 'here', 'mon-laboratoire' ) 370 . ' : <em>' . $translate->get_browser_language() . '</em>)</small>', 371 'Polylang' => __( 'Multilingual, using the Polylang translation plugin', 'mon-laboratoire' ) . ' <small>(' 372 . __( 'Polylang plugin status', 'mon-laboratoire' ) . ' : <em>' 373 . $polylang_interface->get_polylang_plugin_status( 'translated' ) . '</em>)</small>', 374 'WordPress' => sprintf( 375 __( 'Language configured %1$s in WordPress %2$s or by a translation plugin', 'mon-laboratoire' ), 376 '<a href="' . admin_url( 'options-general.php' ) . '">', 377 '</a>' 378 ) . ' <small>(' . __( 'currently', 'mon-laboratoire' ) . ' : <em>' 379 . ( 'activated' === $polylang_interface->get_polylang_plugin_status() 380 ? __( 'defined by Polylang', 'mon-laboratoire' ) 381 : get_locale() 382 ) . '</em>)</small>', 383 ); 318 384 } 319 385 … … 328 394 public function hidden_generic_render( array $args ): self { 329 395 echo $this->_forms_view->hidden_field( 330 $args['settings_group'] . '[' . $args['option_name'] . ']' ,396 $args['settings_group'] . '[' . $args['option_name'] . ']', 331 397 strval( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ) 332 398 ); … … 343 409 * - $args['disable'] : true if disabled form 344 410 * - $args['on_change'] : js to launch if any change 345 * - $args['hide'] : true if CSS display is hide346 * @return Options_Forms_View For method chaining.411 * - $args['hide'] : true if CSS display is hide 412 * @return Options_Forms_View Returns self for method chaining. 347 413 */ 348 414 public function text_field_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 361 427 * - $args['on_change'] : js to launch if any change 362 428 * - $args['hide'] : true if CSS display is hide 363 * @return Options_Forms_View For method chaining.429 * @return Options_Forms_View Returns self for method chaining. 364 430 */ 365 431 public function email_field_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 369 435 370 436 /** 371 * Display a email form field437 * Render a generic input field. 372 438 * Called with "add_field( 'text' ... " 373 439 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,on_change:string} $args Parameters : 374 * - $args['settings_group'] : Group of option to update 375 * - $args['option_name'] : Name of option to update 376 * - $args['description'] : Description to display 377 * - $args['disable'] : true if disabled form 440 * - $args['option_name'] : Name of option to update 441 * - $args['description'] : Description to display 442 * - $args['settings_group'] : Group of option to update 443 * - $args['disable'] : true if disabled form 444 * - $args['hide'] : true if CSS display is hide 378 445 * - $args['on_change'] : js to launch if any change 379 * - $args['hide'] : true if CSS display is hide 380 * @param string $type type of text field 381 * @return Options_Forms_View For method chaining. 446 * @param string $type Type of input field. 447 * @return Options_Forms_View Returns self for method chaining. 382 448 */ 383 449 private function _input_generic_render( array $args, string $type ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod 384 450 $on_change = ''; 385 if ( ! empty( $args['on_change'] ) ) {451 if ( ! empty( $args['on_change'] ) ) { 386 452 $on_change = sprintf( ' onchange="%s"', esc_attr( $args['on_change'] ) ); 387 453 } 388 $type = ( $args['disable'] ? 'hidden' : $type );454 $type = ( $args['disable'] ? 'hidden' : $type ); 389 455 $hideclass = ''; 390 if ( 391 ( isset( $args['hide'] ) && $args['hide'] === true ) 392 || ( isset( $args['disable'] ) && $args['disable'] === true ) 393 ) { 456 if ( ( isset( $args['hide'] ) && true === $args['hide'] ) 457 || ( isset( $args['disable'] ) && true === $args['disable'] ) 458 ) { 394 459 $hideclass = ' MonLabo_hide'; 395 460 } … … 399 464 esc_attr( $args['settings_group'] . '[' . $args['option_name'] . ']' ), 400 465 esc_attr( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ), 401 $on_change, 466 $on_change, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 402 467 wp_kses_post( $args['description'] ) 403 468 ); … … 406 471 407 472 /** 408 * Display a quadruple text form field for translation in fr/en and singular/plural473 * Render four text fields for translation (fr/en, singular/plural). 409 474 * Called with "add_field( 'four_text_fields' ... " 410 475 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 413 478 * - $args['disable'] : true if disabled form 414 479 * - $args['hide'] : true if CSS display is hide 415 * @return Options_Forms_View For method chaining.480 * @return Options_Forms_View Returns self for method chaining. 416 481 */ 417 482 public function four_text_fields_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod 418 483 $html = new Html(); 419 484 $array_options = array( 420 $args['option_name'] . '_en' =>$html->get_translation_flag( 'en' ) . ' ' . __( 'English singular', 'mon-laboratoire' ),421 $args['option_name'] . '_fr' =>$html->get_translation_flag( 'fr' ) . ' ' . __( 'French singular', 'mon-laboratoire' ),485 $args['option_name'] . '_en' => $html->get_translation_flag( 'en' ) . ' ' . __( 'English singular', 'mon-laboratoire' ), 486 $args['option_name'] . '_fr' => $html->get_translation_flag( 'fr' ) . ' ' . __( 'French singular', 'mon-laboratoire' ), 422 487 $args['option_name'] . 's_en' => $html->get_translation_flag( 'en' ) . ' ' . __( 'English plural', 'mon-laboratoire' ), 423 488 $args['option_name'] . 's_fr' => $html->get_translation_flag( 'fr' ) . ' ' . __( 'French plural', 'mon-laboratoire' ), … … 428 493 429 494 /** 430 * Display a double text form field for translation in fr/en495 * Render two text fields for translation (fr/en). 431 496 * Called with "add_field( 'two_text_fields' ... " 432 497 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 435 500 * - $args['disable'] : true if disabled form 436 501 * - $args['hide'] : true if CSS display is hide 437 * @return Options_Forms_View For method chaining.502 * @return Options_Forms_View Returns self for method chaining. 438 503 */ 439 504 public function two_text_fields_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod 440 505 $html = new Html(); 441 506 $array_options = array( 442 $args['option_name'] . '_en' => $html->get_translation_flag( 'en' ) . ' ' . __( 'English', 'mon-laboratoire' ),443 $args['option_name'] . '_fr' => $html->get_translation_flag( 'fr' ) . ' ' . __( 'French', 'mon-laboratoire' ),507 $args['option_name'] . '_en' => $html->get_translation_flag( 'en' ) . ' ' . __( 'English', 'mon-laboratoire' ), 508 $args['option_name'] . '_fr' => $html->get_translation_flag( 'fr' ) . ' ' . __( 'French', 'mon-laboratoire' ), 444 509 ); 445 510 echo( $this->_generate_array_options_field( $array_options, $args['settings_group'], $args['disable'], $args['hide'] ) ); … … 448 513 449 514 /** 450 * Generate a double text form field for translation in fr/en515 * Generate multiple text form fields. 451 516 * @param string[] $array_options List of each text options 452 517 * @param string $settings_group Group of option to update … … 456 521 * @access private 457 522 */ 458 private function _generate_array_options_field( array $array_options, string $settings_group, bool $disable = false, bool $hide = false ): string {523 private function _generate_array_options_field( array $array_options, string $settings_group, bool $disable = false, bool $hide = false ): string { 459 524 if ( empty( $array_options ) ) { 460 525 return ''; 461 526 } 462 $options_ DEFAULT= App::get_options_DEFAULT();463 $type = ( $disable ? 'hidden' : 'text' );464 $out = '';465 $hideclass = $hide ? ' MonLabo_hide' : '';527 $options_default = App::get_options_DEFAULT(); 528 $type = ( $disable ? 'hidden' : 'text' ); 529 $out = ''; 530 $hideclass = $hide ? ' MonLabo_hide' : ''; 466 531 if ( ! $disable ) { 467 532 $out .= '<table class="MonLabo-group-form' . $hideclass . '" role="presentation"><thead><tr>'; … … 479 544 esc_attr( $this->_options[ $settings_group ][ $option_name ] ) 480 545 ); 481 if ( ! $disable && ! empty( $options_ DEFAULT[ $settings_group ][ $option_name ] ) ) {546 if ( ! $disable && ! empty( $options_default[ $settings_group ][ $option_name ] ) ) { 482 547 $out2 .= sprintf( 483 548 'Ex: <em>%s</em>', 484 esc_html( (string) $options_ DEFAULT[ $settings_group ][ $option_name ] )549 esc_html( (string) $options_default[ $settings_group ][ $option_name ] ) 485 550 ); 486 551 } 487 552 $out2 .= ( $disable ? '' : '</td>' ); 488 553 } 489 $out .= $out2 . ( $disable ? '' : '</tr></tbody></table>' ) ;554 $out .= $out2 . ( $disable ? '' : '</tr></tbody></table>' ); 490 555 return $out; 491 556 } 492 557 493 558 /** 494 * Display an image choice form field559 * Render an image selector field. 495 560 * Called with "add_field( 'img_field' ... " 496 561 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 498 563 * - $args['option_name'] : Name of option to update 499 564 * - $args['disable'] : true if disabled form 500 * @return Options_Forms_View For method chaining.565 * @return Options_Forms_View Returns self for method chaining. 501 566 */ 502 567 public function img_field_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 506 571 echo( '<ul>' 507 572 . '<li><a href="#">' 508 . '<img width="60" height="60" id="image-preview" class="wp-image-8 alignleft img-arrondi wp-post-image" src="'509 . $html->image_from_id_or_url( $this->_options[ $args['settings_group'] ][ $args['option_name'] ])510 . '" alt="' . esc_attr( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] )511 . '" />'512 . '</a>' );513 echo( '</ li></ul></div></div>' );573 . '<img width="60" height="60" id="image-preview" class="wp-image-8 alignleft img-arrondi wp-post-image" src="' 574 . esc_url( $html->image_from_id_or_url( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ) ) 575 . '" alt="' . esc_attr( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ) 576 . '" />' 577 . '</a></li></ul>' ); 578 echo( '</div></div>' ); 514 579 printf( 515 580 '<input type="button" class="upload-image-button button" value="%s" onclick="MonLabo.imageMediaMenu(\'%s\', \'%s\', \'image-preview\', \'image_attachment_id\');" />', … … 522 587 $args['settings_group'] . '[' . $args['option_name'] . ']', 523 588 strval( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ), 524 "image_attachment_id"525 ); 526 return $this; 527 } 528 529 /** 530 * Display a color picker form field589 'image_attachment_id' 590 ); 591 return $this; 592 } 593 594 /** 595 * Render a color picker field. 531 596 * Called with "add_field( 'color_picker' ... " 532 597 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 535 600 * - $args['description'] : Description to display 536 601 * - $args['disable'] : true if disabled form 537 * @return Options_Forms_View self For method chaining.602 * @return Options_Forms_View Returns self for method chaining. 538 603 */ 539 604 public function color_picker_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 557 622 558 623 /** 559 * Display a text area form field624 * Render a textarea field. 560 625 * Called with "add_field( 'text_area' ... " 561 626 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 564 629 * - $args['description'] : Description to display 565 630 * - $args['disable'] : true if disabled form 566 * @return Options_Forms_View self For method chaining.631 * @return Options_Forms_View Returns self for method chaining. 567 632 */ 568 633 public function text_area_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 584 649 585 650 /** 586 * Display a button for empty cache651 * Render a button to clear cache. 587 652 * Called with "add_field( 'text_area' ... " 588 653 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 591 656 * - $args['description'] : Description to display 592 657 * - $args['disable'] : true if disabled form 593 * @return Options_Forms_View For method chaining.658 * @return Options_Forms_View Returns self for method chaining. 594 659 */ 595 660 public function button_clear_cache_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 599 664 600 665 $webservice = new Contact_Webservices(); 601 $options = get_option( $args['settings_group'] );666 $options = get_option( $args['settings_group'] ); 602 667 if ( ! empty( $options[ $args['option_name'] ] ) ) { 603 668 $webservice->clear_transients(); 604 echo( '<strong>' . __( 'Cache emptied!', 'mon-laboratoire' ) . '</strong>' );669 echo( '<strong>' . __( 'Cache emptied!', 'mon-laboratoire' ) . '</strong>' ); 605 670 unset( $options[ $args['option_name'] ] ); 606 update_option( $args['settings_group'] , $options );607 // Hide counter of cache without need to reload page 671 update_option( $args['settings_group'], $options ); 672 // Hide counter of cache without need to reload page. 608 673 echo( '<script>' 609 674 . 'document.addEventListener("DOMContentLoaded", function() {' … … 616 681 } 617 682 $transient_count = $webservice->number_of_transient_entries(); 618 619 $hide_class = ''; 620 if ( 0 === $transient_count ) { 621 $hide_class = 'MonLabo_hide'; 622 } 683 $hide_class = ( 0 === $transient_count ) ? 'MonLabo_hide' : ''; 684 623 685 echo( $this->_forms_view->submit_button( 624 686 __( 'Clear publications cache', 'mon-laboratoire' ), … … 630 692 $hide_class 631 693 )); 632 echo( ' ' . $transient_count . ' ' . wp_kses_post( $args['description'] ) ); 633 echo $this->_forms_view->hidden_field( $args['settings_group'] . '[' . $args['option_name'] . ']', "", $args['option_name'] . '_trigger' ); 634 return $this; 635 } 636 637 /** 638 * Display a form for testing sending email 694 echo( ' ' . strval( $transient_count ) . ' ' . wp_kses_post( $args['description'] ) ); 695 echo( $this->_forms_view->hidden_field( 696 $args['settings_group'] . '[' . $args['option_name'] . ']', 697 '', 698 $args['option_name'] . '_trigger' 699 ) ); 700 return $this; 701 } 702 703 /** 704 * Render a test email sending form. 639 705 * Called with "add_field( 'text_area' ... " 640 706 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 644 710 * - $args['disable'] : true if disabled form 645 711 * - $args['hide'] : true if CSS display is hide 646 * @return Options_Forms_View For method chaining.712 * @return Options_Forms_View Returns self for method chaining. 647 713 */ 648 714 public function button_test_send_email_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 650 716 return $this->hidden_generic_render( $args ); 651 717 } 652 $hideclass = ( isset( $args['hide']) && $args['hide'] === true) ? ' MonLabo_hide' : '';653 echo( '<div class="MonLabo_test_send_email' . $hideclass. '">');718 $hideclass = ( isset( $args['hide'] ) && true === $args['hide'] ) ? ' MonLabo_hide' : ''; 719 echo( '<div class="MonLabo_test_send_email' . esc_attr( $hideclass ) . '">'); 654 720 $options = get_option( $args['settings_group'] ); 655 721 if ( ! empty( $options[ $args['option_name'] ] ) ) { 656 $to = $options['MonLabo_data_privacy_test_email'];722 $to = $options['MonLabo_data_privacy_test_email']; 657 723 $subject = '[Test Mail from plugin Mon-Laboratoire of "' . get_bloginfo( 'name' ) . '"]'; 658 724 $content = 'Success!!'; 659 725 echo( '<strong>' ); 660 if ( ( ! filter_var( $to, FILTER_VALIDATE_EMAIL ) ) || ! wp_mail( $to, $subject, $content ) ) { 661 echo( '<p>'. __( 'ERROR : The email could not be sent. Possible reason: your host may have disabled the PHP mail function.', 'mon-laboratoire' ) . '</p>'); 662 echo( '<p>'. __( 'Possible solution : Try to install a plugin for reconfiguring wp_mail() function like WP Mail SMTP.', 'mon-laboratoire' ) . ' <a href="https://wordpress.org/plugins/wp-mail-smtp/">WP Mail SMTP plugin page<a></a></p>'); 726 if ( ! filter_var( $to, FILTER_VALIDATE_EMAIL ) || ! wp_mail( $to, $subject, $content ) ) { 727 echo( '<p>' . __( 'ERROR : The email could not be sent. Possible reason: your host may have disabled the PHP mail function.', 'mon-laboratoire' ) . '</p>' ); 728 echo( '<p>' . __( 'Possible solution : Try to install a plugin for reconfiguring wp_mail() function like WP Mail SMTP.', 'mon-laboratoire' ) ); 729 echo( ' <a href="https://wordpress.org/plugins/wp-mail-smtp/">WP Mail SMTP plugin page<a></a></p>' ); 663 730 } else { 664 printf( __( 'Mail sent to %s.', 'mon-laboratoire' ) , $to);731 printf( __( 'Mail sent to %s.', 'mon-laboratoire' ) , esc_html( $to ) ); 665 732 } 666 733 echo( '</strong> ' ); 667 734 unset( $options[ $args['option_name'] ] ); 668 update_option( $args['settings_group'] , $options );735 update_option( $args['settings_group'], $options ); 669 736 } 670 737 echo( $this->_forms_view->submit_button( 671 __( 'Send test email', 'mon-laboratoire' ) ,738 __( 'Send test email', 'mon-laboratoire' ), 672 739 $args['option_name'] . '_button', 673 740 'MonLabo.fillTriggerAndSubmit(\'' . esc_js( $args['option_name'] ) . '_trigger\')', … … 676 743 'button_' . $args['settings_group'] . '[' . $args['option_name'] . ']', 677 744 '' 678 ) );745 ) ); 679 746 echo( wp_kses_post( $args['description'] ) . '</div>' ); 680 echo $this->_forms_view->hidden_field( $args['settings_group'] . '[' . $args['option_name'] . ']', "", $args['option_name'] . '_trigger' ); 681 return $this; 682 } 683 684 /** 685 * Display a button for create default parent page 747 echo( $this->_forms_view->hidden_field( 748 $args['settings_group'] . '[' . $args['option_name'] . ']', 749 '', 750 $args['option_name'] . '_trigger' 751 ) ); 752 return $this; 753 } 754 755 /** 756 * Render a button to create default parent page. 686 757 * Called with "add_field( 'text_area' ... " 687 758 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 690 761 * - $args['description'] : Description to display 691 762 * - $args['disable'] : true if disabled form 692 * @return Options_Forms_View For method chaining.763 * @return Options_Forms_View Returns self for method chaining. 693 764 */ 694 765 public function button_create_default_parent_page_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 700 771 701 772 if ( ! empty( $options[ $args['option_name'] ] ) ) { 702 switch ( $args['option_name'] ) { 703 case 'MonLabo_do_create_perso_page_parent': 704 $page = new Wordpress_Page( 'person_parent' ); 705 $options['MonLabo_perso_page_parent'] = $page->get_post_id(); 706 break; 707 case 'MonLabo_do_create_team_page_parent': 708 $page = new Wordpress_Page( 'team_parent' ); 709 $options['MonLabo_team_page_parent'] = $page->get_post_id(); 710 break; 711 case 'MonLabo_do_create_thematic_page_parent': 712 $page = new Wordpress_Page( 'thematic_parent' ); 713 $options['MonLabo_thematic_page_parent'] = $page->get_post_id(); 714 break; 715 case 'MonLabo_do_create_unit_page_parent': 716 $page = new Wordpress_Page( 'unit_parent' ); 717 $options['MonLabo_unit_page_parent'] = $page->get_post_id(); 718 break; 719 } 720 721 echo( '<strong>'. __( 'Page created!' , 'mon-laboratoire' ) . ' </strong>' ); 773 $this->_create_parent_page( $args['option_name'], $options ); 774 775 echo( '<strong>' . __( 'Page created!', 'mon-laboratoire' ) . '</strong>' ); 722 776 $options[ $args['option_name'] ] = ''; 723 update_option( $args['settings_group'] , $options );724 echo( '<script type="text/javascript">'725 . 'setTimeout(function() {'777 update_option( $args['settings_group'], $options ); 778 echo( '<script type="text/javascript">' 779 . 'setTimeout(function() {' 726 780 . 'window.location.reload(1); ' // Force reload page 727 781 . '}, 500);' 728 . '</script>' );782 . '</script>' ); 729 783 } 730 784 731 785 echo( $this->_forms_view->submit_button( 732 $args['description'], 'submit_' . $args['option_name'], 786 $args['description'], 787 'submit_' . $args['option_name'], 733 788 'MonLabo.fillTriggerAndSubmit(\'' . esc_js( $args['option_name'] ) . '_trigger\')', 734 '', 'primary', 'button_' . $args['settings_group'] . '[' . $args['option_name'] . ']', '', 789 '', 790 'primary', 791 'button_' . $args['settings_group'] . '[' . $args['option_name'] . ']', 792 '', 735 793 $args['disable'] 736 794 ) ); 737 echo $this->_forms_view->hidden_field( $args['settings_group'] . '[' . $args['option_name'] . ']', "", $args['option_name'] . '_trigger' ); 738 return $this; 739 } 740 741 /** 742 * Display a checkbox form field 795 echo $this->_forms_view->hidden_field( $args['settings_group'] . '[' . $args['option_name'] . ']', '', $args['option_name'] . '_trigger' ); 796 return $this; 797 } 798 799 /** 800 * Create parent page based on option name. 801 * 802 * @param string $option_name Name of the option. 803 * @param array<string,string> &$options Reference to options array. 804 * @return void 805 * @access private 806 */ 807 private function _create_parent_page( string $option_name, array &$options ) { 808 $page_mappings = array( 809 'MonLabo_do_create_perso_page_parent' => array( 'type' => 'person_parent', 'option' => 'MonLabo_perso_page_parent' ), 810 'MonLabo_do_create_team_page_parent' => array( 'type' => 'team_parent', 'option' => 'MonLabo_team_page_parent' ), 811 'MonLabo_do_create_thematic_page_parent' => array( 'type' => 'thematic_parent', 'option' => 'MonLabo_thematic_page_parent' ), 812 'MonLabo_do_create_unit_page_parent' => array( 'type' => 'unit_parent', 'option' => 'MonLabo_unit_page_parent' ), 813 ); 814 815 if ( isset( $page_mappings[ $option_name ] ) ) { 816 $page = new Wordpress_Page( $page_mappings[ $option_name ]['type'] ); 817 $options[ $page_mappings[ $option_name ]['option'] ] = $page->get_post_id(); 818 } 819 } 820 821 /** 822 * Render a checkbox field (style 2). 743 823 * Called with "add_field( 'checkbox2' ... " 744 824 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 748 828 * - $args['disable'] : true if disabled form 749 829 * - $args['hide'] : true if CSS display is hide 750 * @return Options_Forms_View For method chaining.830 * @return Options_Forms_View Returns self for method chaining. 751 831 */ 752 832 public function checkbox2_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 754 834 return $this; 755 835 } 756 $hideclass = ( isset( $args['hide']) && $args['hide'] === true) ? ' MonLabo_hide' : '';757 echo( '<div class="checkbox2 ' . $args['option_name'] . $hideclass. '">' );836 $hideclass = ( isset( $args['hide'] ) && true === $args['hide'] ) ? ' MonLabo_hide' : ''; 837 echo( '<div class="checkbox2 ' . esc_attr( $args['option_name'] . $hideclass ) . '">' ); 758 838 $input_id = uniqid( 'checkbox_' ); 759 $name = esc_attr( $args['settings_group'] . '[' . $args['option_name'] . ']' );760 761 echo( '<input type="checkbox" id="' . esc_attr( $input_id ) . '" name="' . $name. '"' );839 $name = esc_attr( $args['settings_group'] . '[' . $args['option_name'] . ']' ); 840 841 echo( '<input type="checkbox" id="' . esc_attr( $input_id ) . '" name="' . esc_attr( $name ) . '"' ); 762 842 if ( isset( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ) ) { 763 echo( " " . checked( $this->_options[ $args['settings_group'] ][ $args['option_name'] ], '1' , false ));843 checked( $this->_options[ $args['settings_group'] ][ $args['option_name'] ], '1', true ); 764 844 } 765 845 echo( ' value="1">' ); 766 846 echo( '<label for="' . esc_attr( $input_id ) . '"><span class="ui"> </span></label>' ); 767 847 echo( '<p class="description_checkbox2">' ); 768 echo( $args['description']);848 echo( wp_kses_post( $args['description'] ) ); 769 849 echo( '</p></div>' ); 770 850 return $this; 771 851 } 772 773 /** 774 * Display a checkbox form field852 853 /** 854 * Render a checkbox field. 775 855 * Called with "add_field( 'checkbox' ... " 776 856 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 779 859 * - $args['description'] : Description to display 780 860 * - $args['disable'] : true if disabled form 781 * @return Options_Forms_View For method chaining.861 * @return Options_Forms_View Returns self for method chaining. 782 862 */ 783 863 public function checkbox_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 787 867 echo( '<div class="checkbox">' ); 788 868 $input_id = uniqid( 'checkbox_' ); 789 $name = esc_attr( $args['settings_group'] . '[' . $args['option_name'] . ']' );790 791 echo( '<input type="checkbox" id="' . esc_attr( $input_id ) . '" name="' . $name. '"' );869 $name = esc_attr( $args['settings_group'] . '[' . $args['option_name'] . ']' ); 870 871 echo( '<input type="checkbox" id="' . esc_attr( $input_id ) . '" name="' . esc_attr( $name ) . '"' ); 792 872 if ( isset( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ) ) { 793 echo( " " . checked( $this->_options[ $args['settings_group'] ][ $args['option_name'] ], '1' , false ));873 checked( $this->_options[ $args['settings_group'] ][ $args['option_name'] ], '1', true ); 794 874 } 795 875 echo( ' value="1">' ); 796 876 echo( '<label for="' . esc_attr( $input_id ) . '"><span class="ui"> </span></label>' ); 797 877 echo( '<p class="description_checkbox">' ); 798 echo( $args['description']);878 echo( wp_kses_post( $args['description'] ) ); 799 879 echo( '</p></div>' ); 800 880 return $this; … … 802 882 803 883 /** 804 * Display a hidden order to execute884 * Render a hidden order field. 805 885 * Called with "add_field( 'hidden_order' ... " 806 886 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 808 888 * - $args['option_name'] : Name of option to update 809 889 * - $args['disable'] : true if disabled form 810 * @return Options_Forms_View For method chaining.890 * @return Options_Forms_View Returns self for method chaining. 811 891 */ 812 892 public function hidden_order_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 814 894 $this->hidden_generic_render( $args ); 815 895 } else { 816 /*817 ---- No more necessary, cash erase has been moved to a specialized page ----818 if ( isset( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] )819 && ( !empty( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ) )820 ) {821 if ( 'MonLabo_ask_erase_cache_after_cfg' === $args['option_name'] ) {822 $webservice = new Contact_Webservices();823 $webservice->clear_transients();824 unset( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] );825 update_option( $args['settings_group'], $this->_options[ $args['settings_group'] ] );826 }827 }*/828 896 echo $this->_forms_view->hidden_field( $args['settings_group'] . '[' . $args['option_name'] . ']', "1" ); 829 897 } … … 832 900 833 901 /** 834 * Display a number form field902 * Render a number input field. 835 903 * Called with "add_field( 'number' ... " 836 904 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 839 907 * - $args['description'] : Description to display 840 908 * - $args['disable'] : true if disabled form 841 * @return Options_Forms_View For method chaining.909 * @return Options_Forms_View Returns self for method chaining. 842 910 */ 843 911 public function number_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 855 923 856 924 /** 857 * Display a page choice form field925 * Render a page selector field. 858 926 * Called with "add_field( 'page' ... " 859 927 * @param array{option_name:string,description:string,settings_group:string,disable:bool,hide:bool,class:string} $args Parameters : … … 862 930 * - $args['description'] : Description to display 863 931 * - $args['disable'] : true if disabled form 864 * @return Options_Forms_View For method chaining.932 * @return Options_Forms_View Returns self for method chaining. 865 933 */ 866 934 public function select_page_generic_render( array $args ): self { // @phan-suppress-current-line PhanUnreferencedPublicMethod … … 869 937 } 870 938 871 // Convert Option name to number in order to be used by multi-pages functions939 // Convert option name to number in order to be used by multi-pages functions. 872 940 $name_to_number = array( 873 'MonLabo_perso_page_parent' => 1,874 'MonLabo_team_page_parent' => 2,875 'MonLabo_thematic_page_parent' => 3,876 'MonLabo_unit_page_parent' => 4,941 'MonLabo_perso_page_parent' => 1, 942 'MonLabo_team_page_parent' => 2, 943 'MonLabo_thematic_page_parent' => 3, 944 'MonLabo_unit_page_parent' => 4, 877 945 ); 878 946 if ( ! array_key_exists( $args['option_name'], $name_to_number ) ) { 879 947 return $this; 880 948 } 881 $retval = ''; 882 $pages_published = get_pages( ); 949 $pages_published = get_pages(); 883 950 884 951 if ( ! empty( $pages_published ) ) { 885 // Initial values886 $name = $args['settings_group'] . '[' . $args['option_name'] . ']';887 $initial_value = strval( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] );952 // Initial values. 953 $name = $args['settings_group'] . '[' . $args['option_name'] . ']'; 954 $initial_value = strval( $this->_options[ $args['settings_group'] ][ $args['option_name'] ] ); 888 955 $multipost_forms_view = new Wp_Post_Forms_View(); 889 echo $multipost_forms_view->page_selector( $name, true, '', '', $initial_value, 0, 1, false ); 890 $nbpage = $name_to_number[ $args['option_name'] ] ; 891 $retval .= '<div id="delayedLoadDivThumbnail_' . strval( $nbpage ) . '" class="delayedLoadDivThumbnail"><!-- Nous allons afficher ici la suite en asynchone grâce à ajax. --></div>' . "\n"; 892 } 893 894 echo $retval; 895 return $this; 896 } 897 956 echo( $multipost_forms_view->page_selector( $name, true, '', '', $initial_value, 0, 1, false ) ); 957 $nbpage = $name_to_number[ $args['option_name'] ]; 958 printf( 959 '<div id="delayedLoadDivThumbnail_%d" class="delayedLoadDivThumbnail"><!-- Nous allons afficher ici la suite en asynchone grâce à ajax. --></div>' . "\n", 960 intval( $nbpage ) 961 ); 962 } 963 964 return $this; 965 } 898 966 } 899 967 ?> -
mon-laboratoire/trunk/Admin/Forms/class-wp-post-forms-view.php
r3361909 r3369834 5 5 use MonLabo\Lib\Access_Data\{Access_Data}; 6 6 use MonLabo\Admin\Wordpress_Page; 7 use MonLabo\Frontend\ {Person_Or_Structure_View};7 use MonLabo\Frontend\Person_Or_Structure_View; 8 8 use MonLabo\Lib\Person_Or_Structure\Person_Or_Structure; 9 9 … … 11 11 12 12 /** 13 * Class \MonLabo\Admin\Wp_Post_Forms_View 14 * Handles the generation of HTML form elements and controls for WordPress pages 13 * Class \MonLabo\Admin\Forms\Wp_Post_Forms_View 14 * 15 * Handles the generation of HTML form elements for WordPress page management. 15 16 * 16 * Methods : 17 * _page_radio_buttons( $page_number, $name, $description, $initial_value, $type ) 18 * _default_hidden_zone( $text, $css_id ) 19 * _input_wp_post_id_or_url( $is_mandatory, $legend, $name, $description, $initial_value, $page_number) 20 * _input_person_wp_post_id_or_url( $is_mandatory, $legend, $name, $description, $initial_value, $page_number) 21 * _dropdown_pages( string $name, string $wp_post_id) 22 * _page_thumbnail( $wp_post_id, $page_number ) 23 * _tell_if_page_is_already_attributed( $type, $item_id, $wp_post_id ) 24 * person_multi_post_addr_field( $is_mandatory,$legend, $name, $description, $initial_value , $css_id) 25 * multi_post_addr_field( $is_mandatory,$legend, $name, $description, $initial_value , $css_id) 26 * page_selector( $name, $is_mandatory, $legend,$description, $initial_value, $child_of, $depth, $show_drafts) 27 * update_page_infobox( $item_id, $page_number, $wp_post_id, $type ) 17 * This class extends Generic_Forms_View to provide specialized form controls 18 * for managing WordPress pages associated with persons, teams, thematics, 19 * and units. It includes methods for creating page selectors, thumbnails, 20 * radio button controls, and multi-page field management. 21 * 22 * Methods: 23 * _default_hidden_zone( string $text, string $css_id ) 24 * _page_radio_buttons( int $page_number, string $name, string $description, 25 * string $initial_value, string $type ) 26 * _determine_initial_radio_state( string $initial_value, string $type ) 27 * _render_radio_buttons( int $page_number, string $radio_init ) 28 * _input_person_wp_post_id_or_url( bool $is_mandatory, string $legend, string $name, 29 * string $description, string $initial_value, int $page_number ) 30 * _input_wp_post_id_or_url( bool $is_mandatory, string $legend, string $name, 31 * string $description, string $initial_value, int $page_number ) 32 * _page_thumbnail( int $wp_post_id, int $page_number ) 33 * _dropdown_pages( string $name, string $wp_post_id ) 34 * _tell_if_page_is_already_attributed( string $type, int $item_id, $wp_post_id ) 35 * person_multi_post_addr_field( bool $is_mandatory, string $legend, string $name, 36 * string $description, $initial_value, string $css_id ) 37 * multi_post_addr_field( bool $is_mandatory, string $legend, string $name, 38 * string $description, $initial_value, string $css_id ) 39 * page_selector( string $name, bool $is_mandatory, string $legend, string $description, 40 * string $initial_value, int $child_of, int $depth, bool $show_drafts ) 41 * _generate_page_dropdown( string $name, string $initial_value, array $pages_published, 42 * array $pages_draft, int $depth, bool $show_drafts ): 43 * update_page_infobox( $item_id, int $page_number, $wp_post_id, string $type ) 44 * _generate_page_infobox_content( string $wp_post_id, int $page_number, $item_id, string $type ): string 45 * _generate_page_info_for_numeric_id( int $wp_post_id, int $page_number, $item_id, string $type ): string 46 * _generate_page_info_for_url( string $wp_post_id ) 28 47 * 29 48 * @package MonLabo\Admin\Forms 30 */49 */ 31 50 class Wp_Post_Forms_View extends Generic_Forms_View { 32 51 33 52 /** 34 * Generates hidden zone with default content. 35 * @param string $text id of the person 36 * @param string $css_id CSS ID of the showing button 37 * @return string HTML code 38 * @access private 39 */ 40 private function _default_hidden_zone( 41 string $text, 42 string $css_id = '' 43 ): string { 53 * Generates a hidden HTML zone with default content. 54 * 55 * Creates a div element that is initially hidden and can be shown 56 * dynamically via JavaScript interactions. 57 * 58 * @param string $text Content to be placed in the hidden zone. 59 * @param string $css_id HTML ID attribute for the div element. Default ''. 60 * @return string Generated HTML for the hidden zone. 61 * @access private 62 */ 63 private function _default_hidden_zone( string $text, string $css_id = '' ): string { 44 64 return sprintf( 45 65 '<div id="%1$s" style="display:none;">%2$s</div>', … … 50 70 51 71 /** 52 * Generate an HTML code radio buttons for managing pages of Persons, Teams, Thematics or Units 53 * @param int $page_number 54 * @param string $name name of the form field 55 * @param string $description text that is displayed after the field 56 * @param string $initial_value initial value 57 * @return string HTML code of form field 58 * @param string $type of page 'person', 'team', 'thematic' or 'unit' 59 * @access private 60 */ 72 * Generates radio button controls for page management. 73 * 74 * Creates a set of radio buttons for creating, choosing, editing, 75 * or removing page associations for persons, teams, thematics, or units. 76 * 77 * @param int $page_number Index of the page field (for multiple pages). 78 * @param string $name Field name attribute. 79 * @param string $description Description text displayed with the radio buttons. 80 * @param string $initial_value Initial page ID or URL value. 81 * @param string $type Entity type: 'person', 'team', 'thematic' or 'unit'. 82 * @return string Generated HTML for the radio button controls. 83 * @access private 84 */ 61 85 private function _page_radio_buttons( 62 86 int $page_number, … … 65 89 string $initial_value, 66 90 string $type 67 ) : string { 68 $radio_name = sprintf( 'pageradio[%d]', $page_number ); 69 $radio_id = sprintf( 'pageradio%d_', $page_number ); 70 $output = sprintf( 91 ): string { 92 $output = sprintf( 71 93 '<div class="input-group MonLabo-wpPostId"><label for="submit_%1$s" class="radiobutton-label">%2$s :</label>', 72 94 esc_attr( $name ), … … 74 96 ); 75 97 76 $radio_init = 'edit'; 77 $supl_choose_test = true; 78 98 // Determine initial radio button state. 99 $radio_init = $this->_determine_initial_radio_state( $initial_value, $type ); 100 101 // Generate radio buttons. 102 $output .= '<div class="radiobuttons input-group">'; 103 $output .= $this->_render_radio_buttons( $page_number, $radio_init ); 104 $output .= '</div>'; 105 return $output; 106 } 107 108 /** 109 * Determines the initial state for radio buttons. 110 * 111 * @param string $initial_value Initial page ID or URL. 112 * @param string $type Entity type. 113 * @return string Radio button state: 'new', 'choose', 'edit', or 'none'. 114 * @access private 115 */ 116 private function _determine_initial_radio_state( string $initial_value, string $type ): string { 117 if ( '' === $initial_value ) { 118 return 'none'; 119 } 120 if ( ! is_numeric( $initial_value ) || ! get_post( intval( $initial_value ) ) ) { 121 return 'edit'; 122 } 123 // Additional check for person pages. 79 124 if ( 'person' === $type ) { 80 125 $page = new Wordpress_Page( 'from_id', $initial_value ); 81 $supl_choose_test = $page->is_a_person_page(); 82 } 83 84 if ( is_numeric( $initial_value ) && 85 get_post( intval( $initial_value ) ) && 86 $supl_choose_test 87 ) { //Si la page existe et est une page de personne 88 $radio_init = 'choose'; 89 } 90 if ( '' === $initial_value ) { 91 $radio_init = 'none'; 92 } 93 94 $radio_buttons = array( 95 'A' => array( 'value' => 'new', 'label' => __( 'Create', 'mon-laboratoire' ), 'dashicon' => 'plus-alt2', 'class' => 'roundleft' ), 96 'B' => array( 'value' => 'choose', 'label' => __( 'Choose', 'mon-laboratoire' ), 'dashicon' => 'arrow-down-alt2' ), 97 'C' => array( 'value' => 'edit', 'label' => __( 'Edit', 'mon-laboratoire' ), 'dashicon' => 'admin-customizer' ), 98 'D' => array( 'value' => 'none', 'label' => _x( 'None', 'page', 'mon-laboratoire' ), 'dashicon' => 'no-alt', 'class' => 'roundright' ), 99 ); 100 $output .= '<div class="radiobuttons input-group">'; 101 foreach ( $radio_buttons as $key => $button ) { 126 if ( ! $page->is_a_person_page() ) { 127 return 'edit'; 128 } 129 } 130 return 'choose'; 131 } 132 133 /** 134 * Renders radio buttons HTML. 135 * 136 * @param int $page_number Page number for JavaScript. 137 * @param string $radio_init Initially checked value. 138 * @return string Generated HTML for radio buttons. 139 * @access private 140 */ 141 private function _render_radio_buttons( int $page_number, string $radio_init ): string { 142 $buttons = array( 143 'A' => array( 'value' => 'new', 'label' => __( 'Create', 'mon-laboratoire' ), 'dashicon' => 'plus-alt2', 'class' => 'roundleft' ), 144 'B' => array( 'value' => 'choose', 'label' => __( 'Choose', 'mon-laboratoire' ), 'dashicon' => 'arrow-down-alt2' ), 145 'C' => array( 'value' => 'edit', 'label' => __( 'Edit', 'mon-laboratoire' ), 'dashicon' => 'admin-customizer' ), 146 'D' => array( 'value' => 'none', 'label' => _x( 'None', 'page', 'mon-laboratoire' ), 'dashicon' => 'no-alt', 'class' => 'roundright' ), 147 ); 148 $radio_name = sprintf( 'pageradio[%d]', $page_number ); 149 $radio_id = sprintf( 'pageradio%d_', $page_number ); 150 151 $output = ''; 152 foreach ( $buttons as $key => $button ) { 153 // Generate radio input. 102 154 $output .= sprintf( 103 155 '<input type="radio" id="%1$s" name="%2$s" value="%3$s" onclick="MonLabo.pageButtonClick(\'%3$s\', \'%4$d\')" %5$s>', 104 156 esc_attr( $radio_id . $key ), 105 esc_attr( $radio_name ),157 $radio_name, 106 158 esc_attr( $button['value'] ), 107 159 $page_number, 108 160 checked( $radio_init, $button['value'], false ) 109 161 ); 162 // Generate label. 163 $label_class = ! empty( $button['class'] ) ? sprintf( ' class="%s"', esc_attr( $button['class'] ) ) : ''; 110 164 $output .= sprintf( 111 165 '<label for="%1$s"%2$s>%3$s %4$s</label>', 112 166 esc_attr( $radio_id . $key ), 113 ! empty( $button['class'] ) ? sprintf( ' class="%s"', esc_attr( $button['class'] ) ) : '',167 $label_class, 114 168 esc_html( $button['label'] ), 115 169 $this->_html->dashicon( $button['dashicon'] ) 116 170 ); 117 171 } 118 $output .= '</div>'; 119 return $output; 120 } 121 122 123 /** 124 * Generate an HTML code for an input of wp_post_id or a URL 125 * @param bool $is_mandatory if true, fill this field is mandatory. 126 * @param string $legend text that is displayed just before the field 127 * @param string $name name of the form field 128 * @param string $description text that is displayed after the field 129 * @param string $initial_value initial value 130 * @param int $page_number 131 * @return string HTML code of form field 172 return $output; 173 } 174 175 /** 176 * Generates input field for person WordPress post ID or URL. 177 * 178 * Creates a specialized input field for person pages with parent page 179 * selection from plugin settings. 180 * 181 * @param bool $is_mandatory Whether the field is required. 182 * @param string $legend Label text for the field. 183 * @param string $name Field name attribute. 184 * @param string $description Description text. 185 * @param string $initial_value Initial page ID or URL. Default NO_PAGE_OPTION_VALUE. 186 * @param int $page_number Index for multiple page fields. Default 0. 187 * @return string Generated HTML for the input field. 132 188 * @access private 133 189 */ … … 141 197 ): string { 142 198 $options10 = get_option( 'MonLabo_settings_group10' ); 199 200 // Generate radio buttons. 143 201 $output = $this->_page_radio_buttons( $page_number, $name, $description, $initial_value, 'person' ); 144 202 $output .= '<div class="input-group-addon">'; 203 204 // Add page selector if parent page is configured. 145 205 if ( isset( $options10['MonLabo_perso_page_parent'] ) ) { 206 $parent_id = intval( $options10['MonLabo_perso_page_parent'] ); 146 207 $output .= $this->_default_hidden_zone( 147 $this->page_selector( "dropdown_$name", true, '', '', $initial_value, intval( $options10['MonLabo_perso_page_parent'] )),208 $this->page_selector( "dropdown_$name", true, '', '', $initial_value, $parent_id ), 148 209 sprintf( 'hidd_drop_wp_post_ids_%d', $page_number ) 149 210 ); 150 211 } 151 212 $output .= '</div>'; 213 // Add text input field. 152 214 $output .= $this->_large_text_field( $is_mandatory, $legend, $name, '', $initial_value, sprintf( 'submit_wp_post_ids_%d', $page_number ) ); 215 // Add thumbnail container. 153 216 $output .= sprintf( 154 217 '<div id="delayedLoadDivThumbnail_%1$d" class="delayedLoadDivThumbnail"><!-- Asynchronous ajax content will be loaded here --></div></div>', … … 158 221 } 159 222 160 161 /** 162 * Generate an HTML code for an input of Wp_post_id or a URL 163 * @param bool $is_mandatory if true, fill this field is mandatory. 164 * @param string $legend text that is displayed just before the field 165 * @param string $name name of the form field 166 * @param string $description text that is displayed after the field 167 * @param string $initial_value initial value 168 * @param int $page_number 169 * @return string HTML code of form field 223 /** 224 * Generates input field for WordPress post ID or URL. 225 * 226 * Creates a general input field for page selection with dropdown 227 * for all available pages. 228 * 229 * @param bool $is_mandatory Whether the field is required. 230 * @param string $legend Label text for the field. 231 * @param string $name Field name attribute. 232 * @param string $description Description text. 233 * @param string $initial_value Initial page ID or URL. Default NO_PAGE_OPTION_VALUE. 234 * @param int $page_number Index for multiple page fields. Default 0. 235 * @return string Generated HTML for the input field. 170 236 * @access private 171 237 */ … … 178 244 int $page_number = 0 179 245 ): string { 246 // Generate radio buttons. 180 247 $output = $this->_page_radio_buttons( $page_number, $name, $description, $initial_value, 'item' ); 181 248 $output .= '<div class="input-group-addon">'; 249 250 // Add dropdown page selector. 182 251 $output .= $this->_default_hidden_zone( 183 $this->_dropdown_pages( 'dropdown_' . $name, $initial_value ),184 sprintf( 'hidd_drop_wp_post_ids_%d', $page_number )185 );252 $this->_dropdown_pages( 'dropdown_' . $name, $initial_value ), 253 sprintf( 'hidd_drop_wp_post_ids_%d', $page_number ) 254 ); 186 255 $output .= '</div>'; 256 257 // Add text input field. 187 258 $output .= $this->_large_text_field( $is_mandatory, $legend, $name, '', $initial_value, sprintf( 'submit_wp_post_ids_%d', $page_number ) ); 259 260 // Add thumbnail container. 188 261 $output .= sprintf( 189 262 '<div id="delayedLoadDivThumbnail_%1$d" class="delayedLoadDivThumbnail"><!-- Asynchronous ajax content will be loaded here --></div></div>', 190 263 $page_number 191 264 ); 192 return $output; 193 } 194 195 /** 196 * Generate an HTML code for a thumbnail of a page of a person 197 * @param int $wp_post_id ID of the post to display thumbnail 198 * @param int $page_number number of the page (persons can have several pages) 199 * @return string HTML code 265 266 return $output; 267 } 268 269 /** 270 * Generates HTML for a page thumbnail. 271 * 272 * Creates a thumbnail preview for a WordPress post/page if it has 273 * a featured image set. 274 * 275 * @param int $wp_post_id WordPress post/page ID. 276 * @param int $page_number Index for multiple page fields. 277 * @return string Generated HTML for the thumbnail. 278 * @access private 200 279 */ 201 280 private function _page_thumbnail( int $wp_post_id, int $page_number ): string { 202 281 $output = '<a class="hover-zoom-square30-no-border">'; 282 203 283 if ( $wp_post_id > 0 && has_post_thumbnail( $wp_post_id ) ) { 204 284 $thumbnail = get_the_post_thumbnail( 205 285 $wp_post_id, 206 286 array( 150, 150 ), 207 array( 'class' => '', 'id' => 'image-preview_' . $page_number )287 array( 'class' => '', 'id' => 'image-preview_' . $page_number ) 208 288 ); 209 return $output . $thumbnail . '</a>'; 210 } 211 return $output . '</a>'; 212 } 213 214 /** 215 * Generate an HTML code for a selecting a page 216 * @param string $name name of the form field 217 * @param string $wp_post_id id of page selected 218 * @return string HTML code of form field 219 * @access private 220 */ 221 private function _dropdown_pages( string $name, string $wp_post_id): string { 289 $output .= $thumbnail; 290 } 291 292 $output .= '</a>'; 293 294 return $output; 295 } 296 297 /** 298 * Generates a dropdown selector for WordPress pages. 299 * 300 * Creates a select element populated with all available WordPress pages. 301 * 302 * @param string $name Field name attribute. 303 * @param string $wp_post_id Currently selected page ID. 304 * @return string Generated HTML for the dropdown. 305 * @access private 306 */ 307 private function _dropdown_pages( string $name, string $wp_post_id ): string { 222 308 return wp_dropdown_pages( 223 309 array( 224 'name' => $name,225 'echo' => 0,310 'name' => $name, 311 'echo' => 0, 226 312 'show_option_none' => '—' . __( 'Select', 'mon-laboratoire' ) . '—', 227 313 'option_none_value' => '0', 228 'selected' => is_numeric( $wp_post_id ) ? intval( $wp_post_id ) : '',314 'selected' => is_numeric( $wp_post_id ) ? intval( $wp_post_id ) : '', 229 315 ) 230 316 ); … … 232 318 233 319 /** 234 * Checks and indicates if a page is already attributed to other items. 235 * @param string $type of page 'person', 'team', 'thematic' or 'unit' 236 * @param int $item_id id of the item (person or stucture ID) 237 * @param string|int|null $wp_post_id Page ID to test 238 * @return string HTML message about page attribution. 320 * Checks if a page is already attributed to other items. 321 * 322 * Verifies if a WordPress page is already assigned to other persons, 323 * teams, thematics, or units and generates a warning message. 324 * 325 * @param string $type Entity type: 'person', 'team', 'thematic' or 'unit'. 326 * @param int $item_id Current item ID. 327 * @param string|int|null $wp_post_id WordPress page ID to check. 328 * @return string HTML message about page attribution conflicts. 329 * @access private 239 330 */ 240 331 private function _tell_if_page_is_already_attributed( … … 242 333 int $item_id, 243 334 $wp_post_id 244 //$alternate_image = ''245 335 ): string { 246 336 if ( empty( $wp_post_id ) ) { … … 249 339 $access_data = new Access_Data(); 250 340 $other_items = array(); 251 $ output = '';252 $ page_types = array( 'person', 'team', 'thematic', 'unit');253 $item_view = new Person_Or_Structure_View();341 $page_types = array( 'person', 'team', 'thematic', 'unit' ); 342 $item_view = new Person_Or_Structure_View(); 343 // Check all entity types for page usage. 254 344 foreach ( $page_types as $check_type ) { 255 345 $item_class = '\MonLabo\Lib\Person_Or_Structure\\' . ucfirst( $check_type ); 256 346 $page_items = $access_data->get_itemIds_from_wpPostId( $check_type, $wp_post_id ); 257 347 foreach ( $page_items as $key => $value ) { 258 if ( $check_type !== $type || $value !== $item_id ) { 259 $item = new $item_class( 'from_id', $value ); 260 if ( ! $item instanceof Person_Or_Structure ) { 261 wp_trigger_error( __METHOD__, "Object of class '$item_class' cannot be instantiated." ); 262 continue; 263 } 264 $other_items[ $check_type ][ $key ] = $item_view->item_name_with_admin_link( $check_type, $item->info ); 348 // Skip if it's the current item. 349 if ( $check_type === $type && $value === $item_id ) { 350 continue; 265 351 } 352 $item = new $item_class( 'from_id', $value ); 353 if ( ! $item instanceof Person_Or_Structure ) { 354 wp_trigger_error( __METHOD__, "Object of class '$item_class' cannot be instantiated." ); 355 continue; 356 } 357 $other_items[ $check_type ][ $key ] = $item_view->item_name_with_admin_link( $check_type, $item->info ); 266 358 } 267 359 } 268 if ( ! empty( $other_items ) ) { 269 $output .= sprintf( '<br /><strong>%s </strong>', __( 'Attention this page is already assigned to', 'mon-laboratoire' ) ); 270 $item_types = array( 271 'person' => __( 'Person(s):', 'mon-laboratoire' ), 272 'team' => __( 'Team(s):', 'mon-laboratoire' ), 273 'thematic' => __( 'Thematic(s):', 'mon-laboratoire' ), 274 'unit' => __( 'Unit(s):', 'mon-laboratoire' ), 275 ); 276 foreach ( $item_types as $item_type => $label ) { 277 if ( isset( $other_items[ $item_type ] ) ) { 278 $output .= sprintf( '<br />%s %s', esc_html( $label ), wp_kses_post( Lib::secured_implode( ', ', $other_items[ $item_type ] ) ) ); 279 } 360 // Generate warning message if page is used elsewhere. 361 if ( empty( $other_items ) ) { 362 return ''; 363 } 364 $output = sprintf( 365 '<br /><strong>%s </strong>', 366 __( 'Attention this page is already assigned to', 'mon-laboratoire' ) 367 ); 368 $item_labels = array( 369 'person' => __( 'Person(s):', 'mon-laboratoire' ), 370 'team' => __( 'Team(s):', 'mon-laboratoire' ), 371 'thematic' => __( 'Thematic(s):', 'mon-laboratoire' ), 372 'unit' => __( 'Unit(s):', 'mon-laboratoire' ), 373 ); 374 foreach ( $item_labels as $item_type => $label ) { 375 if ( isset( $other_items[ $item_type ] ) ) { 376 $output .= sprintf( '<br />%s %s', esc_html( $label ), wp_kses_post( Lib::secured_implode( ', ', $other_items[ $item_type ] ) ) ); 280 377 } 281 378 } … … 284 381 285 382 /** 286 * Generates person multi-post address field. 287 * @param bool $is_mandatory if true, fill this field is mandatory. 288 * @param string $legend text that is displayed just before the field 289 * @param string $name name of the form field 290 * @param string $general_description text that is displayed after the field 291 * @param string|string[] $initial_value initial value 292 * @param string $css_id CSS id for the <input> tag. 293 * @return string HTML code of form field 383 * Generates multi-page address fields for persons. 384 * 385 * Creates multiple page input fields specifically for person entities, 386 * with special handling for main and additional pages. 387 * 388 * @param bool $is_mandatory Whether at least one page is required. 389 * @param string $legend Label text for the field group. 390 * @param string $name Base field name attribute. 391 * @param string $general_description General description for the field group. 392 * @param string|string[] $initial_value Initial page IDs or URLs. Default empty array. 393 * @param string $css_id CSS ID for the wrapper div. Default ''. 394 * @return string Generated HTML for the multi-page fields. 294 395 * @access public 295 */296 public function person_multi_post_addr_field(396 */ 397 public function person_multi_post_addr_field( 297 398 bool $is_mandatory, 298 399 string $legend, … … 302 403 string $css_id = '' 303 404 ): string { 304 $output = $css_id ? sprintf( '<div class="%s">', esc_attr( $css_id ) ) : ''; 305 $output .= $general_description ? sprintf( '<p>%s</p>', esc_html( $general_description ) ) : ''; 405 // Open wrapper if CSS ID provided. 406 $output = ! empty( $css_id ) ? sprintf( '<div class="%s">', esc_attr( $css_id ) ) : ''; 407 // Add general description if provided. 408 if ( ! empty( $general_description ) ) { 409 $output .= sprintf( '<p>%s</p>', esc_html( $general_description ) ); 410 } 411 // Ensure initial value is array. 306 412 if ( ! is_array( $initial_value ) ) { 307 413 $initial_value = explode( ',', $initial_value ); //Retrocompatibily in case of damaged DB … … 310 416 $initial_value = array( '' ); 311 417 } 418 // Generate existing page fields. 312 419 $count = 0; 313 420 foreach ( $initial_value as $value ) { 314 if ( ! empty( $value ) ) { 315 $output .= $this->_input_person_wp_post_id_or_url( 316 $is_mandatory, 317 '', 318 $name . '[' . $count . ']', 319 $count ? sprintf( __( 'Page %d', 'mon-laboratoire' ), $count + 1 ) : __( 'Main page', 'mon-laboratoire' ), 320 $value, 321 $count 322 ) . '<br />'; 323 $count += 1; 421 if ( empty( $value ) ) { 422 continue; 324 423 } 325 } 326 $description = $count ? __( 'Additional page', 'mon-laboratoire' ) : __( 'Main page', 'mon-laboratoire' ); 327 $output .= $this->_input_person_wp_post_id_or_url( $is_mandatory, $legend, $name . '[' . $count . ']', 328 $description, '', $count ); 329 $output .= $css_id ? '</div>' : ''; 330 return $output; 331 } 332 333 334 /** 335 * Generates multi-post address field. 336 * @param bool $is_mandatory if true, fill this field is mandatory. 337 * @param string $legend text that is displayed just before the field 338 * @param string $name name of the form field 339 * @param string $general_description text that is displayed after the field 340 * @param string|string[] $initial_value initial value 341 * @param string $css_id CSS id for the <input> tag. 342 * @return string HTML code of form field 343 * @access public 344 */ 345 public function multi_post_addr_field( 424 $description = 0 === $count 425 ? __( 'Main page', 'mon-laboratoire' ) 426 : sprintf( __( 'Page %d', 'mon-laboratoire' ), $count + 1 ); 427 $output .= $this->_input_person_wp_post_id_or_url( 428 $is_mandatory, 429 '', 430 $name . '[' . $count . ']', 431 $description, 432 $value, 433 $count 434 ) . '<br />'; 435 $count++; 436 } 437 // Add field for new page. 438 $description = 0 === $count 439 ? __( 'Main page', 'mon-laboratoire' ) 440 : __( 'Additional page', 'mon-laboratoire' ); 441 $output .= $this->_input_person_wp_post_id_or_url( 442 $is_mandatory, 443 $legend, 444 $name . '[' . $count . ']', 445 $description, 446 '', 447 $count 448 ); 449 // Close wrapper if CSS ID provided. 450 if ( ! empty( $css_id ) ) { 451 $output .= '</div>'; 452 } 453 return $output; 454 } 455 456 /** 457 * Generates multi-page address fields for general items. 458 * 459 * Creates multiple page input fields for teams, thematics, and units, 460 * with numbered page labels. 461 * 462 * @param bool $is_mandatory Whether at least one page is required. 463 * @param string $legend Label text for the field group. 464 * @param string $name Base field name attribute. 465 * @param string $general_description General description for the field group. 466 * @param string|string[] $initial_value Initial page IDs or URLs. Default empty array. 467 * @param string $css_id CSS ID for the wrapper div. Default ''. 468 * @return string Generated HTML for the multi-page fields. 469 */ 470 public function multi_post_addr_field( 346 471 bool $is_mandatory, 347 472 string $legend, … … 351 476 string $css_id = '' 352 477 ): string { 353 $output = $css_id ? sprintf( '<div class="%s">', esc_attr( $css_id ) ) : ''; 354 $output .= $general_description ? sprintf( '<p>%s</p>', esc_html( $general_description ) ) : ''; 478 // Open wrapper if CSS ID provided. 479 $output = ! empty( $css_id ) ? sprintf( '<div class="%s">', esc_attr( $css_id ) ) : ''; 480 // Add general description if provided. 481 if ( ! empty( $general_description ) ) { 482 $output .= sprintf( '<p>%s</p>', esc_html( $general_description ) ); 483 } 484 // Ensure initial value is array. 355 485 if ( ! is_array( $initial_value ) ) { 356 486 $initial_value = explode( ',', $initial_value ); //Retrocompatibily in case of damaged DB … … 359 489 $initial_value = array( '' ); 360 490 } 491 // Generate existing page fields. 361 492 $count = 0; 362 493 foreach ( $initial_value as $value ) { 363 if ( ! empty( $value ) ) { 364 $output .= $this->_input_wp_post_id_or_url( 365 $is_mandatory, 366 '', 367 $name . '[' . $count . ']', 368 sprintf( __( 'Page %d', 'mon-laboratoire' ), $count + 1 ), 369 $value, 370 $count 371 ) . '<br />'; 372 $count += 1; 373 } 374 } 375 $description = $count ? __( 'Additional page', 'mon-laboratoire' ) : sprintf( __( 'Page %d', 'mon-laboratoire' ), 1 ); 376 $output .= $this->_input_wp_post_id_or_url( $is_mandatory, $legend, $name . '[' . $count . ']', $description, '', $count ); 377 $output .= $css_id ? '</div>' : ''; 378 return $output; 379 } 380 381 /** 382 * Generate an HTML code for a drop-down list form field of WordPress pages 383 * @param string $name name of the drop-down list 384 * @param bool $is_mandatory if true, select a page is mandatory. 385 * @param string $legend text that is displayed just before the field 386 * @param string $description text that is displayed after the field 387 * @param string $initial_value Pre-select an item of the list 388 * @param int $child_of Displays the sub-pages of a single Page only; uses the ID for a Page as the value. Defaults to 0 (displays all Pages ). 389 * @param int $depth This parameter controls how many levels in the hierarchy of pages are to be included in the list generated by wp_list_pages. The default value is 0 (display all pages, including all sub-pages ). 390 * 0 - Pages and sub-pages displayed in hierarchical ( indented ) form ( Default ). 391 * -1 - Pages in sub-pages displayed in flat (no indent ) form. 392 * 1 - Show only top level Pages 393 * 2 - Value of 2 (or greater) specifies the depth (or level) to descend in displaying Pages. 394 * @param bool $show_drafts if true, show draft pages 395 * @return string HTML code 494 if ( empty( $value ) ) { 495 continue; 496 } 497 $output .= $this->_input_wp_post_id_or_url( 498 $is_mandatory, 499 '', 500 $name . '[' . $count . ']', 501 sprintf( __( 'Page %d', 'mon-laboratoire' ), $count + 1 ), 502 $value, 503 $count 504 ) . '<br />'; 505 $count++; 506 } 507 // Add field for new page. 508 $description = $count > 0 509 ? __( 'Additional page', 'mon-laboratoire' ) 510 : sprintf( __( 'Page %d', 'mon-laboratoire' ), 1 ); 511 $output .= $this->_input_wp_post_id_or_url( 512 $is_mandatory, 513 $legend, 514 $name . '[' . $count . ']', 515 $description, 516 '', 517 $count 518 ); 519 // Close wrapper if CSS ID provided. 520 if ( ! empty( $css_id ) ) { 521 $output .= '</div>'; 522 } 523 return $output; 524 } 525 526 /** 527 * Generates a hierarchical page selector dropdown. 528 * 529 * Creates a select element with WordPress pages organized hierarchically, 530 * optionally including draft pages and filtering by parent page. 531 * 532 * @param string $name Field name attribute. 533 * @param bool $is_mandatory Whether page selection is required. 534 * @param string $legend Label text for the field. 535 * @param string $description Description text displayed after the field. 536 * @param string $initial_value Initially selected page ID. Default NO_PAGE_OPTION_VALUE. 537 * @param int $child_of Parent page ID to filter by. Default 0 (show all). 538 * @param int $depth Hierarchy depth to display. Default 1. 539 * 0 = Hierarchical display (indented). 540 * -1 = Flat display (no indent). 541 * 1 = Top level only. 542 * 2+ = Specific depth level. 543 * @param bool $show_drafts Whether to include draft pages. Default true. 544 * @return string Generated HTML for the page selector. 396 545 */ 397 546 public function page_selector( … … 405 554 bool $show_drafts = true 406 555 ): string { 556 // Normalize child_of parameter. 407 557 if ( App::NO_PAGE_OPTION_VALUE == $child_of || empty( $child_of ) ) { //No strinct comparison between string and int 408 558 $child_of = 0; 409 559 } 560 561 // Open wrapper and add label. 410 562 $output = '<div class="input-group">'; 411 563 $output .= $this->_maybe_add_field_label( $name, $legend, $is_mandatory ); 412 564 $output .= '<div class="input-group-addon"></div>'; 413 $pages_published = get_pages( array( 'child_of' => $child_of ) ); 414 $pages_draft = $show_drafts ? get_pages( array( 'child_of' => $child_of, 'post_status' => 'draft' ) ) : array(); 565 566 // Get published and draft pages. 567 $pages_published = get_pages( array( 'child_of' => $child_of ) ); 568 $pages_draft = $show_drafts 569 ? get_pages( array( 'child_of' => $child_of, 'post_status' => 'draft' ) ) 570 : array(); 571 572 // Generate dropdown if pages exist. 415 573 if ( ! empty( $pages_published ) || ! empty( $pages_draft ) ) { 416 $args = array( 417 'value_field' => 'ID', 418 'selected' => $initial_value, 574 $output .= $this->_generate_page_dropdown( 575 $name, 576 $initial_value, 577 $pages_published, 578 $pages_draft, 579 $depth, 580 $show_drafts 419 581 ); 420 $output .= sprintf( '<select name="%1$s" id="%1$s">', esc_attr( $name ) ) . "\n"; 582 } 583 $output .= $this->description( $description ) . '</div>'; 584 return $output; 585 } 586 587 588 /** 589 * Generates the page dropdown HTML. 590 * 591 * @param string $name Field name. 592 * @param string $initial_value Selected value. 593 * @param \WP_Post[]|false $pages_published Published pages. 594 * @param \WP_Post[]|false $pages_draft Draft pages. 595 * @param int $depth Hierarchy depth. 596 * @param bool $show_drafts Whether to show drafts. 597 * @return string Generated HTML for dropdown. 598 * @access private 599 */ 600 private function _generate_page_dropdown( 601 string $name, 602 string $initial_value, 603 $pages_published, 604 $pages_draft, 605 int $depth, 606 bool $show_drafts 607 ): string { 608 $args = array( 609 'value_field' => 'ID', 610 'selected' => $initial_value, 611 ); 612 $output = sprintf( '<select name="%1$s" id="%1$s">', esc_attr( $name ) ) . "\n"; 613 // Add "No page" option. 614 $output .= sprintf( 615 "\t" . '<option value="%1$s"%2$s>— %3$s — </option>' . "\n", 616 App::NO_PAGE_OPTION_VALUE, 617 selected( App::NO_PAGE_OPTION_VALUE, $initial_value, false ), 618 __( 'No page', 'mon-laboratoire' ) 619 ); 620 // Add published pages. 621 if ( ! empty( $pages_published ) ) { 622 if ( $show_drafts ) { 623 $output .= sprintf( "\t<optgroup label=\"%s\">\n", __( 'Pages published', 'mon-laboratoire' ) ); 624 } 625 $output .= walk_page_dropdown_tree( $pages_published, $depth, $args ); 626 if ( $show_drafts ) { 627 $output .= "\t</optgroup>\n"; 628 } 629 } 630 // Add draft pages if enabled. 631 if ( $show_drafts && ! empty( $pages_draft ) ) { 632 // @codeCoverageIgnoreStart 633 // Not possible to unit test draft pages - WP checks admin mode. 421 634 $output .= sprintf( 422 "\t" . '<option value="%1$s"%2$s>— %3$s — </option>' . "\n", 423 App::NO_PAGE_OPTION_VALUE, 424 selected( App::NO_PAGE_OPTION_VALUE, $initial_value, false ), 425 __( 'No page', 'mon-laboratoire' ) 635 "\t<optgroup label=\"%s\">\n%s\t</optgroup>\n", 636 __( 'Draft pages', 'mon-laboratoire' ), 637 walk_page_dropdown_tree( $pages_draft, $depth, $args ) 426 638 ); 427 if ( ! empty( $pages_published ) ) { 428 if ( $show_drafts ) { 429 $output .= sprintf( "\t<optgroup label=\"%s\">\n", __( 'Pages published', 'mon-laboratoire' ) ); 430 } 431 $output .= walk_page_dropdown_tree( $pages_published, $depth, $args ); 432 if ( $show_drafts ) { 433 $output .= "\t</optgroup>\n"; 434 } 435 } 436 if ( $show_drafts && ! empty( $pages_draft ) ) { 437 // @codeCoverageIgnoreStart 438 // Not possible to unit test a draft page because WP test if this is admin mode to enable this code 439 $output .= sprintf( 440 "\t<optgroup label=\"%s\">\n%s\t</optgroup>\n", 441 __( 'Draft pages', 'mon-laboratoire' ), 442 walk_page_dropdown_tree( $pages_draft, $depth, $args ) 443 ); 444 // @codeCoverageIgnoreEnd 445 } 446 $output .= "</select>\n"; 447 } 448 $output .= $this->description( $description ) . '</div>'; 449 return $output; 450 } 451 452 /** 453 * Generates HTML for page infobox and thumbnail display. 454 * @param int|null $item_id id of the item 455 * @param int $page_number number of the page (persons can have several pages) 456 * @param string|int|null $wp_post_id 457 * @param string $type of item : 'person', 'team', 'thematic' or 'unit' 458 * @return string ex: array( $id => $value ) 639 // @codeCoverageIgnoreEnd 640 } 641 $output .= "</select>\n"; 642 return $output; 643 } 644 645 /** 646 * Generates HTML for page information box and thumbnail display. 647 * 648 * Creates an information box showing page status, thumbnail preview, 649 * edit links, and attribution warnings for a selected page. 650 * 651 * @param int|null $item_id Item ID (person or structure). 652 * @param int $page_number Index for multiple page fields. 653 * @param string|int|null $wp_post_id WordPress page ID, URL, or special value. 654 * @param string $type Entity type: 'person', 'team', 'thematic' or 'unit'. Default 'person'. 655 * @return string Generated HTML for the page information box. 459 656 * @SuppressWarnings(PHPMD.ElseExpression) 460 657 */ … … 465 662 string $type = 'person' 466 663 ): string { 467 if ( empty( $wp_post_id ) ) { $wp_post_id = App::NEW_PAGE_OPTION_VALUE; } 468 if ( is_integer( $wp_post_id ) ) { $wp_post_id = strval( $wp_post_id ); } 469 $output = ''; 470 $html = ''; 471 472 switch ( $wp_post_id ) { 473 case App::NO_PAGE_OPTION_VALUE: // Person with no page - nothing to display 474 break; 475 476 case App::NEW_PAGE_OPTION_VALUE: // New item - nothing to display 477 break; 478 479 default: // Item with valid page 480 $is_numeric_wp_post_id = ( (string) abs( intval( $wp_post_id ) ) ) === $wp_post_id; 481 if ( $is_numeric_wp_post_id && get_post( intval( $wp_post_id ) ) ) { //If page exists 482 $wp_post_id = intval( $wp_post_id ); 483 $post_status = get_post_status( $wp_post_id ); 484 if ( 'draft' === $post_status ) { 485 $html .= sprintf( '<fieldset><legend>%s</legend>', __( 'Draft page', 'mon-laboratoire' ) ); 486 } 487 $html .= $this->_page_thumbnail( $wp_post_id, $page_number ); 488 $polylang_interface = new Polylang_Interface(); 489 $html .= $this->description( 490 $polylang_interface->get_edit_link_if_exists( $wp_post_id ) 491 . $this->_tell_if_page_is_already_attributed( $type, $item_id, $wp_post_id ) 492 ); 493 if ( 'draft' === $post_status ) { 494 $html .= '</fieldset>'; 495 } 496 } else { 497 $is_valid_url = filter_var( $wp_post_id, FILTER_VALIDATE_URL ); 498 if ( $is_numeric_wp_post_id ) { 499 $html .= '<p>' . sprintf( __( 'The page #%s does not exist', 'mon-laboratoire' ), $wp_post_id ) . '</p>'; 500 } elseif ( false === $is_valid_url ) { 501 $html .= '<p>' . sprintf( __( 'URL %s is invalid', 'mon-laboratoire' ), $wp_post_id ) . '</p>'; 502 } 503 } 504 break; 505 } 506 if ( ! empty( $html ) ) { 507 $output = sprintf( '<div class="input-group">%s</div>', $html ); 508 } 509 return $output; 510 } 511 664 // Normalize wp_post_id. 665 if ( empty( $wp_post_id ) ) { 666 $wp_post_id = App::NEW_PAGE_OPTION_VALUE; 667 } 668 if ( is_integer( $wp_post_id ) ) { 669 $wp_post_id = strval( $wp_post_id ); 670 } 671 // Handle special page values. 672 if ( App::NO_PAGE_OPTION_VALUE === $wp_post_id || App::NEW_PAGE_OPTION_VALUE === $wp_post_id ) { 673 return ''; 674 } 675 676 // Generate infobox content. 677 $html = $this->_generate_page_infobox_content( $wp_post_id, $page_number, $item_id, $type ); 678 679 if ( empty( $html ) ) { 680 return ''; 681 } 682 return sprintf( '<div class="input-group">%s</div>', $html ); 683 } 684 685 /** 686 * Generates the content for page information box. 687 * 688 * @param string $wp_post_id WordPress page ID or URL. 689 * @param int $page_number Page field index. 690 * @param int|null $item_id Item ID. 691 * @param string $type Entity type. 692 * @return string Generated HTML content. 693 * @access private 694 */ 695 private function _generate_page_infobox_content( 696 string $wp_post_id, 697 int $page_number, 698 $item_id, 699 string $type 700 ): string { 701 $is_numeric_id = ( (string) abs( intval( $wp_post_id ) ) ) === $wp_post_id; 702 // Handle numeric post ID. 703 if ( $is_numeric_id ) { 704 return $this->_generate_page_info_for_numeric_id( 705 intval( $wp_post_id ), 706 $page_number, 707 $item_id, 708 $type 709 ); 710 } 711 // Handle URL or invalid input. 712 return $this->_generate_page_info_for_url( $wp_post_id ); 713 } 714 715 /** 716 * Generates page info for numeric WordPress post ID. 717 * 718 * @param int $wp_post_id WordPress post ID. 719 * @param int $page_number Page field index. 720 * @param int|null $item_id Item ID. 721 * @param string $type Entity type. 722 * @return string Generated HTML. 723 * @access private 724 */ 725 private function _generate_page_info_for_numeric_id( 726 int $wp_post_id, 727 int $page_number, 728 $item_id, 729 string $type 730 ): string { 731 // Check if page exists. 732 if ( ! get_post( $wp_post_id ) ) { 733 return '<p>' . sprintf( __( 'The page #%s does not exist', 'mon-laboratoire' ), $wp_post_id ) . '</p>'; 734 } 735 $html = ''; 736 $post_status = get_post_status( $wp_post_id ); 737 // Add draft indicator if applicable. 738 if ( 'draft' === $post_status ) { 739 $html .= sprintf( '<fieldset><legend>%s</legend>', __( 'Draft page', 'mon-laboratoire' ) ); 740 } 741 // Add thumbnail. 742 $html .= $this->_page_thumbnail( $wp_post_id, $page_number ); 743 // Add edit link and attribution warnings. 744 $polylang_interface = new Polylang_Interface(); 745 $html .= $this->description( 746 $polylang_interface->get_edit_link_if_exists( $wp_post_id ) 747 . $this->_tell_if_page_is_already_attributed( $type, $item_id, $wp_post_id ) 748 ); 749 // Close draft fieldset if applicable. 750 if ( 'draft' === $post_status ) { 751 $html .= '</fieldset>'; 752 } 753 return $html; 754 } 755 756 /** 757 * Generates page info for URL input. 758 * 759 * @param string $wp_post_id URL or invalid input. 760 * @return string Generated HTML. 761 * @access private 762 */ 763 private function _generate_page_info_for_url( string $wp_post_id ): string { 764 $is_valid_url = filter_var( $wp_post_id, FILTER_VALIDATE_URL ); 765 if ( false === $is_valid_url ) { 766 return '<p>' . sprintf( 767 __( 'URL %s is invalid', 'mon-laboratoire' ), 768 esc_html( $wp_post_id ) 769 ) . '</p>'; 770 } 771 return ''; 772 } 512 773 } 513 774 ?> -
mon-laboratoire/trunk/Admin/class-admin-menu.php
r3355231 r3369834 312 312 echo( $this->_get_title( esc_html( get_admin_page_title() ) ) ); 313 313 settings_errors(); 314 echo( '<form method=" POST" id="MonLabo_admin_options" class="MonLabo_admin_options" action="options.php">' );314 echo( '<form method="post" id="MonLabo_admin_options" class="MonLabo_admin_options" action="options.php">' ); 315 315 316 316 echo( '<h2 class="nav-tab-wrapper">' ); … … 381 381 echo wp_kses_post( $this->_get_title( esc_html( get_admin_page_title() ) ) ); 382 382 settings_errors(); 383 echo '<form method=" POST" id="MonLabo_admin_options" action="options.php">';383 echo '<form method="post" id="MonLabo_admin_options" action="options.php">'; 384 384 settings_fields( 'pluginSettings_MonLabo_settings_group7' ); 385 385 do_settings_sections( 'MonLaboPageConfigPublicationsCache' ); -
mon-laboratoire/trunk/Admin/class-admin-page.php
r3361909 r3369834 200 200 } 201 201 202 $titletext = ( $this->_hide_fields === true ) ? '<span class="MonLabo_hide">' . $title . ' </span>' : $title;202 $titletext = ( $this->_hide_fields === true ) ? '<span class="MonLabo_hide">' . $title . ' </span>' : $title; 203 203 // Add the field using Settings API 204 204 $this->_optionsFormsView->add( -
mon-laboratoire/trunk/Admin/class-admin-table-view.php
r3355231 r3369834 405 405 $out .= '<h3 id="personnes_table">' . __( 'Persons', 'mon-laboratoire' ) . '</h3>'; 406 406 $out .= '<h4>' . _x( 'Working', 'nom_pluriel', 'mon-laboratoire' ) . '</h4>'; 407 $out .= wp_kses_post( $this->_generate_table_admin_for_persons( 'actif' ));407 $out .= $this->_generate_table_admin_for_persons( 'actif' ); 408 408 $out .= '<h4>' . _x( 'Former members', 'nom_pluriel', 'mon-laboratoire' ) . '</h4>'; 409 $out .= wp_kses_post( $this->_generate_table_admin_for_persons( 'alumni' ));409 $out .= $this->_generate_table_admin_for_persons( 'alumni' ); 410 410 $out .= '<a href="#haut">' . __( 'Back to top of page', 'mon-laboratoire' ) . '</a>'; 411 411 // Teams table 412 412 $out .= '<h3 id="equipes_table">' . __( 'Teams', 'mon-laboratoire' ) . '</h3>'; 413 $out .= wp_kses_post( $this->_generate_table_admin_for_teams());413 $out .= $this->_generate_table_admin_for_teams(); 414 414 $out .= '<a href="#haut">' . __( 'Back to top of page', 'mon-laboratoire' ) . '</a>'; 415 415 // Thematics table 416 416 if ( $options->uses['thematics'] ) { 417 417 $out .= '<h3 id="thematiques_table">' . __( 'Thematics', 'mon-laboratoire' ) . '</h3>'; 418 $out .= wp_kses_post( $this->_generate_table_admin_for_thematics());418 $out .= $this->_generate_table_admin_for_thematics(); 419 419 $out .= '<a href="#haut">' . __( 'Back to top of page', 'mon-laboratoire' ) . '</a>'; 420 420 } … … 422 422 if ( $options->uses['units'] ) { 423 423 $out .= '<h3 id="unites_table">' . __( 'Units', 'mon-laboratoire' ) . '</h3>'; 424 $out .= wp_kses_post( $this->_generate_table_admin_for_units());424 $out .= $this->_generate_table_admin_for_units(); 425 425 $out .= '<a href="#haut">' . __( 'Back to top of page', 'mon-laboratoire' ) . '</a>'; 426 426 } -
mon-laboratoire/trunk/Admin/class-wordpress-page.php
r3355231 r3369834 145 145 * 146 146 * @return bool True if page has configured person parent 147 * TODO : préférer plutôt tester que la page est désignées comme page de personne 148 * ou a minima faire ce test si $options10['MonLabo_perso_page_parent'] n'est 149 * pas défini. 147 150 */ 148 151 public function is_a_person_page(): bool { -
mon-laboratoire/trunk/Lib/class-privacy.php
r3361909 r3369834 2 2 namespace MonLabo\Lib; 3 3 4 defined( 'ABSPATH' ) ordie( 'No direct script access allowed' );4 defined( 'ABSPATH' ) || die( 'No direct script access allowed' ); 5 5 6 6 /** … … 34 34 * Privacy options from WordPress options. 35 35 * 36 * @var array<string,string> 36 * @var array<string,string> Key-value pairs of privacy settings. 37 37 * @access private 38 38 */ … … 41 41 /** 42 42 * Whether the current user is considered trusted. 43 * 44 * @ access private45 * @ var bool43 * 44 * @var bool True if user is trusted, false otherwise. 45 * @access private 46 46 */ 47 47 private $_is_trusted_user = false; 48 48 49 49 /** 50 * Initializes a new Privacy instance. 51 * 52 * Sets up the privacy options, translation capabilities and 53 * calculates the trust status of the current user if needed. 50 * Constructor for Privacy class. 51 * 52 * Initializes a new Privacy instance. Sets up the privacy options, 53 * translation capabilities and calculates the trust status of the 54 * current user if needed. 54 55 * 55 56 * @return void … … 57 58 */ 58 59 private function __construct() { 59 $this->_options = get_option( 'MonLabo_settings_group11' );60 $this->_options = get_option( 'MonLabo_settings_group11' ); 60 61 $this->_is_trusted_user = $this->_calculate_trust_status(); 61 62 } 62 63 63 64 /** 64 * Generic function for is_hide_email(), is_hide_room(), is_hide_phone() and is_hide_photo() 65 * 66 * @param string $privacy_option Name of the privacy option 65 * Generic method to determine if an item should be hidden. 66 * 67 * Used internally by is_hide_email(), is_hide_room(), is_hide_phone() 68 * and is_hide_photo() methods. 69 * 70 * @param string $privacy_option Name of the privacy option to check. 67 71 * @return bool True if item should be hidden, false otherwise. 68 * /69 public function _is_hide_generic( string $privacy_option ): bool {70 if (71 ! isset( $this->_options[ $privacy_option ] )72 * @access private 73 */ 74 private function _is_hide_generic( string $privacy_option ): bool { 75 if ( ! isset( $this->_options[ $privacy_option ] ) 72 76 || App::PRIVACY_SHOW === $this->_options[ $privacy_option ] 73 77 ) { … … 80 84 } 81 85 82 83 86 /** 84 87 * Determines if emails should be hidden for the current context. … … 126 129 */ 127 130 private function _calculate_trust_status(): bool { 128 if (129 ! isset( $this->_options['MonLabo_trusted_visitors'] )131 // Check if all visitors are trusted. 132 if ( ! isset( $this->_options['MonLabo_trusted_visitors'] ) 130 133 || App::PRIVACY_TRUST_EVERYBODY === $this->_options['MonLabo_trusted_visitors'] 131 134 ) { … … 133 136 } 134 137 135 // First: test if user logged-in138 // Check if user is logged in. 136 139 if ( is_user_logged_in() ) { 137 140 return true; 141 } 142 143 // Check if IP is in trusted range. 144 if ( App::PRIVACY_TRUST_IP_ZONE !== $this->_options['MonLabo_trusted_visitors'] ) { 145 return false; 138 146 } 139 147 … … 163 171 return false; 164 172 } 165 166 /** 167 * Determines if switcboard and nature fields should be displayed. 168 * 169 * @return bool True if fields have to be displayed 170 */ 171 public function is_display_switchboard_fields() : bool { 172 if( ! isset( $this->_options['MonLabo_phone_privacy'] ) ) { 173 return false; 174 } 175 if ( App::PRIVACY_SWITCHBOARD_LOCAL_SHOW === $this->_options['MonLabo_phone_privacy'] 176 ) { 177 return true; 178 } 179 return false; 180 } 181 182 183 /** 184 * Determines if switcboard and nature fields should be displayed. 185 * 186 * @return bool True if fields have to be displayed 187 */ 188 public function is_display_email_test() : bool { 189 if( ! isset( $this->_options['MonLabo_email_privacy'] ) ) { 190 return false; 191 } 192 if ( App::PRIVACY_FORM_LOCAL_SHOW === $this->_options['MonLabo_email_privacy'] 193 ) { 194 return true; 195 } 196 return false; 197 } 198 199 200 /** 201 * Determines if switcboard and nature fields should be displayed. 202 * 203 * @return bool True if fields have to be displayed 204 */ 205 public function is_display_trusted_IP_form() : bool { 206 if( ! isset( $this->_options['MonLabo_trusted_visitors'] ) ) { 207 return false; 208 } 209 if ( App::PRIVACY_TRUST_IP_ZONE === $this->_options['MonLabo_trusted_visitors'] ) { 210 return true; 211 } 212 return false; 173 174 /** 175 * Determines if switchboard and nature fields should be displayed. 176 * 177 * @return bool True if fields should be displayed, false otherwise. 178 */ 179 public function is_display_switchboard_fields(): bool { 180 if ( ! isset( $this->_options['MonLabo_phone_privacy'] ) ) { 181 return false; 182 } 183 return App::PRIVACY_SWITCHBOARD_LOCAL_SHOW === $this->_options['MonLabo_phone_privacy']; 184 } 185 186 /** 187 * Determines if email test fields should be displayed. 188 * 189 * @return bool True if email test should be displayed, false otherwise. 190 */ 191 public function is_display_email_test(): bool { 192 if ( ! isset( $this->_options['MonLabo_email_privacy'] ) ) { 193 return false; 194 } 195 return App::PRIVACY_FORM_LOCAL_SHOW === $this->_options['MonLabo_email_privacy']; 196 } 197 198 /** 199 * Determines if trusted IP form fields should be displayed. 200 * 201 * @return bool True if trusted IP form should be displayed, false otherwise. 202 */ 203 public function is_display_trusted_IP_form(): bool { 204 if ( ! isset( $this->_options['MonLabo_trusted_visitors'] ) ) { 205 return false; 206 } 207 return App::PRIVACY_TRUST_IP_ZONE === $this->_options['MonLabo_trusted_visitors']; 213 208 } 214 209 … … 218 213 * @return bool True if phones should be replaced with switchboard number. 219 214 */ 220 public function is_phone_replaced_with_switchboard() : bool { 221 if( ! isset( $this->_options['MonLabo_phone_privacy'] ) ) { 222 return false; 223 } 224 if ( 225 App::PRIVACY_SWITCHBOARD_LOCAL_SHOW === $this->_options['MonLabo_phone_privacy'] 226 && ! $this->_is_trusted_user 227 ) { 228 return true; 229 } 230 return false; 231 } 232 215 public function is_phone_replaced_with_switchboard(): bool { 216 if ( ! isset( $this->_options['MonLabo_phone_privacy'] ) ) { 217 return false; 218 } 219 return App::PRIVACY_SWITCHBOARD_LOCAL_SHOW === $this->_options['MonLabo_phone_privacy'] 220 && ! $this->_is_trusted_user; 221 } 222 233 223 /** 234 224 * Checks if email addresses should be replaced with a contact form. 235 225 * 236 * @return bool True if emails should be replaced with contact form. 237 */ 238 public function is_email_replaced_by_form() : bool { 239 if( ! isset( $this->_options['MonLabo_email_privacy'] ) ) { 240 return false; 241 } 242 if ( 243 App::PRIVACY_FORM_LOCAL_SHOW === $this->_options['MonLabo_email_privacy'] 244 && ! $this->_is_trusted_user 245 ) { 246 return true; 247 } 248 return false; 249 } 250 251 /** 252 * Send switchboard parameters. 226 * @return bool True if emails should be replaced with contact form, false otherwise. 227 */ 228 public function is_email_replaced_by_form(): bool { 229 if ( ! isset( $this->_options['MonLabo_email_privacy'] ) ) { 230 return false; 231 } 232 return App::PRIVACY_FORM_LOCAL_SHOW === $this->_options['MonLabo_email_privacy'] 233 && ! $this->_is_trusted_user; 234 } 235 236 /** 237 * Get switchboard parameters. 238 * 239 * Returns the switchboard number and nature labels in English and French. 253 240 * 254 241 * @return string[] $switchboard_params -
mon-laboratoire/trunk/mon-laboratoire.php
r3361909 r3369834 16 16 * Plugin URI: http://www.monlabo.org 17 17 * Description: Simplify the management of a research unit's website 18 * Version: 5.1 18 * Version: 5.1.1 19 19 * Requires at least: 5.6 20 20 * Requires PHP: 7.2 … … 42 42 43 43 defined( 'ABSPATH' ) or die( 'No direct script access allowed' ); 44 define( 'MONLABO_VERSION', '5.1 ' ); //Currently plugin version, use SemVer - https://semver.org44 define( 'MONLABO_VERSION', '5.1.1' ); //Currently plugin version, use SemVer - https://semver.org 45 45 46 46 require_once ( __DIR__ . '/polyfill.php' ); -
mon-laboratoire/trunk/readme.txt
r3361909 r3369834 5 5 Requires at least: 5.6 6 6 Tested up to: 6.7 7 Stable tag: 5.1 7 Stable tag: 5.1.1 8 8 Requires PHP: 7.2 9 9 License: GPLv3 or later … … 46 46 == Changelog == 47 47 48 = 5.1.1 = 49 *Release Date - 29 september 2025* 50 * BUG : Combinations of privacy options could show the email address in cases where it should have been hidden. 51 * BUG : Admin menu - Modify buttons where accidentally inactivated in "table view" tab. 52 * CODE : improve coding standard 53 54 48 55 = 5.1 = 49 56 *Release Date - 15 september 2025* 50 57 51 58 * New Features: 52 * - EVOL : simplify privacy configuration page for managing personal data protection 53 * 59 - EVOL : simplify privacy configuration page for managing personal data protection 54 60 * Bug Fixes & Reliability: 55 *- CODE : class refactoring for improved maintainability:56 *- Html_Forms -> Forms\{Generic_Forms_View, Forms_View, Wp_Post_Forms_View}57 *- Settings_Fields -> Forms\Options_Forms_View58 *- Forms_Processing\Forms_Processing -> Forms\Forms_Processing59 *- Forms_Processing\Forms_Processing_Generic -> Forms\Forms_Processing_Generic60 *- Forms_Processing\Forms_Processing_Advanced -> Forms\Forms_Processing_Advanced61 *- BUG : mail form was not translated62 *- BUG : In admin menu for editing person or other item, first page links and translation were not displayed61 - CODE : class refactoring for improved maintainability: 62 - Html_Forms -> Forms\{Generic_Forms_View, Forms_View, Wp_Post_Forms_View} 63 - Settings_Fields -> Forms\Options_Forms_View 64 - Forms_Processing\Forms_Processing -> Forms\Forms_Processing 65 - Forms_Processing\Forms_Processing_Generic -> Forms\Forms_Processing_Generic 66 - Forms_Processing\Forms_Processing_Advanced -> Forms\Forms_Processing_Advanced 67 - BUG : mail form was not translated 68 - BUG : In admin menu for editing person or other item, first page links and translation were not displayed 63 69 64 70 = 5.0.4 = … … 72 78 73 79 * New Features: 74 * - NEW: Comprehensive privacy configuration page for managing personal data protection (page available at URL https://YOURSITE.TLD/wp-admin/admin.php?page=MonLabo_config&tab=tab_privacy) 75 * - Can replace email addresses with contact forms on public sites (email is not hidden for internal users) 76 * - Can replace phone numbers with switchboard numbers on public sites (full view for internal users) 77 * - Can hide personal photos and/or office locations on public sites (full view for internal users) 78 * - Can define trusted IP address ranges for internal users with full data access 79 * - NEW: Preview version of [publications_list2] shortcode - complete rewrite of [publications_list] using HAL API V3 exclusively 80 * - Eliminates dependency on potentially discontinued external tools 81 * (exportPubli from haltools.inria.fr and afficheRequetePubli from haltools.archives-ouvertes.fr) 82 * - Removes support for legacy Descartes Publi database 83 * - Handles pages with thousands of publications without HAL server timeouts 84 * - Enables future feature: expanded publication format support 85 * - Enables future feature: customizable publication type filtering 86 * - Fixes publication ordering issue (now correctly displays most recent first) 87 * - EVOL in shortodes : 88 * - [person_panel] : small improve of formating 89 * - [teams_list] : suppress option "teams_publications_page" useless and unnecessarily complicated 90 * - EVOL and IMPROVE in admin space : 91 * - Dynamic sub-option display when features are activated 92 * - Add publication cache counter on upper bar. Dynamically hide cache counters when they are emptied. 93 * - DOC: Added comprehensive contributor credits and version history 94 * 80 - NEW: Comprehensive privacy configuration page for managing personal data protection (page available at URL https://YOURSITE.TLD/wp-admin/admin.php?page=MonLabo_config&tab=tab_privacy) 81 - Can replace email addresses with contact forms on public sites (email is not hidden for internal users) 82 - Can replace phone numbers with switchboard numbers on public sites (full view for internal users) 83 - Can hide personal photos and/or office locations on public sites (full view for internal users) 84 - Can define trusted IP address ranges for internal users with full data access 85 - NEW: Preview version of [publications_list2] shortcode - complete rewrite of [publications_list] using HAL API V3 exclusively 86 - Eliminates dependency on potentially discontinued external tools 87 (exportPubli from haltools.inria.fr and afficheRequetePubli from haltools.archives-ouvertes.fr) 88 - Removes support for legacy Descartes Publi database 89 - Handles pages with thousands of publications without HAL server timeouts 90 - Enables future feature: expanded publication format support 91 - Enables future feature: customizable publication type filtering 92 - Fixes publication ordering issue (now correctly displays most recent first) 93 - EVOL in shortodes : 94 - [person_panel] : small improve of formating 95 - [teams_list] : suppress option "teams_publications_page" useless and unnecessarily complicated 96 - EVOL and IMPROVE in admin space : 97 - Dynamic sub-option display when features are activated 98 - Add publication cache counter on upper bar. Dynamically hide cache counters when they are emptied. 99 - DOC: Added comprehensive contributor credits and version history 95 100 * Bug Fixes & Reliability: 96 *- BUG : Repair import tool (it was often not functionnal because of a bad check of file extension)97 *- BUG : In shortcode [publications_list], repair wilcard selection ('*') for persons, teams or unit98 *- CODE: Major class refactoring for improved maintainability:99 *- Access_Data -> Access_Data\{ Access_Generic, Access_Data, Core\Data_Accessor, Core\Data_Creator, Core\Data_Remover }100 *- Html -> { Html, Person_Or_Structure_View,101 *Shortcodes\Generic_View, Shortcodes\Chart_view, Shortcodes\Table_view, Shortcodes\List_view }102 *- Edit_Members -> Edit_Members\{ Edit_Members, Edit_Members_Generic, Edit_Members_Comment, Edit_Members_Advanced }103 *- Forms_Processing -> Forms_Processing\{ Forms_Processing, Forms_Processing_Generic, Forms_Processing_Advanced }104 *- Admin_Ui -> { Admin_Init_Pages, Forms_Processing_Generic, Forms_Processing_Advanced }105 *- Page -> Wordpress_Page106 *- Admin -> { Admin, Admin_Init }107 *- Admin_Render -> Admin_Menu108 *- CODE : Comprehensive rewrite of all classes:109 *- Enhanced PHPDoc comments throughout all classes110 *- Improved coding standards compliance across all classes111 *- Strengthened security with proper escaping (esc_attr(), esc_js(), wp_kses_post(), esc_html())112 *- Cleaner HTML generation (consistent double quotes, optimized spacing...)113 *- Reduced code complexity through helper methods, conditional execution...114 *- CODE: Eliminated global functions for better architecture:115 *- Migrated inc-lib-tables.php to new Admin_Table_View class116 *- Migrated inc-lib-modal.php to Html class117 *- Migrated main code to new Mon_Laboratoire class118 *- Migrated admin main code to Admin class119 *- CODE: Now uses null coalescing operator (??) - requires PHP 7.0+ that has been already required in former versions.120 *- CODE: Fully tested and compatible with WordPress 6.8121 *- CODE: Updated page URLs from ?p= to ?page_id= format122 *- CODE: Refactored admin JavaScript following WordPress best practices101 - BUG : Repair import tool (it was often not functionnal because of a bad check of file extension) 102 - BUG : In shortcode [publications_list], repair wilcard selection ('*') for persons, teams or unit 103 - CODE: Major class refactoring for improved maintainability: 104 - Access_Data -> Access_Data\{ Access_Generic, Access_Data, Core\Data_Accessor, Core\Data_Creator, Core\Data_Remover } 105 - Html -> { Html, Person_Or_Structure_View, 106 Shortcodes\Generic_View, Shortcodes\Chart_view, Shortcodes\Table_view, Shortcodes\List_view } 107 - Edit_Members -> Edit_Members\{ Edit_Members, Edit_Members_Generic, Edit_Members_Comment, Edit_Members_Advanced } 108 - Forms_Processing -> Forms_Processing\{ Forms_Processing, Forms_Processing_Generic, Forms_Processing_Advanced } 109 - Admin_Ui -> { Admin_Init_Pages, Forms_Processing_Generic, Forms_Processing_Advanced } 110 - Page -> Wordpress_Page 111 - Admin -> { Admin, Admin_Init } 112 - Admin_Render -> Admin_Menu 113 - CODE : Comprehensive rewrite of all classes: 114 - Enhanced PHPDoc comments throughout all classes 115 - Improved coding standards compliance across all classes 116 - Strengthened security with proper escaping (esc_attr(), esc_js(), wp_kses_post(), esc_html()) 117 - Cleaner HTML generation (consistent double quotes, optimized spacing...) 118 - Reduced code complexity through helper methods, conditional execution... 119 - CODE: Eliminated global functions for better architecture: 120 - Migrated inc-lib-tables.php to new Admin_Table_View class 121 - Migrated inc-lib-modal.php to Html class 122 - Migrated main code to new Mon_Laboratoire class 123 - Migrated admin main code to Admin class 124 - CODE: Now uses null coalescing operator (??) - requires PHP 7.0+ that has been already required in former versions. 125 - CODE: Fully tested and compatible with WordPress 6.8 126 - CODE: Updated page URLs from ?p= to ?page_id= format 127 - CODE: Refactored admin JavaScript following WordPress best practices 123 128 124 129 = 4.9.1 = -
mon-laboratoire/trunk/todo.txt
r3361909 r3369834 10 10 11 11 Hal: 12 TODO: Mettre en gras les personnels alumni dans les publications. 12 13 TODO: Faire un bouton "page suivante" si l'on dépasse le max de requête HAL 13 14 ÉVOL: Pouvoir avec HAL faire des requêtes avec des IdHal et des struct en même temps (ou consécutivement et fusionnées)
Note: See TracChangeset
for help on using the changeset viewer.