Merge branch 'develop' into feature/b3217-2dev

This commit is contained in:
odain
2020-09-08 17:00:41 +02:00
641 changed files with 23943 additions and 4198 deletions

View File

@@ -1,3 +1,5 @@
root = true
[*]
charset = utf-8
end_of_line = lf
@@ -11,7 +13,7 @@ ij_formatter_off_tag = @formatter:off
ij_formatter_on_tag = @formatter:on
ij_formatter_tags_enabled = false
ij_smart_tabs = false
ij_visual_guides = 80, 120, 140
ij_visual_guides = 140
ij_wrap_on_typing = true
[*.css]
@@ -33,53 +35,9 @@ ij_css_space_after_colon = true
ij_css_space_before_opening_brace = true
ij_css_value_alignment = 0
[*.csv]
max_line_length = 2147483647
ij_wrap_on_typing = false
ij_csv_wrap_long_lines = false
[*.feature]
indent_size = 2
ij_gherkin_keep_indents_on_empty_lines = false
[*.less]
indent_size = 2
ij_less_align_closing_brace_with_properties = false
ij_less_blank_lines_around_nested_selector = 1
ij_less_blank_lines_between_blocks = 1
ij_less_brace_placement = 0
ij_less_hex_color_long_format = false
ij_less_hex_color_lower_case = false
ij_less_hex_color_short_format = false
ij_less_hex_color_upper_case = false
ij_less_keep_blank_lines_in_code = 2
ij_less_keep_indents_on_empty_lines = false
ij_less_keep_single_line_blocks = false
ij_less_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_less_space_after_colon = true
ij_less_space_before_opening_brace = true
ij_less_value_alignment = 0
[*.sass]
indent_size = 2
ij_sass_align_closing_brace_with_properties = false
ij_sass_blank_lines_around_nested_selector = 1
ij_sass_blank_lines_between_blocks = 1
ij_sass_brace_placement = 0
ij_sass_hex_color_long_format = false
ij_sass_hex_color_lower_case = false
ij_sass_hex_color_short_format = false
ij_sass_hex_color_upper_case = false
ij_sass_keep_blank_lines_in_code = 2
ij_sass_keep_indents_on_empty_lines = false
ij_sass_keep_single_line_blocks = false
ij_sass_properties_order = font,font-family,font-size,font-weight,font-style,font-variant,font-size-adjust,font-stretch,line-height,position,z-index,top,right,bottom,left,display,visibility,float,clear,overflow,overflow-x,overflow-y,clip,zoom,align-content,align-items,align-self,flex,flex-flow,flex-basis,flex-direction,flex-grow,flex-shrink,flex-wrap,justify-content,order,box-sizing,width,min-width,max-width,height,min-height,max-height,margin,margin-top,margin-right,margin-bottom,margin-left,padding,padding-top,padding-right,padding-bottom,padding-left,table-layout,empty-cells,caption-side,border-spacing,border-collapse,list-style,list-style-position,list-style-type,list-style-image,content,quotes,counter-reset,counter-increment,resize,cursor,user-select,nav-index,nav-up,nav-right,nav-down,nav-left,transition,transition-delay,transition-timing-function,transition-duration,transition-property,transform,transform-origin,animation,animation-name,animation-duration,animation-play-state,animation-timing-function,animation-delay,animation-iteration-count,animation-direction,text-align,text-align-last,vertical-align,white-space,text-decoration,text-emphasis,text-emphasis-color,text-emphasis-style,text-emphasis-position,text-indent,text-justify,letter-spacing,word-spacing,text-outline,text-transform,text-wrap,text-overflow,text-overflow-ellipsis,text-overflow-mode,word-wrap,word-break,tab-size,hyphens,pointer-events,opacity,color,border,border-width,border-style,border-color,border-top,border-top-width,border-top-style,border-top-color,border-right,border-right-width,border-right-style,border-right-color,border-bottom,border-bottom-width,border-bottom-style,border-bottom-color,border-left,border-left-width,border-left-style,border-left-color,border-radius,border-top-left-radius,border-top-right-radius,border-bottom-right-radius,border-bottom-left-radius,border-image,border-image-source,border-image-slice,border-image-width,border-image-outset,border-image-repeat,outline,outline-width,outline-style,outline-color,outline-offset,background,background-color,background-image,background-repeat,background-attachment,background-position,background-position-x,background-position-y,background-clip,background-origin,background-size,box-decoration-break,box-shadow,text-shadow
ij_sass_space_after_colon = true
ij_sass_space_before_opening_brace = true
ij_sass_value_alignment = 0
[*.scss]
indent_style = tab
ij_smart_tabs = true
ij_scss_align_closing_brace_with_properties = false
ij_scss_blank_lines_around_nested_selector = 1
ij_scss_blank_lines_between_blocks = 1
@@ -99,7 +57,6 @@ ij_scss_value_alignment = 0
[*.twig]
indent_style = tab
ij_smart_tabs = true
ij_wrap_on_typing = false
ij_twig_keep_indents_on_empty_lines = false
ij_twig_spaces_inside_delimiters = true
ij_twig_spaces_inside_variable_delimiters = true
@@ -112,7 +69,212 @@ ij_editorconfig_space_before_colon = false
ij_editorconfig_space_before_comma = false
ij_editorconfig_spaces_around_assignment_operators = true
[{*.cjs,*.js}]
[{*.ctp,*.phtml,*.module,*.php,*.php5,*.php4,*.hphp,*.inc}]
indent_style = tab
ij_continuation_indent_size = 4
ij_smart_tabs = true
ij_wrap_on_typing = false
ij_php_align_assignments = false
ij_php_align_class_constants = false
ij_php_align_group_field_declarations = false
ij_php_align_inline_comments = false
ij_php_align_key_value_pairs = false
ij_php_align_multiline_array_initializer_expression = false
ij_php_align_multiline_binary_operation = false
ij_php_align_multiline_chained_methods = false
ij_php_align_multiline_extends_list = false
ij_php_align_multiline_for = true
ij_php_align_multiline_parameters = false
ij_php_align_multiline_parameters_in_calls = false
ij_php_align_multiline_ternary_operation = false
ij_php_align_phpdoc_comments = false
ij_php_align_phpdoc_param_names = false
ij_php_api_weight = 1
ij_php_array_initializer_new_line_after_left_brace = true
ij_php_array_initializer_right_brace_on_new_line = true
ij_php_array_initializer_wrap = on_every_item
ij_php_assignment_wrap = off
ij_php_author_weight = 7
ij_php_binary_operation_sign_on_next_line = false
ij_php_binary_operation_wrap = off
ij_php_blank_lines_after_class_header = 0
ij_php_blank_lines_after_function = 1
ij_php_blank_lines_after_imports = 1
ij_php_blank_lines_after_opening_tag = 0
ij_php_blank_lines_after_package = 1
ij_php_blank_lines_around_class = 1
ij_php_blank_lines_around_constants = 0
ij_php_blank_lines_around_field = 0
ij_php_blank_lines_around_method = 1
ij_php_blank_lines_before_class_end = 0
ij_php_blank_lines_before_imports = 1
ij_php_blank_lines_before_method_body = 0
ij_php_blank_lines_before_package = 1
ij_php_blank_lines_before_return_statement = 1
ij_php_block_brace_style = end_of_line
ij_php_call_parameters_new_line_after_left_paren = false
ij_php_call_parameters_right_paren_on_new_line = false
ij_php_call_parameters_wrap = normal
ij_php_catch_on_new_line = false
ij_php_category_weight = 28
ij_php_class_brace_style = end_of_line
ij_php_comma_after_last_array_element = true
ij_php_concat_spaces = false
ij_php_copyright_weight = 28
ij_php_deprecated_weight = 28
ij_php_do_while_brace_force = always
ij_php_else_if_style = as_is
ij_php_else_on_new_line = true
ij_php_example_weight = 3
ij_php_extends_keyword_wrap = off
ij_php_extends_list_wrap = off
ij_php_fields_default_visibility = private
ij_php_filesource_weight = 28
ij_php_finally_on_new_line = false
ij_php_for_brace_force = always
ij_php_for_statement_new_line_after_left_paren = false
ij_php_for_statement_right_paren_on_new_line = false
ij_php_for_statement_wrap = off
ij_php_force_short_declaration_array_style = false
ij_php_global_weight = 28
ij_php_group_use_wrap = on_every_item
ij_php_if_brace_force = always
ij_php_if_lparen_on_next_line = false
ij_php_if_rparen_on_next_line = false
ij_php_ignore_weight = 28
ij_php_import_sorting = alphabetic
ij_php_indent_break_from_case = true
ij_php_indent_case_from_switch = true
ij_php_indent_code_in_php_tags = false
ij_php_internal_weight = 0
ij_php_keep_blank_lines_after_lbrace = 2
ij_php_keep_blank_lines_before_right_brace = 2
ij_php_keep_blank_lines_in_code = 2
ij_php_keep_blank_lines_in_declarations = 2
ij_php_keep_control_statement_in_one_line = true
ij_php_keep_first_column_comment = true
ij_php_keep_indents_on_empty_lines = false
ij_php_keep_line_breaks = true
ij_php_keep_rparen_and_lbrace_on_one_line = true
ij_php_keep_simple_methods_in_one_line = false
ij_php_lambda_brace_style = end_of_line
ij_php_license_weight = 28
ij_php_line_comment_add_space = false
ij_php_line_comment_at_first_column = true
ij_php_link_weight = 28
ij_php_lower_case_boolean_const = true
ij_php_lower_case_null_const = true
ij_php_method_brace_style = end_of_line
ij_php_method_call_chain_wrap = off
ij_php_method_parameters_new_line_after_left_paren = true
ij_php_method_parameters_right_paren_on_new_line = true
ij_php_method_parameters_wrap = normal
ij_php_method_weight = 28
ij_php_modifier_list_wrap = false
ij_php_multiline_chained_calls_semicolon_on_new_line = false
ij_php_namespace_brace_style = 1
ij_php_null_type_position = in_the_end
ij_php_package_weight = 28
ij_php_param_weight = 4
ij_php_parentheses_expression_new_line_after_left_paren = false
ij_php_parentheses_expression_right_paren_on_new_line = false
ij_php_phpdoc_blank_line_before_tags = true
ij_php_phpdoc_blank_lines_around_parameters = true
ij_php_phpdoc_keep_blank_lines = true
ij_php_phpdoc_param_spaces_between_name_and_description = 1
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
ij_php_phpdoc_param_spaces_between_type_and_name = 1
ij_php_phpdoc_use_fqcn = true
ij_php_phpdoc_wrap_long_lines = true
ij_php_place_assignment_sign_on_next_line = false
ij_php_place_parens_for_constructor = 0
ij_php_property_read_weight = 28
ij_php_property_weight = 28
ij_php_property_write_weight = 28
ij_php_return_type_on_new_line = false
ij_php_return_weight = 5
ij_php_see_weight = 2
ij_php_since_weight = 28
ij_php_sort_phpdoc_elements = true
ij_php_space_after_colon = true
ij_php_space_after_colon_in_return_type = true
ij_php_space_after_comma = true
ij_php_space_after_for_semicolon = true
ij_php_space_after_quest = true
ij_php_space_after_type_cast = false
ij_php_space_after_unary_not = false
ij_php_space_before_array_initializer_left_brace = false
ij_php_space_before_catch_keyword = true
ij_php_space_before_catch_left_brace = true
ij_php_space_before_catch_parentheses = true
ij_php_space_before_class_left_brace = true
ij_php_space_before_closure_left_parenthesis = true
ij_php_space_before_colon = true
ij_php_space_before_colon_in_return_type = false
ij_php_space_before_comma = false
ij_php_space_before_do_left_brace = true
ij_php_space_before_else_keyword = true
ij_php_space_before_else_left_brace = true
ij_php_space_before_finally_keyword = true
ij_php_space_before_finally_left_brace = true
ij_php_space_before_for_left_brace = true
ij_php_space_before_for_parentheses = true
ij_php_space_before_for_semicolon = false
ij_php_space_before_if_left_brace = true
ij_php_space_before_if_parentheses = true
ij_php_space_before_method_call_parentheses = false
ij_php_space_before_method_left_brace = true
ij_php_space_before_method_parentheses = false
ij_php_space_before_quest = true
ij_php_space_before_switch_left_brace = true
ij_php_space_before_switch_parentheses = true
ij_php_space_before_try_left_brace = true
ij_php_space_before_unary_not = false
ij_php_space_before_while_keyword = true
ij_php_space_before_while_left_brace = true
ij_php_space_before_while_parentheses = true
ij_php_space_between_ternary_quest_and_colon = false
ij_php_spaces_around_additive_operators = true
ij_php_spaces_around_arrow = false
ij_php_spaces_around_assignment_in_declare = false
ij_php_spaces_around_assignment_operators = true
ij_php_spaces_around_bitwise_operators = true
ij_php_spaces_around_equality_operators = true
ij_php_spaces_around_logical_operators = true
ij_php_spaces_around_multiplicative_operators = true
ij_php_spaces_around_null_coalesce_operator = true
ij_php_spaces_around_relational_operators = true
ij_php_spaces_around_shift_operators = true
ij_php_spaces_around_unary_operator = false
ij_php_spaces_around_var_within_brackets = false
ij_php_spaces_within_array_initializer_braces = false
ij_php_spaces_within_brackets = false
ij_php_spaces_within_catch_parentheses = false
ij_php_spaces_within_for_parentheses = false
ij_php_spaces_within_if_parentheses = false
ij_php_spaces_within_method_call_parentheses = false
ij_php_spaces_within_method_parentheses = false
ij_php_spaces_within_parentheses = false
ij_php_spaces_within_short_echo_tags = true
ij_php_spaces_within_switch_parentheses = false
ij_php_spaces_within_while_parentheses = false
ij_php_special_else_if_treatment = false
ij_php_subpackage_weight = 28
ij_php_ternary_operation_signs_on_next_line = false
ij_php_ternary_operation_wrap = off
ij_php_throws_weight = 6
ij_php_todo_weight = 28
ij_php_unknown_tag_weight = 28
ij_php_upper_case_boolean_const = false
ij_php_upper_case_null_const = false
ij_php_uses_weight = 28
ij_php_var_weight = 28
ij_php_variable_naming_style = mixed
ij_php_version_weight = 28
ij_php_while_brace_force = always
ij_php_while_on_new_line = false
[{*.js,*.cjs}]
indent_style = tab
ij_continuation_indent_size = 4
ij_smart_tabs = true
@@ -134,13 +296,13 @@ ij_javascript_array_initializer_wrap = off
ij_javascript_assignment_wrap = off
ij_javascript_binary_operation_sign_on_next_line = false
ij_javascript_binary_operation_wrap = off
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**/*
ij_javascript_blacklist_imports = rxjs/Rx,node_modules/**/*,@angular/material,@angular/material/typings/**
ij_javascript_blank_lines_after_imports = 1
ij_javascript_blank_lines_around_class = 1
ij_javascript_blank_lines_around_field = 0
ij_javascript_blank_lines_around_function = 1
ij_javascript_blank_lines_around_method = 1
ij_javascript_block_brace_style = next_line
ij_javascript_block_brace_style = end_of_line
ij_javascript_call_parameters_new_line_after_left_paren = false
ij_javascript_call_parameters_right_paren_on_new_line = false
ij_javascript_call_parameters_wrap = off
@@ -148,7 +310,7 @@ ij_javascript_catch_on_new_line = false
ij_javascript_chained_call_dot_on_new_line = true
ij_javascript_class_brace_style = end_of_line
ij_javascript_comma_on_new_line = false
ij_javascript_do_while_brace_force = never
ij_javascript_do_while_brace_force = always
ij_javascript_else_on_new_line = true
ij_javascript_enforce_trailing_comma = keep
ij_javascript_extends_keyword_wrap = off
@@ -156,7 +318,7 @@ ij_javascript_extends_list_wrap = off
ij_javascript_field_prefix = _
ij_javascript_file_name_style = relaxed
ij_javascript_finally_on_new_line = false
ij_javascript_for_brace_force = never
ij_javascript_for_brace_force = always
ij_javascript_for_statement_new_line_after_left_paren = false
ij_javascript_for_statement_right_paren_on_new_line = false
ij_javascript_for_statement_wrap = off
@@ -272,216 +434,11 @@ ij_javascript_use_path_mapping = always
ij_javascript_use_public_modifier = false
ij_javascript_use_semicolon_after_statement = true
ij_javascript_var_declaration_wrap = normal
ij_javascript_while_brace_force = never
ij_javascript_while_brace_force = always
ij_javascript_while_on_new_line = false
ij_javascript_wrap_comments = false
[{*.module,*.hphp,*.phtml,*.php5,*.php4,*.php,*.ctp,*.inc}]
indent_style = tab
ij_continuation_indent_size = 4
ij_smart_tabs = true
ij_wrap_on_typing = false
ij_php_align_assignments = false
ij_php_align_class_constants = false
ij_php_align_group_field_declarations = false
ij_php_align_inline_comments = false
ij_php_align_key_value_pairs = false
ij_php_align_multiline_array_initializer_expression = false
ij_php_align_multiline_binary_operation = false
ij_php_align_multiline_chained_methods = false
ij_php_align_multiline_extends_list = false
ij_php_align_multiline_for = true
ij_php_align_multiline_parameters = false
ij_php_align_multiline_parameters_in_calls = false
ij_php_align_multiline_ternary_operation = false
ij_php_align_phpdoc_comments = false
ij_php_align_phpdoc_param_names = false
ij_php_api_weight = 1
ij_php_array_initializer_new_line_after_left_brace = true
ij_php_array_initializer_right_brace_on_new_line = true
ij_php_array_initializer_wrap = on_every_item
ij_php_assignment_wrap = off
ij_php_author_weight = 7
ij_php_binary_operation_sign_on_next_line = false
ij_php_binary_operation_wrap = off
ij_php_blank_lines_after_class_header = 0
ij_php_blank_lines_after_function = 1
ij_php_blank_lines_after_imports = 1
ij_php_blank_lines_after_opening_tag = 0
ij_php_blank_lines_after_package = 1
ij_php_blank_lines_around_class = 1
ij_php_blank_lines_around_constants = 0
ij_php_blank_lines_around_field = 0
ij_php_blank_lines_around_method = 1
ij_php_blank_lines_before_class_end = 0
ij_php_blank_lines_before_imports = 1
ij_php_blank_lines_before_method_body = 0
ij_php_blank_lines_before_package = 1
ij_php_blank_lines_before_return_statement = 1
ij_php_block_brace_style = next_line
ij_php_call_parameters_new_line_after_left_paren = false
ij_php_call_parameters_right_paren_on_new_line = false
ij_php_call_parameters_wrap = normal
ij_php_catch_on_new_line = true
ij_php_category_weight = 28
ij_php_class_brace_style = next_line
ij_php_comma_after_last_array_element = true
ij_php_concat_spaces = false
ij_php_copyright_weight = 28
ij_php_deprecated_weight = 28
ij_php_do_while_brace_force = always
ij_php_else_if_style = as_is
ij_php_else_on_new_line = true
ij_php_example_weight = 3
ij_php_extends_keyword_wrap = off
ij_php_extends_list_wrap = off
ij_php_fields_default_visibility = private
ij_php_filesource_weight = 28
ij_php_finally_on_new_line = true
ij_php_for_brace_force = always
ij_php_for_statement_new_line_after_left_paren = false
ij_php_for_statement_right_paren_on_new_line = false
ij_php_for_statement_wrap = off
ij_php_force_short_declaration_array_style = false
ij_php_global_weight = 28
ij_php_group_use_wrap = on_every_item
ij_php_if_brace_force = always
ij_php_if_lparen_on_next_line = false
ij_php_if_rparen_on_next_line = false
ij_php_ignore_weight = 28
ij_php_import_sorting = alphabetic
ij_php_indent_break_from_case = true
ij_php_indent_case_from_switch = true
ij_php_indent_code_in_php_tags = false
ij_php_internal_weight = 0
ij_php_keep_blank_lines_after_lbrace = 2
ij_php_keep_blank_lines_before_right_brace = 2
ij_php_keep_blank_lines_in_code = 2
ij_php_keep_blank_lines_in_declarations = 2
ij_php_keep_control_statement_in_one_line = true
ij_php_keep_first_column_comment = true
ij_php_keep_indents_on_empty_lines = false
ij_php_keep_line_breaks = true
ij_php_keep_rparen_and_lbrace_on_one_line = true
ij_php_keep_simple_methods_in_one_line = false
ij_php_lambda_brace_style = end_of_line
ij_php_license_weight = 28
ij_php_line_comment_add_space = false
ij_php_line_comment_at_first_column = true
ij_php_link_weight = 28
ij_php_lower_case_boolean_const = true
ij_php_lower_case_null_const = true
ij_php_method_brace_style = next_line
ij_php_method_call_chain_wrap = off
ij_php_method_parameters_new_line_after_left_paren = true
ij_php_method_parameters_right_paren_on_new_line = true
ij_php_method_parameters_wrap = normal
ij_php_method_weight = 28
ij_php_modifier_list_wrap = false
ij_php_multiline_chained_calls_semicolon_on_new_line = false
ij_php_namespace_brace_style = 1
ij_php_null_type_position = in_the_end
ij_php_package_weight = 28
ij_php_param_weight = 4
ij_php_parentheses_expression_new_line_after_left_paren = false
ij_php_parentheses_expression_right_paren_on_new_line = false
ij_php_phpdoc_blank_line_before_tags = true
ij_php_phpdoc_blank_lines_around_parameters = true
ij_php_phpdoc_keep_blank_lines = true
ij_php_phpdoc_param_spaces_between_name_and_description = 1
ij_php_phpdoc_param_spaces_between_tag_and_type = 1
ij_php_phpdoc_param_spaces_between_type_and_name = 1
ij_php_phpdoc_use_fqcn = true
ij_php_phpdoc_wrap_long_lines = true
ij_php_place_assignment_sign_on_next_line = false
ij_php_place_parens_for_constructor = 0
ij_php_property_read_weight = 28
ij_php_property_weight = 28
ij_php_property_write_weight = 28
ij_php_return_type_on_new_line = false
ij_php_return_weight = 5
ij_php_see_weight = 2
ij_php_since_weight = 28
ij_php_sort_phpdoc_elements = true
ij_php_space_after_colon = true
ij_php_space_after_colon_in_return_type = true
ij_php_space_after_comma = true
ij_php_space_after_for_semicolon = true
ij_php_space_after_quest = true
ij_php_space_after_type_cast = false
ij_php_space_after_unary_not = false
ij_php_space_before_array_initializer_left_brace = false
ij_php_space_before_catch_keyword = true
ij_php_space_before_catch_left_brace = true
ij_php_space_before_catch_parentheses = true
ij_php_space_before_class_left_brace = true
ij_php_space_before_closure_left_parenthesis = true
ij_php_space_before_colon = true
ij_php_space_before_colon_in_return_type = false
ij_php_space_before_comma = false
ij_php_space_before_do_left_brace = true
ij_php_space_before_else_keyword = true
ij_php_space_before_else_left_brace = true
ij_php_space_before_finally_keyword = true
ij_php_space_before_finally_left_brace = true
ij_php_space_before_for_left_brace = true
ij_php_space_before_for_parentheses = true
ij_php_space_before_for_semicolon = false
ij_php_space_before_if_left_brace = true
ij_php_space_before_if_parentheses = true
ij_php_space_before_method_call_parentheses = false
ij_php_space_before_method_left_brace = true
ij_php_space_before_method_parentheses = false
ij_php_space_before_quest = true
ij_php_space_before_switch_left_brace = true
ij_php_space_before_switch_parentheses = true
ij_php_space_before_try_left_brace = true
ij_php_space_before_unary_not = false
ij_php_space_before_while_keyword = true
ij_php_space_before_while_left_brace = true
ij_php_space_before_while_parentheses = true
ij_php_space_between_ternary_quest_and_colon = false
ij_php_spaces_around_additive_operators = true
ij_php_spaces_around_arrow = false
ij_php_spaces_around_assignment_in_declare = false
ij_php_spaces_around_assignment_operators = true
ij_php_spaces_around_bitwise_operators = true
ij_php_spaces_around_equality_operators = true
ij_php_spaces_around_logical_operators = true
ij_php_spaces_around_multiplicative_operators = true
ij_php_spaces_around_null_coalesce_operator = true
ij_php_spaces_around_relational_operators = true
ij_php_spaces_around_shift_operators = true
ij_php_spaces_around_unary_operator = false
ij_php_spaces_around_var_within_brackets = false
ij_php_spaces_within_array_initializer_braces = false
ij_php_spaces_within_brackets = false
ij_php_spaces_within_catch_parentheses = false
ij_php_spaces_within_for_parentheses = false
ij_php_spaces_within_if_parentheses = false
ij_php_spaces_within_method_call_parentheses = false
ij_php_spaces_within_method_parentheses = false
ij_php_spaces_within_parentheses = false
ij_php_spaces_within_short_echo_tags = true
ij_php_spaces_within_switch_parentheses = false
ij_php_spaces_within_while_parentheses = false
ij_php_special_else_if_treatment = false
ij_php_subpackage_weight = 28
ij_php_ternary_operation_signs_on_next_line = false
ij_php_ternary_operation_wrap = off
ij_php_throws_weight = 6
ij_php_todo_weight = 28
ij_php_unknown_tag_weight = 28
ij_php_upper_case_boolean_const = false
ij_php_upper_case_null_const = false
ij_php_uses_weight = 28
ij_php_var_weight = 28
ij_php_variable_naming_style = mixed
ij_php_version_weight = 28
ij_php_while_brace_force = always
ij_php_while_on_new_line = false
[{*.sht,*.htm,*.html,*.shtm,*.shtml}]
[{*.sht,*.html,*.shtm,*.shtml,*.htm,*.ng}]
indent_style = tab
ij_smart_tabs = true
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
@@ -510,185 +467,20 @@ ij_html_space_around_equality_in_attribute = false
ij_html_space_inside_empty_tag = false
ij_html_text_wrap = normal
[{*.ts,*.ats}]
ij_continuation_indent_size = 4
ij_typescript_align_imports = false
ij_typescript_align_multiline_array_initializer_expression = false
ij_typescript_align_multiline_binary_operation = false
ij_typescript_align_multiline_chained_methods = false
ij_typescript_align_multiline_extends_list = false
ij_typescript_align_multiline_for = true
ij_typescript_align_multiline_parameters = true
ij_typescript_align_multiline_parameters_in_calls = false
ij_typescript_align_multiline_ternary_operation = false
ij_typescript_align_object_properties = 0
ij_typescript_align_union_types = false
ij_typescript_align_var_statements = 0
ij_typescript_array_initializer_new_line_after_left_brace = false
ij_typescript_array_initializer_right_brace_on_new_line = false
ij_typescript_array_initializer_wrap = off
ij_typescript_assignment_wrap = off
ij_typescript_binary_operation_sign_on_next_line = false
ij_typescript_binary_operation_wrap = off
ij_typescript_blacklist_imports = rxjs/Rx,node_modules/**/*
ij_typescript_blank_lines_after_imports = 1
ij_typescript_blank_lines_around_class = 1
ij_typescript_blank_lines_around_field = 0
ij_typescript_blank_lines_around_field_in_interface = 0
ij_typescript_blank_lines_around_function = 1
ij_typescript_blank_lines_around_method = 1
ij_typescript_blank_lines_around_method_in_interface = 1
ij_typescript_block_brace_style = end_of_line
ij_typescript_call_parameters_new_line_after_left_paren = false
ij_typescript_call_parameters_right_paren_on_new_line = false
ij_typescript_call_parameters_wrap = off
ij_typescript_catch_on_new_line = false
ij_typescript_chained_call_dot_on_new_line = true
ij_typescript_class_brace_style = end_of_line
ij_typescript_comma_on_new_line = false
ij_typescript_do_while_brace_force = never
ij_typescript_else_on_new_line = false
ij_typescript_enforce_trailing_comma = keep
ij_typescript_extends_keyword_wrap = off
ij_typescript_extends_list_wrap = off
ij_typescript_field_prefix = _
ij_typescript_file_name_style = relaxed
ij_typescript_finally_on_new_line = false
ij_typescript_for_brace_force = never
ij_typescript_for_statement_new_line_after_left_paren = false
ij_typescript_for_statement_right_paren_on_new_line = false
ij_typescript_for_statement_wrap = off
ij_typescript_force_quote_style = false
ij_typescript_force_semicolon_style = false
ij_typescript_function_expression_brace_style = end_of_line
ij_typescript_if_brace_force = never
ij_typescript_import_merge_members = global
ij_typescript_import_prefer_absolute_path = global
ij_typescript_import_sort_members = true
ij_typescript_import_sort_module_name = false
ij_typescript_import_use_node_resolution = true
ij_typescript_imports_wrap = on_every_item
ij_typescript_indent_case_from_switch = true
ij_typescript_indent_chained_calls = true
ij_typescript_indent_package_children = 0
ij_typescript_jsdoc_include_types = false
ij_typescript_jsx_attribute_value = braces
ij_typescript_keep_blank_lines_in_code = 2
ij_typescript_keep_first_column_comment = true
ij_typescript_keep_indents_on_empty_lines = false
ij_typescript_keep_line_breaks = true
ij_typescript_keep_simple_blocks_in_one_line = false
ij_typescript_keep_simple_methods_in_one_line = false
ij_typescript_line_comment_add_space = true
ij_typescript_line_comment_at_first_column = false
ij_typescript_method_brace_style = end_of_line
ij_typescript_method_call_chain_wrap = off
ij_typescript_method_parameters_new_line_after_left_paren = false
ij_typescript_method_parameters_right_paren_on_new_line = false
ij_typescript_method_parameters_wrap = off
ij_typescript_object_literal_wrap = on_every_item
ij_typescript_parentheses_expression_new_line_after_left_paren = false
ij_typescript_parentheses_expression_right_paren_on_new_line = false
ij_typescript_place_assignment_sign_on_next_line = false
ij_typescript_prefer_as_type_cast = false
ij_typescript_prefer_parameters_wrap = false
ij_typescript_reformat_c_style_comments = false
ij_typescript_space_after_colon = true
ij_typescript_space_after_comma = true
ij_typescript_space_after_dots_in_rest_parameter = false
ij_typescript_space_after_generator_mult = true
ij_typescript_space_after_property_colon = true
ij_typescript_space_after_quest = true
ij_typescript_space_after_type_colon = true
ij_typescript_space_after_unary_not = false
ij_typescript_space_before_async_arrow_lparen = true
ij_typescript_space_before_catch_keyword = true
ij_typescript_space_before_catch_left_brace = true
ij_typescript_space_before_catch_parentheses = true
ij_typescript_space_before_class_lbrace = true
ij_typescript_space_before_class_left_brace = true
ij_typescript_space_before_colon = true
ij_typescript_space_before_comma = false
ij_typescript_space_before_do_left_brace = true
ij_typescript_space_before_else_keyword = true
ij_typescript_space_before_else_left_brace = true
ij_typescript_space_before_finally_keyword = true
ij_typescript_space_before_finally_left_brace = true
ij_typescript_space_before_for_left_brace = true
ij_typescript_space_before_for_parentheses = true
ij_typescript_space_before_for_semicolon = false
ij_typescript_space_before_function_left_parenth = true
ij_typescript_space_before_generator_mult = false
ij_typescript_space_before_if_left_brace = true
ij_typescript_space_before_if_parentheses = true
ij_typescript_space_before_method_call_parentheses = false
ij_typescript_space_before_method_left_brace = true
ij_typescript_space_before_method_parentheses = false
ij_typescript_space_before_property_colon = false
ij_typescript_space_before_quest = true
ij_typescript_space_before_switch_left_brace = true
ij_typescript_space_before_switch_parentheses = true
ij_typescript_space_before_try_left_brace = true
ij_typescript_space_before_type_colon = false
ij_typescript_space_before_unary_not = false
ij_typescript_space_before_while_keyword = true
ij_typescript_space_before_while_left_brace = true
ij_typescript_space_before_while_parentheses = true
ij_typescript_spaces_around_additive_operators = true
ij_typescript_spaces_around_arrow_function_operator = true
ij_typescript_spaces_around_assignment_operators = true
ij_typescript_spaces_around_bitwise_operators = true
ij_typescript_spaces_around_equality_operators = true
ij_typescript_spaces_around_logical_operators = true
ij_typescript_spaces_around_multiplicative_operators = true
ij_typescript_spaces_around_relational_operators = true
ij_typescript_spaces_around_shift_operators = true
ij_typescript_spaces_around_unary_operator = false
ij_typescript_spaces_within_array_initializer_brackets = false
ij_typescript_spaces_within_brackets = false
ij_typescript_spaces_within_catch_parentheses = false
ij_typescript_spaces_within_for_parentheses = false
ij_typescript_spaces_within_if_parentheses = false
ij_typescript_spaces_within_imports = false
ij_typescript_spaces_within_interpolation_expressions = false
ij_typescript_spaces_within_method_call_parentheses = false
ij_typescript_spaces_within_method_parentheses = false
ij_typescript_spaces_within_object_literal_braces = false
ij_typescript_spaces_within_object_type_braces = true
ij_typescript_spaces_within_parentheses = false
ij_typescript_spaces_within_switch_parentheses = false
ij_typescript_spaces_within_type_assertion = false
ij_typescript_spaces_within_union_types = true
ij_typescript_spaces_within_while_parentheses = false
ij_typescript_special_else_if_treatment = true
ij_typescript_ternary_operation_signs_on_next_line = false
ij_typescript_ternary_operation_wrap = off
ij_typescript_union_types_wrap = on_every_item
ij_typescript_use_chained_calls_group_indents = false
ij_typescript_use_double_quotes = true
ij_typescript_use_explicit_js_extension = global
ij_typescript_use_path_mapping = always
ij_typescript_use_public_modifier = false
ij_typescript_use_semicolon_after_statement = true
ij_typescript_var_declaration_wrap = normal
ij_typescript_while_brace_force = never
ij_typescript_while_on_new_line = false
ij_typescript_wrap_comments = false
[{*.yml,*.yaml}]
indent_size = 2
ij_continuation_indent_size = 2
ij_yaml_keep_indents_on_empty_lines = false
ij_yaml_keep_line_breaks = true
[{*.zsh,*.bash,*.sh}]
[{*.zsh,*.sh,*.bash}]
ij_shell_binary_ops_start_line = false
ij_shell_keep_column_alignment_padding = false
ij_shell_minify_program = false
ij_shell_redirect_followed_by_space = false
ij_shell_switch_cases_indented = false
[{.stylelintrc,.eslintrc,.babelrc,jest.config,*.bowerrc,*.jsb3,*.jsb2,*.json}]
[{.babelrc,.stylelintrc,.eslintrc,jest.config,*.json,*.jsb3,*.jsb2,*.bowerrc}]
indent_size = 2
ij_json_keep_blank_lines_in_code = 0
ij_json_keep_indents_on_empty_lines = false
@@ -701,7 +493,7 @@ ij_json_spaces_within_braces = false
ij_json_spaces_within_brackets = false
ij_json_wrap_long_lines = false
[{phpunit.xml.dist,*.jhm,*.rng,*.wsdl,*.fxml,*.xslt,*.jrxml,*.ant,*.xul,*.xsl,*.xsd,*.tld,*.jnlp,*.xml}]
[{phpunit.xml.dist,*.xslt,*.xul,*.rng,*.xsl,*.xsd,*.ant,*.jhm,*.tld,*.fxml,*.wsdl,*.jrxml,*.xml,*.jnlp}]
indent_size = 2
indent_style = tab
tab_width = 2

1
.gitignore vendored
View File

@@ -140,3 +140,4 @@ local.properties
.scala_dependencies
.worksheet
/css/setup.css

View File

@@ -2,6 +2,12 @@
<profile version="1.0">
<option name="myName" value="Combodo" />
<inspection_tool class="CascadeStringReplacementInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CucumberExamplesColon" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CucumberMissedExamples" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="CucumberTableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="CucumberUndefinedStep" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicateKeyInSection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="DuplicateSectionInFile" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ForgottenDebugOutputInspection" enabled="true" level="ERROR" enabled_by_default="true">
<option name="configuration">
<list>
@@ -68,11 +74,17 @@
</option>
<option name="migratedIntoUserSpace" value="true" />
</inspection_tool>
<inspection_tool class="GherkinBrokenTableInspection" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="GherkinMisplacedBackground" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="GherkinScenarioToScenarioOutline" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="HtmlRequiredAltAttribute" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="HtmlRequiredLangAttribute" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="InconsistentLineSeparators" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="IsNullFunctionUsageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LessResolvedByNameOnly" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="LessUnresolvedMixin" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="LessUnresolvedVariable" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="MysqlParsingInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="NodeModulesDependencies" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="PhpComposerExtensionStubsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="PhpIncludeInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpMethodParametersCountMismatchInspection" enabled="true" level="ERROR" enabled_by_default="true" />
@@ -84,7 +96,6 @@
<option name="DONT_REPORT_MULTI_RESOLVE" value="true" />
</inspection_tool>
<inspection_tool class="PhpUndefinedMethodInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnhandledExceptionInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
<inspection_tool class="PhpUnusedLocalVariableInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="DONT_REPORT_INSIDE_LIST" value="true" />
</inspection_tool>
@@ -146,6 +157,8 @@
</list>
</option>
</inspection_tool>
<inspection_tool class="ShellCheck" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="SlowArrayOperationsInLoopInspection" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SqlAddNotNullColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAmbiguousColumnInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlAutoIncrementDuplicateInspection" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -167,5 +180,30 @@
<inspection_tool class="SqlStorageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TaskProblemsInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptAbstractClassConstructorCanBeMadeProtected" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptAccessibilityCheck" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptCheckImport" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="TypeScriptConfig" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptDuplicateUnionOrIntersectionType" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptExplicitMemberType" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="TypeScriptFieldCanBeMadeReadonly" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptLibrary" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="TypeScriptMissingAugmentationImport" enabled="false" level="INFORMATION" enabled_by_default="false" />
<inspection_tool class="TypeScriptMissingConfigOption" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptRedundantGenericType" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptSmartCast" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptSuspiciousConstructorParameterAssignment" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptUMDGlobal" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptUnresolvedFunction" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptUnresolvedVariable" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptValidateGenericTypes" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="TypeScriptValidateJSTypes" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
<inspection_tool class="TypeScriptValidateTypes" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="UnresolvedReference" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="XsltDeclarations" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="XsltTemplateInvocation" enabled="false" level="ERROR" enabled_by_default="false" />
<inspection_tool class="XsltUnusedDeclaration" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="XsltVariableShadowing" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env bash
set -x
# create target dirs
mkdir -p var
mkdir -p toolkit
# cleanup target dirs
rm -rf toolkit/*
# fill target dirs
curl https://www.combodo.com/documentation/iTopDataModelToolkit-2.3.zip > toolkit.zip
unzip toolkit.zip
rm toolkit.zip
cp -r .jenkins/configuration/default-environment/unattended_install/* toolkit

View File

@@ -1,11 +0,0 @@
#!/usr/bin/env bash
set -x
# on the root dir
# composer install -a # => Not needed anymore (libs were added to git with N°2435)
# under the test dir
cd test
composer install

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -x
whoami
pwd
ls
echo "$BRANCH_NAME:${BRANCH_NAME}"
echo "printenv :"
printenv

View File

@@ -1,41 +0,0 @@
#!/usr/bin/env bash
set -x
cd test
export DEBUG_UNIT_TEST=0
RUN_NONREG_TESTS=0
#USAGE ${debugMode} ${runNonRegOQLTests} "${coverture}" "${testFile}"
if [ $# -ge 1 -a "x$1" == "xtrue" ]
then
export DEBUG_UNIT_TEST=1
else
export DEBUG_UNIT_TEST=0
fi
set -x
OPTION=""
if [ $# -ge 3 -a "x$3" == "xtrue" ]
then
##coverture
OPTION="-dxdebug.coverage_enable=1 --coverage-clover ../var/test/coverage.xml"
fi
TESTFILE="$4"
if [ "x$TESTFILE" != "x" ]
then
# shellcheck disable=SC2001
TESTFILE=$(echo "$TESTFILE" | sed 's|test/||1')
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml $OPTION $TESTFILE --teamcity
exit 0
fi
if [ $# -ge 2 -a "x$2" == "xtrue" ]
then
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml $OPTION --teamcity
else
#echo php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml --teamcity
php vendor/bin/phpunit --log-junit ../var/test/phpunit-log.junit.xml $OPTION --exclude-group OQL --teamcity
fi

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env bash
set -x
chmod 666 conf/production/config-itop.php
cd toolkit
php unattended_install.php --response_file=default-params.xml --clean=true

View File

@@ -1,284 +0,0 @@
<?php
/**
*
* Configuration file, generated by the iTop configuration wizard
*
* The file is used in MetaModel::LoadConfig() which does all the necessary initialization job
*
*/
$MySettings = array(
// access_message: Message displayed to the users when there is any access restriction
// default: 'iTop is temporarily frozen, please wait... (the admin team)'
'access_message' => 'iTop is temporarily frozen, please wait... (the admin team)',
// access_mode: Access mode: ACCESS_READONLY = 0, ACCESS_ADMIN_WRITE = 2, ACCESS_FULL = 3
// default: 3
'access_mode' => 3,
'allowed_login_types' => 'form|basic|external',
// apc_cache.enabled: If set, the APC cache is allowed (the PHP extension must also be active)
// default: true
'apc_cache.enabled' => true,
// apc_cache.query_ttl: Time to live set in APC for the prepared queries (seconds - 0 means no timeout)
// default: 3600
'apc_cache.query_ttl' => 3600,
// app_root_url: Root URL used for navigating within the application, or from an email to the application (you can put $SERVER_NAME$ as a placeholder for the server's name)
// default: ''
'app_root_url' => 'http://127.0.0.1/itop/svn/trunk/',
// buttons_position: Position of the forms buttons: bottom | top | both
// default: 'both'
'buttons_position' => 'both',
// cas_include_path: The path where to find the phpCAS library
// default: '/usr/share/php'
'cas_include_path' => '/usr/share/php',
// cron_max_execution_time: Duration (seconds) of the page cron.php, must be shorter than php setting max_execution_time and shorter than the web server response timeout
// default: 600
'cron_max_execution_time' => 600,
// csv_file_default_charset: Character set used by default for downloading and uploading data as a CSV file. Warning: it is case sensitive (uppercase is preferable).
// default: 'ISO-8859-1'
'csv_file_default_charset' => 'ISO-8859-1',
'csv_import_charsets' => array (
),
// csv_import_history_display: Display the history tab in the import wizard
// default: false
'csv_import_history_display' => false,
// date_and_time_format: Format for date and time display (per language)
// default: array (
// 'default' =>
// array (
// 'date' => 'Y-m-d',
// 'time' => 'H:i:s',
// 'date_time' => '$date $time',
// ),
// )
'date_and_time_format' => array (
'default' =>
array (
'date' => 'Y-m-d',
'time' => 'H:i:s',
'date_time' => '$date $time',
),
'FR FR' =>
array (
'date' => 'd/m/Y',
'time' => 'H:i:s',
'date_time' => '$date $time',
),
),
'db_host' => '',
'db_name' => 'itop_ci',
'db_pwd' => 'IKnowYouSeeMeInJenkinsConf',
'db_subname' => '',
'db_user' => 'jenkins_itop',
// deadline_format: The format used for displaying "deadline" attributes: any string with the following placeholders: $date$, $difference$
// default: '$difference$'
'deadline_format' => '$difference$',
'default_language' => 'EN US',
// draft_attachments_lifetime: Lifetime (in seconds) of drafts' attachments and inline images: after this duration, the garbage collector will delete them.
// default: 3600
'draft_attachments_lifetime' => 3600,
// email_asynchronous: If set, the emails are sent off line, which requires cron.php to be activated. Exception: some features like the email test utility will force the serialized mode
// default: false
'email_asynchronous' => false,
// email_default_sender_address: Default address provided in the email from header field.
// default: ''
'email_default_sender_address' => '',
// email_default_sender_label: Default label provided in the email from header field.
// default: ''
'email_default_sender_label' => '',
// email_transport: Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocole)
// default: 'PHPMail'
'email_transport' => 'SMTP',
// email_transport_smtp.host: host name or IP address (optional)
// default: 'localhost'
'email_transport_smtp.host' => 'smtp.combodo.com',
// email_transport_smtp.password: Authentication password (optional)
// default: ''
'email_transport_smtp.password' => 'IDoNotWork',
// email_transport_smtp.port: port number (optional)
// default: 25
'email_transport_smtp.port' => 25,
// email_transport_smtp.username: Authentication user (optional)
// default: ''
'email_transport_smtp.username' => 'test2@combodo.com',
// email_validation_pattern: Regular expression to validate/detect the format of an eMail address
// default: '[a-zA-Z0-9._&\'-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z0-9-]{2,}'
'email_validation_pattern' => '[a-zA-Z0-9._&\'-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z0-9-]{2,}',
'encryption_key' => '@iT0pEncr1pti0n!',
'ext_auth_variable' => '$_SERVER[\'REMOTE_USER\']',
'fast_reload_interval' => '60',
// graphviz_path: Path to the Graphviz "dot" executable for graphing objects lifecycle
// default: '/usr/bin/dot'
'graphviz_path' => '/usr/bin/dot',
// inline_image_max_display_width: The maximum width (in pixels) when displaying images inside an HTML formatted attribute. Images will be displayed using this this maximum width.
// default: '250'
'inline_image_max_display_width' => 250,
// inline_image_max_storage_width: The maximum width (in pixels) when uploading images to be used inside an HTML formatted attribute. Images larger than the given size will be downsampled before storing them in the database.
// default: '1600'
'inline_image_max_storage_width' => 1600,
// link_set_attribute_qualifier: Link set from string: attribute qualifier (encloses both the attcode and the value)
// default: '\''
'link_set_attribute_qualifier' => '\'',
// link_set_attribute_separator: Link set from string: attribute separator
// default: ';'
'link_set_attribute_separator' => ';',
// link_set_item_separator: Link set from string: line separator
// default: '|'
'link_set_item_separator' => '|',
// link_set_value_separator: Link set from string: value separator (between the attcode and the value itself
// default: ':'
'link_set_value_separator' => ':',
'log_global' => true,
'log_issue' => true,
'log_notification' => true,
'log_web_service' => true,
// max_combo_length: The maximum number of elements in a drop-down list. If more then an autocomplete will be used
// default: 50
'max_combo_length' => 50,
'max_display_limit' => '15',
// max_linkset_output: Maximum number of items shown when getting a list of related items in an email, using the form $this->some_list$. 0 means no limit.
// default: 100
'max_linkset_output' => 100,
'min_display_limit' => '10',
// online_help: Hyperlink to the online-help web page
// default: 'http://www.combodo.com/itop-help'
'online_help' => 'http://www.combodo.com/itop-help',
// php_path: Path to the php executable in CLI mode
// default: 'php'
'php_path' => 'php',
// portal_tickets: CSV list of classes supported in the portal
// default: 'UserRequest'
'portal_tickets' => 'UserRequest',
'query_cache_enabled' => true,
// search_manual_submit: Force manual submit of search requests (class => true)
// default: false
'search_manual_submit' => array (
'Person' => true,
),
'secure_connection_required' => false,
// session_name: The name of the cookie used to store the PHP session id
// default: 'iTop'
'session_name' => 'iTop',
// shortcut_actions: Actions that are available as direct buttons next to the "Actions" menu
// default: 'UI:Menu:Modify,UI:Menu:New'
'shortcut_actions' => 'UI:Menu:Modify,UI:Menu:New',
// source_dir: Source directory for the datamodel files. (which gets compiled to env-production).
// default: ''
'source_dir' => 'datamodels/2.x/',
'standard_reload_interval' => '300',
// synchro_trace: Synchronization details: none, display, save (includes 'display')
// default: 'none'
'synchro_trace' => 'none',
// timezone: Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitely configured in PHP
// default: 'Europe/Paris'
'timezone' => 'Europe/Paris',
// tracking_level_linked_set_default: Default tracking level if not explicitely set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)
// default: 1
'tracking_level_linked_set_default' => 0,
// url_validation_pattern: Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)
// default: '(https?|ftp)\\://([a-zA-Z0-9+!*(),;?&=\\$_.-]+(\\:[a-zA-Z0-9+!*(),;?&=\\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\\:[0-9]{2,5})?(/([a-zA-Z0-9%+\\$_-]\\.?)+)*/?(\\?[a-zA-Z+&\\$_.-][a-zA-Z0-9;:[\\]@&%=+/\\$_.-]*)?(#[a-zA-Z_.-][a-zA-Z0-9+\\$_.-]*)?'
'url_validation_pattern' => '(https?|ftp)\\://([a-zA-Z0-9+!*(),;?&=\\$_.-]+(\\:[a-zA-Z0-9+!*(),;?&=\\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\\:[0-9]{2,5})?(/([a-zA-Z0-9%+\\$_-]\\.?)+)*/?(\\?[a-zA-Z+&\\$_.-][a-zA-Z0-9;:[\\]@&%=+/\\$_.-]*)?(#[a-zA-Z_.-][a-zA-Z0-9+\\$_.-]*)?',
);
/**
*
* Modules specific settings
*
*/
$MyModuleSettings = array(
'authent-local' => array (
'password_validation.pattern' => '',
),
'itop-attachments' => array (
'allowed_classes' => array (
0 => 'Ticket',
),
'position' => 'relations',
'preview_max_width' => 290,
),
'itop-backup' => array (
'mysql_bindir' => '',
'week_days' => 'monday, tuesday, wednesday, thursday, friday',
'time' => '23:30',
'retention_count' => 5,
'enabled' => true,
'debug' => false,
),
'molkobain-console-tooltips' => array (
'decoration_class' => 'fas fa-question',
'enabled' => true,
),
);
/**
*
* Data model modules to be loaded. Names are specified as relative paths
*
*/
$MyModules = array(
'addons' => array (
'user rights' => 'addons/userrights/userrightsprofile.class.inc.php',
),
);
?>

View File

@@ -1,208 +0,0 @@
<?php
/**
* Copyright (C) 2013-2019 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
//this scrit will be run under the ./toolkit directory, relatively to the document root
require_once('../approot.inc.php');
require_once(APPROOT.'/application/utils.inc.php');
require_once(APPROOT.'/application/clipage.class.inc.php');
require_once(APPROOT.'/core/config.class.inc.php');
require_once(APPROOT.'/core/log.class.inc.php');
require_once(APPROOT.'/core/kpi.class.inc.php');
require_once(APPROOT.'/core/cmdbsource.class.inc.php');
require_once(APPROOT.'/setup/setuppage.class.inc.php');
require_once(APPROOT.'/setup/wizardcontroller.class.inc.php');
require_once(APPROOT.'/setup/wizardsteps.class.inc.php');
require_once(APPROOT.'/setup/applicationinstaller.class.inc.php');
/////////////////////////////////////////////////
$sParamFile = utils::ReadParam('response_file', 'default-params.xml', true /* CLI allowed */, 'raw_data');
$bCheckConsistency = (utils::ReadParam('check_consistency', '0', true /* CLI allowed */) == '1');
$oParams = new XMLParameters($sParamFile);
$sMode = $oParams->Get('mode');
if ($sMode == 'install')
{
echo "Installation mode detected.\n";
$bClean = utils::ReadParam('clean', false, true /* CLI allowed */);
if ($bClean)
{
echo "Cleanup mode detected.\n";
$sTargetEnvironment = $oParams->Get('target_env', '');
if ($sTargetEnvironment == '')
{
$sTargetEnvironment = 'production';
}
$sTargetDir = APPROOT.'env-'.$sTargetEnvironment;
// Configuration file
$sConfigFile = APPCONF.$sTargetEnvironment.'/'.ITOP_CONFIG_FILE;
if (file_exists($sConfigFile))
{
echo "Trying to delete the configuration file: '$sConfigFile'.\n";
@chmod($sConfigFile, 0770); // RWX for owner and group, nothing for others
unlink($sConfigFile);
}
else
{
echo "No config file to delete ($sConfigFile does not exist).\n";
}
// env-xxx directory
if (file_exists($sTargetDir))
{
if (is_dir($sTargetDir))
{
echo "Emptying the target directory '$sTargetDir'.\n";
SetupUtils::tidydir($sTargetDir);
}
else
{
die("ERROR the target dir '$sTargetDir' exists, but is NOT a directory !!!\nExiting.\n");
}
}
else
{
echo "No target directory to delete ($sTargetDir does not exist).\n";
}
// Database
$aDBSettings = $oParams->Get('database', array());
$sDBServer = $aDBSettings['server'];
$sDBUser = $aDBSettings['user'];
$sDBPwd = $aDBSettings['pwd'];
$sDBName = $aDBSettings['name'];
$sDBPrefix = $aDBSettings['prefix'];
if ($sDBPrefix != '')
{
die("Cleanup not implemented for a partial database (prefix= '$sDBPrefix')\nExiting.");
}
$oMysqli = new mysqli($sDBServer, $sDBUser, $sDBPwd);
if ($oMysqli->connect_errno)
{
die("Cannot connect to the MySQL server (".$oMysqli->connect_errno . ") ".$oMysqli->connect_error."\nExiting");
}
else
{
if ($oMysqli->select_db($sDBName))
{
echo "Deleting database '$sDBName'\n";
$oMysqli->query("DROP DATABASE `$sDBName`");
}
else
{
echo "The database '$sDBName' does not seem to exist. Nothing to cleanup.\n";
}
}
}
}
$bHasErrors = false;
$aChecks = SetupUtils::CheckBackupPrerequisites(APPROOT.'data'); // mmm should be the backup destination dir
$aSelectedModules = $oParams->Get('selected_modules');
$sSourceDir = $oParams->Get('source_dir', 'datamodels/latest');
$sExtensionDir = $oParams->Get('extensions_dir', 'extensions');
$aChecks = array_merge($aChecks, SetupUtils::CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules));
foreach($aChecks as $oCheckResult)
{
switch($oCheckResult->iSeverity)
{
case CheckResult::ERROR:
$bHasErrors = true;
$sHeader = "Error";
break;
case CheckResult::WARNING:
$sHeader = "Warning";
break;
case CheckResult::INFO:
default:
$sHeader = "Info";
break;
}
echo $sHeader.": ".$oCheckResult->sLabel;
if (strlen($oCheckResult->sDescription))
{
echo ' - '.$oCheckResult->sDescription;
}
echo "\n";
}
if ($bHasErrors)
{
echo "Encountered stopper issues. Aborting...\n";
die;
}
$bFoundIssues = false;
$bInstall = utils::ReadParam('install', true, true /* CLI allowed */);
if ($bInstall)
{
echo "Starting the unattended installation...\n";
$oWizard = new ApplicationInstaller($oParams);
$bRes = $oWizard->ExecuteAllSteps();
if (!$bRes)
{
echo "\nencountered installation issues!";
$bFoundIssues = true;
}
}
else
{
echo "No installation requested.\n";
}
if (!$bFoundIssues && $bCheckConsistency)
{
echo "Checking data model consistency.\n";
ob_start();
$sCheckRes = '';
try
{
MetaModel::CheckDefinitions(false);
$sCheckRes = ob_get_clean();
}
catch(Exception $e)
{
$sCheckRes = ob_get_clean()."\nException: ".$e->getMessage();
}
if (strlen($sCheckRes) > 0)
{
echo $sCheckRes;
echo "\nfound consistency issues!";
$bFoundIssues = true;
}
}
if (!$bFoundIssues)
{
// last line: used to check the install
// the only way to track issues in case of Fatal error or even parsing error!
echo "\ninstalled!";
exit;
}

View File

@@ -0,0 +1,90 @@
<?php
$iBeginTime = time();
chdir(__DIR__);
$aCommands = [
'php composer/rmDeniedTestDir.php',
'php build/commands/setupCssCompiler.php',
// 'bash /tmp/gabuzomeu.sh',
];
$aFailedCommands=[];
foreach ($aCommands as $sCommand)
{
if (!ExecCommand($sCommand))
{
$aFailedCommands[] = $sCommand;
}
}
$iElapsed = time() - $iBeginTime;
if (count($aFailedCommands))
{
fwrite(STDERR, "\nafterBuild execution failed! (in ${iElapsed}s)\n");
fwrite(STDERR, "List of failling commands:\n - " . implode("\n - ", $aFailedCommands) . "\n");
exit(1);
}
echo "\nDone (${iElapsed}s)\n";
exit(0);
/**
* Executes a command and returns an array with exit code, stdout and stderr content
*
* @param string $cmd - Command to execute
*
* @return bool
* @throws \Exception
*/
function ExecCommand($cmd) {
$iBeginTime = time();
echo sprintf("command: %s", str_pad("$cmd ", 50));
$descriptorspec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w"), // stderr
);
$process = proc_open($cmd, $descriptorspec, $pipes, __DIR__ . '/..', null);
$stdout = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$iCode = proc_close($process);
$bSuccess = (0 === $iCode);
$iElapsed = time() - $iBeginTime;
if (!$bSuccess) {
fwrite(STDERR, sprintf(
"\nCOMMAND FAILED! (%s) \n - status:%s \n - stderr:%s \n - stdout: %s\n - elapsed:%ss\n\n",
$cmd,
$iCode,
rtrim($stderr),
rtrim($stdout),
$iElapsed
));
}
else
{
echo "| elapsed:${iElapsed}s \n";
}
if (!empty($stderr))
{
fwrite(STDERR, "$stderr\n");
}
if (!empty($stdout))
{
echo "stdout :$stdout\n\n";
}
return $bSuccess;
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* Copyright (C) 2010-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http: *www.gnu.org/licenses/>
*
*/
use Combodo\iTop\Composer\iTopComposer;
$iTopFolder = __DIR__."/../../../";
require_once("$iTopFolder/approot.inc.php");
require_once(APPROOT."/application/utils.inc.php");
if (php_sapi_name() !== 'cli')
{
throw new \Exception('This script can only run from CLI');
}
$sCssFile = APPROOT.'/css/setup.css';
if (file_exists($sCssFile))
{
fwrite(STDERR, "$sCssFile already exists (it should not), removing it.");
if (!unlink($sCssFile))
{
fwrite(STDERR, "Failed to remove $sCssFile, exiting.");
exit(1);
}
}
$sCssRelPath = utils::GetCSSFromSASS('css/setup.scss');
if (!file_exists($sCssFile))
{
fwrite(STDERR, "Failed to compile $sCssFile, exiting.");
exit(1);
}

78
Jenkinsfile vendored
View File

@@ -1,73 +1,11 @@
pipeline {
agent any
parameters {
booleanParam(name: 'debugMode', defaultValue: 'false', description: 'Debug mode?')
string(name: 'testFile', defaultValue: '', description: 'Provide test file to execute. Example: test/core/LogAPITest.php')
booleanParam(name: 'coverture', defaultValue: 'false', description: 'Test coverture?')
booleanParam(name: 'runNonRegOQLTests', defaultValue: 'false', description: 'Do You want to run legacy OQL regression tests?')
}
stages {
def infra
stage('init') {
parallel {
stage('debug') {
steps {
sh './.jenkins/bin/init/debug.sh'
}
}
stage('append files to project') {
steps {
sh './.jenkins/bin/init/append_files.sh'
}
}
stage('composer install') {
steps {
sh './.jenkins/bin/init/composer_install.sh'
}
}
}
}
node(){
checkout scm
stage('unattended_install') {
parallel {
stage('unattended_install default env') {
steps {
sh './.jenkins/bin/unattended_install/default_env.sh'
}
}
}
}
stage('test') {
parallel {
stage('phpunit') {
steps {
sh './.jenkins/bin/tests/phpunit.sh ${debugMode} ${runNonRegOQLTests} "${coverture}" "${testFile}"'
}
}
}
}
}
post {
always {
archiveArtifacts allowEmptyArchive:true, excludes: '.gitkeep', artifacts: 'var/test/*.xml'
junit 'var/test/phpunit-log.junit.xml'
}
failure {
slackSend(channel: "#jenkins-itop", color: '#FF0000', message: "Ho no! Build failed! (${currentBuild.result}), Job '${env.JOB_NAME_UNESCAPED} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
}
fixed {
slackSend(channel: "#jenkins-itop", color: '#FFa500', message: "Yes! Build repaired! (${currentBuild.result}), Job '${env.JOB_NAME_UNESCAPED} [${env.BUILD_NUMBER}]' (${env.BUILD_URL})")
}
}
environment {
DEBUG_UNIT_TEST = '0'
JOB_NAME_UNESCAPED = env.JOB_NAME.replaceAll("%2F", "/")
}
options {
timeout(time: 20, unit: 'MINUTES')
}
infra = load '/var/lib/jenkins/workspace/itop-test-infra_master/src/Infra.groovy'
}
infra.call()

View File

@@ -78,10 +78,10 @@ We would like to give a special thank you to the people from the community who c
- Alves, David
- Beck, Pedro
- Bilger, Jean-François
- Bostoen, Jeffrey
- Bostoen, Jeffrey (a.k.a @jbostoen)
- Cardoso, Anderson
- Cassaro, Bruno
- Casteleyn, Thomas
- Casteleyn, Thomas (a.k.a @Hipska)
- Castro, Randall Badilla
- Colantoni, Maria Laura
- Couronné, Guy
@@ -97,6 +97,7 @@ We would like to give a special thank you to the people from the community who c
- Lazcano, Federico
- Lucas, Jonathan
- Malik, Remie
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
- Rosenke, Stephan
- Seki, Shoji
- Shilov, Vladimir

View File

@@ -9,7 +9,7 @@ responsible disclosure and will make every effort to acknowledge your contributi
### iTop vulnerabilities
Please send a procedure to reproduce iTop vulnerabilities to [itop-security@combodo.com](mailto:itop-security@combodo.com).
You can send us a standard "given / then / when" report, including iTop version, impacts, and maybe installed modules or data if they are
You can send us a standard "given / when / then" report, including iTop version, impacts, and maybe installed modules or data if they are
needed to reproduce.
### Dependencies vulnerabilities

View File

@@ -434,7 +434,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Support drastic data model changes: no organization class (or not writable)!
if (MetaModel::IsValidClass('Organization') && !MetaModel::IsAbstract('Organization'))
{
$oOrg = new Organization();
$oOrg = MetaModel::NewObject('Organization');
$oOrg->Set('name', 'My Company/Department');
$oOrg->Set('code', 'SOMECODE');
$iOrgId = $oOrg->DBInsertNoReload();
@@ -442,17 +442,13 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Support drastic data model changes: no Person class (or not writable)!
if (MetaModel::IsValidClass('Person') && !MetaModel::IsAbstract('Person'))
{
$oContact = new Person();
$oContact = MetaModel::NewObject('Person');
$oContact->Set('name', 'My last name');
$oContact->Set('first_name', 'My first name');
if (MetaModel::IsValidAttCode('Person', 'org_id'))
{
$oContact->Set('org_id', $iOrgId);
}
if (MetaModel::IsValidAttCode('Person', 'phone'))
{
$oContact->Set('phone', '+00 000 000 000');
}
$oContact->Set('email', 'my.email@foo.org');
$iContactId = $oContact->DBInsertNoReload();
}
@@ -561,7 +557,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
/**
* @param $oUser User
* @return array
* @return bool
*/
public function IsAdministrator($oUser)
{
@@ -571,16 +567,22 @@ class UserRightsProfile extends UserRightsAddOnAPI
/**
* @param $oUser User
* @return array
* @return bool
*/
public function IsPortalUser($oUser)
{
// UserRights caches the list for us
return UserRights::HasProfile(PORTAL_PROFILE_NAME, $oUser);
}
/**
* @param $oUser User
* @return bool
*
* @return array
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*/
public function ListProfiles($oUser)
{

View File

@@ -535,7 +535,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Support drastic data model changes: no organization class (or not writable)!
if (MetaModel::IsValidClass('Organization') && !MetaModel::IsAbstract('Organization'))
{
$oOrg = new Organization();
$oOrg = MetaModel::NewObject('Organization');
$oOrg->Set('name', 'My Company/Department');
$oOrg->Set('code', 'SOMECODE');
$oOrg::SetCurrentChange($oChange);
@@ -544,17 +544,13 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Support drastic data model changes: no Person class (or not writable)!
if (MetaModel::IsValidClass('Person') && !MetaModel::IsAbstract('Person'))
{
$oContact = new Person();
$oContact = MetaModel::NewObject('Person');
$oContact->Set('name', 'My last name');
$oContact->Set('first_name', 'My first name');
if (MetaModel::IsValidAttCode('Person', 'org_id'))
{
$oContact->Set('org_id', $iOrgId);
}
if (MetaModel::IsValidAttCode('Person', 'phone'))
{
$oContact->Set('phone', '+00 000 000 000');
}
$oContact->Set('email', 'my.email@foo.org');
$oContact::SetCurrentChange($oChange);
$iContactId = $oContact->DBInsertNoReload();
@@ -711,7 +707,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
public function LoadCache()
{
if (!is_null($this->m_aProfiles)) return;
if (!is_null($this->m_aProfiles)) return false;
// Could be loaded in a shared memory (?)
$oKPI = new ExecutionKPI();

View File

@@ -30,8 +30,11 @@ function mb_str_replace($search, $replace, $subject, &$count = 0) {
$replacements = array_pad($replacements, count($searches), '');
foreach ($searches as $key => $search) {
$parts = mb_split(preg_quote($search), $subject);
$count += count($parts) - 1;
$subject = implode($replacements[$key], $parts);
if (is_countable($parts))
{
$count += count($parts) - 1;
$subject = implode($replacements[$key], $parts);
}
}
} else {
// Call mb_str_replace for each subject in array, recursively

View File

@@ -200,7 +200,15 @@ class ApplicationContext
}
return implode("&", $aParams);
}
/**
* @since 2.8.0 N°2534 - dashboard: bug with autorefresh that deactivates filtering on organisation
* Returns the params as c[menu]:..., c[org_id]:....
* @return string The params
*/
public function GetForPostParams()
{
return json_encode( $this->aValues);
}
/**
* Returns the context as sequence of input tags to be inserted inside a <form> tag
* @return string The context as a sequence of <input type="hidden" /> tags

View File

@@ -663,7 +663,30 @@ EOF
{
// n:n links
$oLinkingAttDef = MetaModel::GetAttributeDef($sLinkedClass, $oAttDef->GetExtKeyToRemote());
$sLinkingAttCode = $oLinkingAttDef->GetCode();
$sTargetClass = $oLinkingAttDef->GetTargetClass();
// N°2334 fields to display for n:n relations
$aLnkAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectLinkClass($sClass, $sAttCode);
$aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($sTargetClass);
$aLnkAttCodesToDisplay = array_map(function ($oLnkAttDef) {
return ormLinkSet::LINK_ALIAS.'.'.$oLnkAttDef->GetCode();
},
$aLnkAttDefsToDisplay
);
if (!in_array(ormLinkSet::LINK_ALIAS.'.'.$sLinkingAttCode, $aLnkAttCodesToDisplay))
{
// we need to display a link to the remote class instance !
$aLnkAttCodesToDisplay[] = ormLinkSet::LINK_ALIAS.'.'.$sLinkingAttCode;
}
$aRemoteAttCodesToDisplay = array_map(function ($oRemoteAttDef) {
return ormLinkSet::REMOTE_ALIAS.'.'.$oRemoteAttDef->GetCode();
},
$aRemoteAttDefsToDisplay
);
$aAttCodesToDisplay = array_merge($aLnkAttCodesToDisplay, $aRemoteAttCodesToDisplay);
$sAttCodesToDisplay = implode(',', $aAttCodesToDisplay);
$aParams = array(
'link_attr' => $oAttDef->GetExtKeyToMe(),
'object_id' => $this->GetKey(),
@@ -671,8 +694,12 @@ EOF
'view_link' => false,
'menu' => false,
//'menu_actions_target' => '_blank',
'display_limit' => true, // By default limit the list to speed up the initial load & display
// By default limit the list to speed up the initial load & display
'display_limit' => true,
'table_id' => $sClass.'_'.$sAttCode,
// N°2334 specify fields to display for n:n relations
'zlist' => false,
'extra_fields' => $sAttCodesToDisplay,
);
}
$oPage->p(MetaModel::GetClassIcon($sTargetClass)."&nbsp;".$oAttDef->GetDescription());
@@ -1286,7 +1313,14 @@ HTML
/**
* @param \WebPage $oPage
* @param \CMDBObjectSet $oSet
* @param array $aExtraParams
* @param array $aExtraParams key used :
* <ul>
* <li>view_link : if true then for extkey will display links with friendly name and make column sortable, default true
* <li>menu : if true prints DisplayBlock menu, default true
* <li>display_aliases : list of query aliases that will be printed, defaults to [] (displays all)
* <li>zlist : name of the zlist to use, false to disable zlist lookup, default to 'list'
* <li>extra_fields : list of <alias>.<attcode> to add to the result, separator ',', defaults to empty string
* </ul>
*
* @return string
* @throws \CoreException
@@ -1365,7 +1399,7 @@ HTML
}
// Filter the list to removed linked set since we are not able to display them here
foreach($aList[$sAlias] as $index => $sAttCode)
foreach ($aList[$sAlias] as $index => $sAttCode)
{
$oAttDef = MetaModel::GetAttributeDef($sClassName, $sAttCode);
if ($oAttDef instanceof AttributeLinkedSet)
@@ -1374,6 +1408,11 @@ HTML
unset($aList[$sAlias][$index]);
}
}
if (empty($aList[$sAlias]))
{
unset($aList[$sAlias], $aAuthorizedClasses[$sAlias]);
}
}
$sSelectMode = 'none';
@@ -1932,6 +1971,11 @@ HTML
$sNullValue = $oAttDef->GetNullValue(); // used for the ValidateField() call in js/forms-json-utils.js
$sFieldToValidateId = $iId; // can be different than the displayed field (for example in TagSet)
// List of attributes that depend on the current one
// Might be modified depending on the current field
$sWizardHelperJsVarName = "oWizardHelper{$sFormPrefix}";
$aDependencies = MetaModel::GetDependentAttributes($sClass, $sAttCode);
switch ($oAttDef->GetEditClass())
{
case 'Date':
@@ -2222,6 +2266,7 @@ EOF
break;
case 'ExtKey':
/** @var \AttributeExternalKey $oAttDef */
$aEventsList[] = 'validate';
$aEventsList[] = 'change';
@@ -2240,6 +2285,19 @@ EOF
$sHTMLValue = UIExtKeyWidget::DisplayFromAttCode($oPage, $sAttCode, $sClass, $oAttDef->GetLabel(),
$oAllowedValues, $value, $iId, $bMandatory, $sFieldName, $sFormPrefix, $aExtKeyParams);
$sHTMLValue .= "<!-- iFlags: $iFlags bMandatory: $bMandatory -->\n";
$bHasExtKeyUpdatingRemoteClassFields = (
array_key_exists('replaceDependenciesByRemoteClassFields', $aArgs)
&& ($aArgs['replaceDependenciesByRemoteClassFields'])
);
if ($bHasExtKeyUpdatingRemoteClassFields)
{
// On this field update we need to update all the corresponding remote class fields
// Used when extkey widget is in a linkedset indirect
$sWizardHelperJsVarName = $aArgs['wizHelperRemote'];
$aDependencies = $aArgs['remoteCodes'];
}
break;
case 'RedundancySetting':
@@ -2293,23 +2351,23 @@ EOF
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/form_field.js');
$oPage->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/subform_field.js');
$oPage->add_ready_script(
<<<EOF
$('#{$iId}_field_set').field_set($sFieldSetOptions);
$('#{$iId}_console_form').console_form_handler($sFormHandlerOptions);
$('#{$iId}_console_form').console_form_handler('alignColumns');
$('#{$iId}_console_form').console_form_handler('option', 'field_set', $('#{$iId}_field_set'));
// field_change must be processed to refresh the hidden value at anytime
$('#{$iId}_console_form').bind('value_change', function() { $('#{$iId}').val(JSON.stringify($('#{$iId}_field_set').triggerHandler('get_current_values'))); });
// Initialize the hidden value with current state
// update_value is triggered when preparing the wizard helper object for ajax calls
$('#{$iId}').bind('update_value', function() { $(this).val(JSON.stringify($('#{$iId}_field_set').triggerHandler('get_current_values'))); });
// validate is triggered by CheckFields, on all the input fields, once at page init and once before submitting the form
$('#{$iId}').bind('validate', function(evt, sFormId) {
$(this).val(JSON.stringify($('#{$iId}_field_set').triggerHandler('get_current_values')));
return ValidateCustomFields('$iId', sFormId); // Custom validation function
});
EOF
<<<JS
$('#{$iId}_field_set').field_set($sFieldSetOptions);
$('#{$iId}_console_form').console_form_handler($sFormHandlerOptions);
$('#{$iId}_console_form').console_form_handler('alignColumns');
$('#{$iId}_console_form').console_form_handler('option', 'field_set', $('#{$iId}_field_set'));
// field_change must be processed to refresh the hidden value at anytime
$('#{$iId}_console_form').bind('value_change', function() { $('#{$iId}').val(JSON.stringify($('#{$iId}_field_set').triggerHandler('get_current_values'))); });
// Initialize the hidden value with current state
// update_value is triggered when preparing the wizard helper object for ajax calls
$('#{$iId}').bind('update_value', function() { $(this).val(JSON.stringify($('#{$iId}_field_set').triggerHandler('get_current_values'))); });
// validate is triggered by CheckFields, on all the input fields, once at page init and once before submitting the form
$('#{$iId}').bind('validate', function(evt, sFormId) {
$(this).val(JSON.stringify($('#{$iId}_field_set').triggerHandler('get_current_values')));
return ValidateCustomFields('$iId', sFormId); // Custom validation function
});
JS
);
break;
@@ -2437,16 +2495,39 @@ EOF
$sNullValue = "'$sNullValue'"; // Add quotes to turn this into a JS string if it's not a number
}
$sOriginalValue = ($iFlags & OPT_ATT_MUSTCHANGE) ? json_encode($value) : 'undefined';
$oPage->add_ready_script("$('#$sFieldToValidateId').bind('".implode(' ',
$aEventsList)."', function(evt, sFormId) { return ValidateField('$sFieldToValidateId', '$sPattern', $bMandatory, sFormId, $sNullValue, $sOriginalValue) } );\n"); // Bind to a custom event: validate
$sEventList = implode(' ', $aEventsList);
$oPage->add_ready_script(<<<JS
$('#$sFieldToValidateId')
.bind('$sEventList',
function(evt, sFormId) {
// Bind to a custom event: validate
return ValidateField('$sFieldToValidateId', '$sPattern', $bMandatory, sFormId, $sNullValue, $sOriginalValue);
}
);
JS
);
}
$aDependencies = MetaModel::GetDependentAttributes($sClass,
$sAttCode); // List of attributes that depend on the current one
// handle dependent fields updates (init for WizardHelper JS object)
if (count($aDependencies) > 0)
{
// Unbind first to avoid duplicate event handlers in case of reload of the whole (or part of the) form
$oPage->add_ready_script("$('#$iId').unbind('change.dependencies').bind('change.dependencies', function(evt, sFormId) { return oWizardHelper{$sFormPrefix}.UpdateDependentFields(['".implode("','",
$aDependencies)."']) } );\n"); // Bind to a custom event: validate
//--- Add an event handler to launch a custom event: validate
// * Unbind first to avoid duplicate event handlers in case of reload of the whole (or part of the) form
// * We were using off/on directly on the node before, but that was causing an issue when adding dynamically new nodes
// indeed the events weren't attached on the of the new nodes !
// So we're adding the handler on a node above, and we're using a selector to catch only the event we're interested in !
$sDependencies = implode("','", $aDependencies);
$oPage->add_ready_script(<<<JS
$('div#field_{$iId}')
.off('change.dependencies', '#$iId')
.on('change.dependencies', '#$iId',
function(evt, sFormId) {
return $sWizardHelperJsVarName.UpdateDependentFields(['$sDependencies']);
}
);
JS
);
}
}
$oPage->add_dict_entry('UI:ValueMustBeSet');
@@ -3111,7 +3192,7 @@ EOF
$this->GetOwnershipJSHandler($oPage, $sOwnershipToken);
}
// Note: This part (inline images activation) is duplicated in self::DisplayModifyForm and several other places. Maybe it should be refactored so it automatically activates when an HTML field is present, or be an option of the attribute. See bug n°1240.
// Note: This part (inline images activation) is duplicated in self::DisplayModifyForm and several other places. Maybe it should be refactored so it automatically activates when an HTML field is present, or be an option of the attribute. See bug N°1240.
$sTempId = utils::GetUploadTempId($iTransactionId);
$oPage->add_ready_script(InlineImage::EnableCKEditorImageUpload($this, $sTempId));
}
@@ -3796,19 +3877,24 @@ EOF
break;
case 'Image':
$value = null;
$oImage = utils::ReadPostedDocument("attr_{$sFormPrefix}{$sAttCode}", 'fcontents');
$aSize = utils::GetImageSize($oImage->GetData());
$oImage = utils::ResizeImageToFit($oImage, $aSize[0], $aSize[1], $oAttDef->Get('storage_max_width'),
$oAttDef->Get('storage_max_height'));
if (!is_null($oImage->GetData()))
{
$aSize = utils::GetImageSize($oImage->GetData());
$oImage = utils::ResizeImageToFit(
$oImage,
$aSize[0],
$aSize[1],
$oAttDef->Get('storage_max_width'),
$oAttDef->Get('storage_max_height')
);
}
$aOtherData = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data');
if (is_array($aOtherData))
{
$value = array('fcontents' => $oImage, 'remove' => $aOtherData['remove']);
}
else
{
$value = null;
}
break;
case 'RedundancySetting':
@@ -4131,6 +4217,16 @@ EOF
$this->bAllowWrite = $bAllow;
}
/**
* Whether to bypass the checks of user rights when writing this object, could be used in {@link \iApplicationObjectExtension::OnCheckToWrite()}
*
* @return bool
*/
public function GetAllowWrite()
{
return $this->bAllowWrite;
}
/**
* Bypass the check of the user rights when deleting this object
*

View File

@@ -491,7 +491,7 @@ abstract class Dashboard
$("#attr_auto_reload_sec").prop('disabled', !$(this).is(':checked'));
} );
$('#select_layout').buttonset();
$('#select_layout').controlgroup();
$('#select_dashlet').droppable({
accept: '.dashlet',
drop: function(event, ui) {
@@ -928,6 +928,9 @@ class RuntimeDashboard extends Dashboard
$sExtraParams = json_encode($aAjaxParams);
$iReloadInterval = 1000 * $this->GetAutoReloadInterval();
$sReloadURL = $this->GetReloadURL();
$oAppContext = new ApplicationContext();
$sContext=$oAppContext->GetForPostParams();
//$sContext is named "c" because it use the existing code for context parameters c[org_id] and c[menu]
$oPage->add_script(
<<<EOF
if (typeof(AutoReloadDashboardId$sDivId) !== 'undefined')
@@ -945,7 +948,7 @@ class RuntimeDashboard extends Dashboard
{
$('.dashboard_contents#$sDivId').block();
$.post(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php',
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, reload_url: '$sReloadURL'},
{ operation: 'reload_dashboard', dashboard_id: '$sId', file: '$sFile', extra_params: $sExtraParams, c: $sContext, reload_url: '$sReloadURL'},
function(data){
$('.dashboard_contents#$sDivId').html(data);
$('.dashboard_contents#$sDivId').unblock();

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.6">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<classes>
<class id="AbstractResource" _delta="define">
<parent>cmdbAbstractObject</parent>
@@ -399,7 +399,8 @@
<stylesheets>
<stylesheet id="jqueryui">../css/ui-lightness/jqueryui.scss</stylesheet>
<stylesheet id="main">../css/light-grey.scss</stylesheet>
</stylesheets>
</stylesheets>
<precompiled_stylesheet>itop-config-mgmt/precompiled-themes/light-grey/main.css</precompiled_stylesheet>
</theme>
<theme id="test-red" _delta="define">
<variables>
@@ -415,6 +416,7 @@
<stylesheet id="main">../css/light-grey.scss</stylesheet>
<stylesheet id="environment-banner">../css/backoffice-environment-banner.scss</stylesheet>
</stylesheets>
<precompiled_stylesheet>itop-config-mgmt/precompiled-themes/test-red/main.css</precompiled_stylesheet>
</theme>
</themes>
</branding>

View File

@@ -971,13 +971,13 @@ class DataTableSettings implements Serializable
* @throws \CoreException
* @throws \DictExceptionMissingString
*/
static public function GetDataModelSettings($aClassAliases, $bViewLink, $aDefaultLists)
public static function GetDataModelSettings($aClassAliases, $bViewLink, $aDefaultLists)
{
$oSettings = new DataTableSettings($aClassAliases);
// Retrieve the class specific settings for each class/alias based on the 'list' ZList
//TODO let the caller pass some other default settings (another Zlist, extre fields...)
$aColumns = array();
foreach($aClassAliases as $sAlias => $sClass)
foreach ($aClassAliases as $sAlias => $sClass)
{
if ($aDefaultLists == null)
{

View File

@@ -24,15 +24,6 @@ require_once(APPROOT.'/application/utils.inc.php');
*
* Each block is actually rendered as a <div></div> tag that can be rendered synchronously
* or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php).
* The list of cmdbObjects to be displayed into the block is defined by a filter
* Right now the type of display is either: list, count, bare_details, details, csv, modify or search
* - list produces a table listing the objects
* - count produces a paragraphs with a sentence saying 'cont' objects found
* - bare_details displays just the details of the attributes of the object (best if only one)
* - details display the full details of each object found using its template (best if only one)
* - csv displays a textarea with the CSV export of the list of objects
* - modify displays the form to modify an object (best if only one)
* - search displays a search form with the criteria of the filter set
*/
class DisplayBlock
{
@@ -45,7 +36,23 @@ class DisplayBlock
protected $m_aParams;
protected $m_oSet;
protected $m_bShowObsoleteData = null;
/**
* @param \DBSearch $oFilter list of cmdbObjects to be displayed into the block
* @param string $sStyle one of :
* <ul>
* <li>list : produces a table listing the objects</li>
* <li>count : produces a paragraphs with a sentence saying 'cont' objects found</li>
* <li>bare_details : displays just the details of the attributes of the object (best if only one)</li>
* <li>details : display the full details of each object found using its template (best if only one)</li>
* <li>csv : displays a textarea with the CSV export of the list of objects</li>
* <li>modify : displays the form to modify an object (best if only one)</li>
* <li>search : displays a search form with the criteria of the filter set</li>
* </ul>
* @param bool $bAsynchronous
* @param array $aParams
* @param \DBObjectSet $oSet
*/
public function __construct(DBSearch $oFilter, $sStyle = 'list', $bAsynchronous = false, $aParams = array(), $oSet = null)
{
$this->m_oFilter = $oFilter->DeepClone();

View File

@@ -79,6 +79,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->add_linked_stylesheet("../css/c3.min.css");
$this->add_linked_stylesheet("../css/font-awesome/css/all.min.css");
$this->add_linked_stylesheet("../js/ckeditor/plugins/codesnippet/lib/highlight/styles/obsidian.css");
$this->add_linked_stylesheet("../css/selectize.default.css");
$this->add_linked_script('../js/jquery.layout.min.js');
$this->add_linked_script('../js/jquery.ba-bbq.min.js');
@@ -106,6 +107,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->add_linked_script('../js/moment-with-locales.min.js');
$this->add_linked_script('../js/showdown.min.js');
$this->add_linked_script('../js/newsroom_menu.js');
$this->add_linked_script("../js/selectize.min.js");
$this->add_dict_entry('UI:FillAllMandatoryFields');
@@ -804,21 +806,18 @@ JS
break;
default:
$sHtml = '';
$oAppContext = new ApplicationContext();
$iCurrentOrganization = $oAppContext->GetCurrentValue('org_id');
$sHtml = '<div id="SiloSelection">';
$sHtml .= '<form style="display:inline" action="'.utils::GetAbsoluteUrlAppRoot().'pages/UI.php">'; //<select class="org_combo" name="c[org_id]" title="Pick an organization" onChange="this.form.submit();">';
$sFavoriteOrgs = '';
$oWidget = new UIExtKeyWidget('Organization', 'org_id', '', true /* search mode */);
$sHtml .= $oWidget->Display($this, 50, false, '', $oSet, $iCurrentOrganization, 'org_id', false, 'c[org_id]', '',
$sHtml .= $oWidget->DisplaySelect($this, 50, false, '', $oSet, $iCurrentOrganization, false, 'c[org_id]', '',
array(
'iFieldSize' => 20,
'iMinChars' => MetaModel::GetConfig()->Get('min_autocomplete_chars'),
'sDefaultValue' => Dict::S('UI:AllOrganizations'),
),
null, 'select', false /* bSearchMultiple */);
));
$this->add_ready_script('$("#org_id").bind("extkeychange", function() { $("#SiloSelection form").submit(); } )');
$this->add_ready_script("$('#label_org_id').click( function() { if ($('#org_id').val() == '') { $(this).val(''); } } );\n");
// Add other dimensions/context information to this form

View File

@@ -107,7 +107,7 @@ class LoginWebPage extends NiceWebPage
* @throws \CoreException
* @throws \CoreUnexpectedValue
*/
public static function SynchroniseProfiles(&$oUser, array $aProfiles, $sOrigin)
public static function SynchronizeProfiles(&$oUser, array $aProfiles, $sOrigin)
{
$oProfilesSet = $oUser->Get(profile_list);
//delete old profiles
@@ -928,7 +928,7 @@ class LoginWebPage extends NiceWebPage
{
$sOrigin .= " ({$_SESSION['login_mode']})";
}
$aExistingProfiles = self::SynchroniseProfiles($oUser, $aProfiles, $sOrigin);
$aExistingProfiles = self::SynchronizeProfiles($oUser, $aProfiles, $sOrigin);
if ($oUser->IsModified())
{
$oUser->DBWrite();

View File

@@ -39,7 +39,7 @@ class NiceWebPage extends WebPage
{
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-migrate.prod.min.js');
}
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui-1.11.4.custom.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery-ui.custom.min.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/utils.js');
$this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/hovertip.js');
// table sorting

View File

@@ -35,7 +35,17 @@ register_shutdown_function(function()
$sReservedMemory = null;
if (!is_null($err = error_get_last()) && ($err['type'] == E_ERROR))
{
IssueLog::error($err['message']);
// Remove stack trace from MySQLException
$sMessage = $err['message'];
if (strpos($sMessage, 'MySQLException') !== false)
{
$iStackTracePos = strpos($sMessage, 'Stack trace:');
if ($iStackTracePos !== false)
{
$sMessage = substr($sMessage, 0, $iStackTracePos);
}
}
IssueLog::error($sMessage);
if (strpos($err['message'], 'Allowed memory size of') !== false)
{
$sLimit = ini_get('memory_limit');

View File

@@ -25,6 +25,9 @@
*/
class ThemeHandler
{
const IMAGE_EXTENSIONS = ['png', 'gif', 'jpg', 'jpeg'];
private static $oCompileCSSService;
/**
* Return default theme name and parameters
*
@@ -33,19 +36,19 @@ class ThemeHandler
*/
public static function GetDefaultThemeInformation()
{
return array(
return [
'name' => 'light-grey',
'parameters' => array(
'variables' => array(),
'imports' => array(
'parameters' => [
'variables' => [],
'imports' => [
'css-variables' => '../css/css-variables.scss',
),
'stylesheets' => array(
],
'stylesheets' => [
'jqueryui' => '../css/ui-lightness/jqueryui.scss',
'main' => '../css/light-grey.scss',
),
),
);
],
],
];
}
/**
@@ -57,6 +60,10 @@ class ThemeHandler
{
try
{
if (is_null(MetaModel::GetConfig()))
{
throw new CoreException('no config');
}
$sThemeId = MetaModel::GetConfig()->Get('backoffice_default_theme');
}
catch(CoreException $oCompileException)
@@ -108,37 +115,49 @@ class ThemeHandler
SetupUtils::builddir($sDefaultThemeDirPath);
}
static::CompileTheme($sThemeId, $aDefaultTheme['parameters']);
static::CompileTheme($sThemeId, false, "", $aDefaultTheme['parameters']);
}
// Return absolute url to theme compiled css
return utils::GetAbsoluteUrlModulesRoot().'/branding/themes/'.$sThemeId.'/main.css';
return utils::GetAbsoluteUrlModulesRoot().'branding/themes/'.$sThemeId.'/main.css';
}
/**
* Compile the $sThemeId theme
* Compile the $sThemeId theme, the actual compilation is skipped when either
* 1) The produced CSS file exists and is more recent than any of its components (imports, stylesheets)
* 2) The produced CSS file exists and its signature is equal to the expected signature (imports, stylesheets, variables)
*
* @param string $sThemeId
* @param boolean $bSetup
* @param string $sSetupCompilationTimestamp : setup compilation timestamp in micro secunds
* @param array|null $aThemeParameters Parameters (variables, imports, stylesheets) for the theme, if not passed, will be retrieved from compiled DM
* @param array|null $aImportsPaths Paths where imports can be found. Must end with '/'
* @param string|null $sWorkingPath Path of the folder used during compilation. Must end with a '/'
*
* @throws \CoreException
* @return boolean: indicate whether theme compilation occured
*/
public static function CompileTheme($sThemeId, $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
public static function CompileTheme($sThemeId, $bSetup=false, $sSetupCompilationTimestamp="", $aThemeParameters = null, $aImportsPaths = null, $sWorkingPath = null)
{
if ($sSetupCompilationTimestamp==="")
{
$sSetupCompilationTimestamp = microtime(true);
}
$sSetupCompilationTimestampInSecunds = (strpos($sSetupCompilationTimestamp, '.') !==false) ? explode('.', $sSetupCompilationTimestamp)[0] : $sSetupCompilationTimestamp;
$sEnv = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
// Default working path
if($sWorkingPath === null)
{
$sWorkingPath = APPROOT.'env-'.utils::GetCurrentEnvironment().'/';
$sWorkingPath = $sEnv;
}
// Default import paths (env-*)
if($aImportsPaths === null)
{
$aImportsPaths = array(
APPROOT.'env-'.utils::GetCurrentEnvironment().'/',
);
$aImportsPaths = [ $sEnv];
}
// Note: We do NOT check that the folder exists!
@@ -148,6 +167,11 @@ class ThemeHandler
// Save parameters if passed... (typically during DM compilation)
if(is_array($aThemeParameters))
{
if (!is_dir($sThemeFolderPath))
{
mkdir($sWorkingPath.'/branding/');
mkdir($sWorkingPath.'/branding/themes/');
}
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
}
// ... Otherwise, retrieve them from compiled DM (typically when switching current theme in the config. file)
@@ -160,31 +184,589 @@ class ThemeHandler
}
}
$aThemeParametersWithVersion = self::CloneThemeParameterAndIncludeVersion($aThemeParameters, $sSetupCompilationTimestampInSecunds);
$sTmpThemeScssContent = '';
$iStyleLastModified = 0;
clearstatcache();
// Loading files to import and stylesheet to compile, also getting most recent modification time on overall files
$aStylesheetFiles = [];
foreach ($aThemeParameters['imports'] as $sImport)
{
$sTmpThemeScssContent .= '@import "'.$sImport.'";'."\n";
$iImportLastModified = @filemtime($sWorkingPath.$sImport);
$sFile = static::FindStylesheetFile($sImport, $aImportsPaths);
$iImportLastModified = @filemtime($sFile);
$aStylesheetFiles[] = $sFile;
$iStyleLastModified = $iStyleLastModified < $iImportLastModified ? $iImportLastModified : $iStyleLastModified;
}
foreach ($aThemeParameters['stylesheets'] as $sStylesheet)
{
$sTmpThemeScssContent .= '@import "'.$sStylesheet.'";'."\n";
$iStylesheetLastModified = @filemtime($sWorkingPath.$sStylesheet);
$sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths);
$iStylesheetLastModified = @filemtime($sFile);
$aStylesheetFiles[] = $sFile;
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
}
// Checking if our compiled css is outdated
if (!file_exists($sThemeCssPath) || (is_writable($sThemeFolderPath) && (@filemtime($sThemeCssPath) < $iStyleLastModified)))
$aIncludedImages=static::GetIncludedImages($aThemeParametersWithVersion, $aStylesheetFiles, $sThemeId);
foreach ($aIncludedImages as $sImage)
{
$sTmpThemeCssContent = utils::CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths, $aThemeParameters['variables']);
file_put_contents($sThemeCssPath, $sTmpThemeCssContent);
if (is_file($sImage))
{
$iStylesheetLastModified = @filemtime($sImage);
$iStyleLastModified = $iStyleLastModified < $iStylesheetLastModified ? $iStylesheetLastModified : $iStyleLastModified;
}
}
// Checking if our compiled css is outdated
$iFilemetime = @filemtime($sThemeCssPath);
$bFileExists = file_exists($sThemeCssPath);
$bVarSignatureChanged=false;
if ($bFileExists && $bSetup)
{
$sPrecompiledSignature = static::GetSignature($sThemeCssPath);
//check variable signature has changed which is independant from any file modification
if (!empty($sPrecompiledSignature)){
$sPreviousVariableSignature = static::GetVarSignature($sPrecompiledSignature);
$sCurrentVariableSignature = md5(json_encode($aThemeParameters['variables']));
$bVarSignatureChanged= ($sPreviousVariableSignature!==$sCurrentVariableSignature);
}
}
if (!$bFileExists || $bVarSignatureChanged || (is_writable($sThemeFolderPath) && ($iFilemetime < $iStyleLastModified)))
{
// Dates don't match. Second chance: check if the already compiled stylesheet exists and is consistent based on its signature
$sActualSignature = static::ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages);
if ($bFileExists && !$bSetup)
{
$sPrecompiledSignature = static::GetSignature($sThemeCssPath);
}
if (!empty($sPrecompiledSignature) && $sActualSignature == $sPrecompiledSignature)
{
touch($sThemeCssPath); // Stylesheet is up to date, mark it as more recent to speedup next time
}
else
{
// Alas, we really need to recompile
// Add the signature to the generated CSS file so that the file can be used as a precompiled stylesheet if needed
$sSignatureComment =
<<<CSS
/*
=== SIGNATURE BEGIN ===
$sActualSignature
=== SIGNATURE END ===
*/
CSS;
if (!static::$oCompileCSSService)
{
static::$oCompileCSSService = new CompileCSSService();
}
//store it again to change $version with latest compiled time
$sTmpThemeCssContent = static::$oCompileCSSService->CompileCSSFromSASS($sTmpThemeScssContent, $aImportsPaths,
$aThemeParametersWithVersion);
file_put_contents($sThemeFolderPath.'/theme-parameters.json', json_encode($aThemeParameters));
file_put_contents($sThemeCssPath, $sSignatureComment.$sTmpThemeCssContent);
SetupLog::Info("Theme $sThemeId file compiled.");
return true;
}
}
return false;
}
/**
* Compute the signature of a theme defined by its theme parameters. The signature is a JSON structure of
* 1) one MD5 of all the variables/values (JSON encoded)
* 2) the MD5 of each stylesheet file
* 3) the MD5 of each import file
* 3) the MD5 of each images referenced in style sheets
*
* @param string[] $aThemeParameters
* @param string[] $aImportsPaths
* @param string[] $aIncludedImages
*
* @return string
* @throws \Exception
*/
public static function ComputeSignature($aThemeParameters, $aImportsPaths, $aIncludedImages)
{
$aSignature = [
'variables' => md5(json_encode($aThemeParameters['variables'])),
'stylesheets' => [],
'imports' => [],
'images' => []
];
foreach ($aThemeParameters['imports'] as $key => $sImport)
{
$sFile = static::FindStylesheetFile($sImport, $aImportsPaths);
$aSignature['stylesheets'][$key] = md5_file($sFile);
}
foreach ($aThemeParameters['stylesheets'] as $key => $sStylesheet)
{
$sFile = static::FindStylesheetFile($sStylesheet, $aImportsPaths);
$aSignature['stylesheets'][$key] = md5_file($sFile);
}
foreach ($aIncludedImages as $sImage)
{
if (is_file($sImage))
{
$sUri = str_replace(APPROOT, '', $sImage);
$aSignature['images'][$sUri] = md5_file($sImage);
}
}
return json_encode($aSignature);
}
/**
* Search for images referenced in stylesheet files
*
* @param array $aThemeParametersVariables
* @param array $aStylesheetFiles
* @param string $sThemeId: used only for logging purpose
*
* @return array
* @since 2.8.0
*/
public static function GetIncludedImages($aThemeParametersVariables, $aStylesheetFiles, $sThemeId)
{
$sTargetThemeFolderPath = static::GetCompiledThemeFolderAbsolutePath($sThemeId);
$aCompleteUrls = [];
$aToCompleteUrls = [];
$aMissingVariables = [];
$aFoundVariables = ['version'=>''];
$aMap = [
'aCompleteUrls' => $aCompleteUrls,
'aToCompleteUrls' => $aToCompleteUrls,
'aMissingVariables' => $aMissingVariables,
'aFoundVariables' => $aFoundVariables,
];
foreach ($aStylesheetFiles as $sStylesheetFile)
{
$aRes = static::GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile);
/** @var array $aVal */
foreach($aMap as $key => $aVal)
{
if (array_key_exists($key, $aMap))
{
$aMap[$key] = array_merge($aVal, $aRes[$key]);
}
}
}
$aMap = static::ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFiles);
$aImages = [];
foreach ($aMap ['aCompleteUrls'] as $sUri => $sUrl)
{
$sImg = $sUrl;
if (preg_match("/(.*)\?/", $sUrl, $aMatches))
{
$sImg=$aMatches[1];
}
if (static::HasImageExtension($sImg)
&& ! array_key_exists($sImg, $aImages))
{
$sFilePath = realpath($sImg);
if ($sFilePath!==false)
{
$aImages[$sImg]=$sFilePath;
continue;
}
$sCanonicalPath = static::CanonicalizePath($sTargetThemeFolderPath.DIRECTORY_SEPARATOR.$sImg);
$sFilePath=realpath($sCanonicalPath);
if ($sFilePath!==false)
{
$aImages[$sImg]=$sFilePath;
continue;
}
SetupLog::Warning("Cannot find $sCanonicalPath ($sImg) during SCSS $sThemeId precompilation");
}
}
return array_values($aImages);
}
/**
* Reduce path without using realpath (works only when file exists)
* @param $path
*
* @return string
*/
public static function CanonicalizePath($path)
{
$path = explode('/', str_replace('//','/', $path));
$stack = array();
foreach ($path as $seg) {
if ($seg == '..') {
// Ignore this segment, remove last segment from stack
array_pop($stack);
continue;
}
if ($seg == '.') {
// Ignore this segment
continue;
}
$stack[] = $seg;
}
return implode('/', $stack);
}
/**
* Complete url using provided variables. Example with $var=1: XX + $var => XX1
* @param $aMap
* @param $aThemeParametersVariables
* @param $aStylesheetFile
*
* @return mixed
*/
public static function ResolveUncompleteUrlsFromScss($aMap, $aThemeParametersVariables, $aStylesheetFile)
{
$sContent="";
foreach ($aStylesheetFile as $sStylesheetFile)
{
if (is_file($sStylesheetFile))
{
$sContent .= '\n' . file_get_contents($sStylesheetFile);
}
}
$aMissingVariables=$aMap['aMissingVariables'];
$aFoundVariables=$aMap['aFoundVariables'];
$aToCompleteUrls=$aMap['aToCompleteUrls'];
$aCompleteUrls=$aMap['aCompleteUrls'];
list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, true);
list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls);
$aMap['aMissingVariables']=$aMissingVariables;
$aMap['aFoundVariables']=$aFoundVariables;
$aMap['aToCompleteUrls']=$aToCompleteUrls;
$aMap['aCompleteUrls']=$aCompleteUrls;
return $aMap;
}
/**
* Find missing variable values from SCSS content based on their name.
*
* @param $aThemeParametersVariables
* @param $aMissingVariables
* @param $aFoundVariables
* @param $sContent : scss content
* @param bool $bForceEmptyValueWhenNotFound
*
* @return array
*/
public static function FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent, $bForceEmptyValueWhenNotFound=false)
{
$aNewMissingVars = [];
if (!empty($aMissingVariables))
{
foreach ($aMissingVariables as $var)
{
if (array_key_exists($var, $aThemeParametersVariables))
{
$aFoundVariables[$var] = $aThemeParametersVariables[$var];
}
else
{
if (preg_match_all("/\\\$$var\s*:\s*[\"']{0,1}(.*)[\"']{0,1};/", $sContent, $aValues))
{
$sValue = $aValues[1][0];
if (preg_match_all("/([^!]+)!/", $sValue, $aSubValues))
{
$sValue = trim($aSubValues[1][0], ' "\'');
}
if (strpos($sValue, '$') === false)
{
$aFoundVariables[$var] = $sValue;
}
else{
$aNewMissingVars[] = $var;
}
}
else
{
if ($bForceEmptyValueWhenNotFound)
{
$aFoundVariables[$var] = '';
}
else
{
$aNewMissingVars[] = $var;
}
}
}
}
}
return [ $aNewMissingVars, $aFoundVariables ];
}
/**
* @param $aFoundVariables
* @param array $aToCompleteUrls
* @param array $aCompleteUrls
*
* @return array
*/
public static function ResolveUrls($aFoundVariables, array $aToCompleteUrls, array $aCompleteUrls)
{
if (!empty($aFoundVariables))
{
$aFoundVariablesWithEmptyValue = [];
foreach ($aFoundVariables as $aFoundVariable => $sValue)
{
$aFoundVariablesWithEmptyValue[$aFoundVariable] = '';
}
foreach ($aToCompleteUrls as $sUrlTemplate)
{
unset($aToCompleteUrls[$sUrlTemplate]);
$sResolvedUrl = static::ResolveUrl($sUrlTemplate, $aFoundVariables);
if ($sResolvedUrl == false)
{
$aToCompleteUrls[$sUrlTemplate] = $sUrlTemplate;
}
else
{
$sUri = static::ResolveUrl($sUrlTemplate, $aFoundVariablesWithEmptyValue);
$aExplodedUri = explode('?', $sUri);
if (empty($aExplodedUri))
{
$aCompleteUrls[$sUri] = $sResolvedUrl;
}
else
{
$aCompleteUrls[$aExplodedUri[0]] = $sResolvedUrl;
}
}
}
}
return [ $aToCompleteUrls, $aCompleteUrls];
}
/**
* Find all referenced URLs from a SCSS file.
* @param $aThemeParametersVariables
* @param $sStylesheetFile
*
* @return array
*/
public static function GetAllUrlFromScss($aThemeParametersVariables, $sStylesheetFile)
{
$aCompleteUrls = [];
$aToCompleteUrls = [];
$aMissingVariables = [];
$aFoundVariables = [];
if (is_file($sStylesheetFile))
{
$sContent = file_get_contents($sStylesheetFile);
if (preg_match_all("/url\s*\((.*)\)/", $sContent, $aMatches))
{
foreach ($aMatches[1] as $path)
{
if (!array_key_exists($path, $aCompleteUrls)
&& !array_key_exists($path, $aToCompleteUrls))
{
if (preg_match_all("/\\$([\w\-_]+)/", $path, $aCurrentVars))
{
/** @var string $aCurrentVars */
foreach ($aCurrentVars[1] as $var)
{
if (!array_key_exists($var, $aMissingVariables))
{
$aMissingVariables[$var] = $var;
}
}
$aToCompleteUrls[$path] = $path;
}
else
{
$aCompleteUrls[$path] = trim($path, "\"'");
}
}
}
}
if (!empty($aMissingVariables))
{
list($aMissingVariables, $aFoundVariables) = static::FindMissingVariables($aThemeParametersVariables, $aMissingVariables, $aFoundVariables, $sContent);
list($aToCompleteUrls, $aCompleteUrls) = static::ResolveUrls($aFoundVariables, $aToCompleteUrls, $aCompleteUrls);
}
}
return [
'aCompleteUrls' => $aCompleteUrls,
'aToCompleteUrls' => $aToCompleteUrls,
'aMissingVariables' => $aMissingVariables,
'aFoundVariables' => $aFoundVariables
];
}
/**
* Calculate url based on its template + variables.
* @param $sUrlTemplate
* @param $aFoundVariables
*
* @return bool|string
*/
public static function ResolveUrl($sUrlTemplate, $aFoundVariables)
{
$aPattern= [];
$aReplacement= [];
foreach ($aFoundVariables as $aFoundVariable => $aFoundVariableValue)
{
//XX + $key + YY
$aPattern[]="/['\"]\s*\+\s*\\\$" . $aFoundVariable . "[\s\+]+\s*['\"]/";
$aReplacement[]=$aFoundVariableValue;
//$key + YY
$aPattern[]="/\\\$" . $aFoundVariable. "[\s\+]+\s*['\"]/";
$aReplacement[]=$aFoundVariableValue;
//XX + $key
$aPattern[]="/['\"]\s*[\+\s]+\\\$" . $aFoundVariable . "$/";
$aReplacement[]=$aFoundVariableValue;
}
$sResolvedUrl=preg_replace($aPattern, $aReplacement, $sUrlTemplate);
if (strpos($sResolvedUrl, "+")!==false)
{
return false;
}
return trim($sResolvedUrl, "\"'");
}
/**
* indicate whether a string ends with image suffix.
* @param $path
*
* @return bool
*/
private static function HasImageExtension($path)
{
foreach (static::IMAGE_EXTENSIONS as $sExt)
{
if (endsWith($path, $sExt))
{
return true;
}
}
return false;
}
/**
* Extract the signature for a generated CSS file. The signature MUST be alone one line immediately
* followed (on the next line) by the === SIGNATURE END === pattern
*
* Note the signature can be place anywhere in the CSS file (obviously inside a CSS comment !) but the
* function will be faster if the signature is at the beginning of the file (since the file is scanned from the start)
*
* @param $sFilepath
*
* @return string
*/
public static function GetSignature($sFilepath)
{
$sPreviousLine = '';
$hFile = @fopen($sFilepath, "r");
if ($hFile !== false)
{
$sLine = '';
do
{
$sPreviousLine = $sLine;
$sLine = rtrim(fgets($hFile)); // Remove the trailing \n
}
while (($sLine !== false) && ($sLine != '=== SIGNATURE END ==='));
fclose($hFile);
}
return $sPreviousLine;
}
public static function GetVarSignature($JsonSignature)
{
$aJsonArray = json_decode($JsonSignature, true);
if (array_key_exists('variables', $aJsonArray))
{
return $aJsonArray['variables'];
}
return false;
}
/**
* Find the given file in the list of ImportsPaths directory
* @param string $sFile
* @param string[] $aImportsPaths
* @throws Exception
* @return string
*/
public static function FindStylesheetFile($sFile, $aImportsPaths)
{
foreach($aImportsPaths as $sPath)
{
$sImportedFile = realpath($sPath.'/'.$sFile);
if (file_exists($sImportedFile))
{
return $sImportedFile;
}
}
return ''; // Not found, fail silently, maybe the SCSS compiler knowns better...
}
public static function MockCompileCSSService($oCompileCSSServiceMock)
{
static::$oCompileCSSService = $oCompileCSSServiceMock;
}
/**
* Clone variable array and include $version with bSetupCompilationTimestamp value
* @param $aThemeParameters
* @param $bSetupCompilationTimestamp
*
* @return array
*/
public static function CloneThemeParameterAndIncludeVersion($aThemeParameters, $bSetupCompilationTimestamp)
{
$aThemeParametersVariable = [];
if (array_key_exists('variables', $aThemeParameters))
{
if (is_array($aThemeParameters['variables']))
{
$aThemeParametersVariable = array_merge([], $aThemeParameters['variables']);
}
}
$aThemeParametersVariable['$version'] = $bSetupCompilationTimestamp;
return $aThemeParametersVariable;
}
}
class CompileCSSService
{
/**
* CompileCSSService constructor.
*/
public function __construct()
{
}
public function CompileCSSFromSASS($sSassContent, $aImportPaths = [], $aVariables = []){
return utils::CompileCSSFromSASS($sSassContent, $aImportPaths, $aVariables);
}
}

View File

@@ -234,7 +234,14 @@ class privUITransactionFile
*/
public static function IsTransactionValid($id, $bRemoveTransaction = true)
{
$sFilepath = APPROOT.'data/transactions/'.$id;
// Constraint the transaction file within APPROOT.'data/transactions'
$sTransactionDir = realpath(APPROOT.'data/transactions');
$sFilepath = utils::RealPath($sTransactionDir.'/'.$id, $sTransactionDir);
if (($sFilepath === false) || (strlen($sTransactionDir) == strlen($sFilepath)))
{
return false;
}
clearstatcache(true, $sFilepath);
$bResult = file_exists($sFilepath);
if ($bResult)

View File

@@ -68,6 +68,7 @@ class UIExtKeyWidget
protected $iId;
protected $sTargetClass;
protected $sAttCode;
//@deprecated
protected $bSearchMode;
//public function __construct($sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '')
@@ -86,7 +87,29 @@ class UIExtKeyWidget
$sDisplayStyle = 'select'; // In search mode, always use a drop-down list
}
$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode, $bSearchMode);
return $oWidget->Display($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix, $aArgs, null, $sDisplayStyle);
if(!$bSearchMode)
{
switch($sDisplayStyle)
{
case 'radio':
case 'radio_horizontal':
case 'radio_vertical':
return $oWidget->DisplayRadio($oPage, $iMaxComboLength, $bAllowTargetCreation, $oAllowedValues, $value, $sFieldName, $sDisplayStyle);
break;
case 'select':
case 'list':
default:
return $oWidget->DisplaySelect($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value,
$bMandatory, $sFieldName, $sFormPrefix, $aArgs);
}
}
else
{
return $oWidget->Display($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix, $aArgs, null, $sDisplayStyle);
}
}
public function __construct($sTargetClass, $iInputId, $sAttCode = '', $bSearchMode = false)
@@ -98,6 +121,289 @@ class UIExtKeyWidget
}
/**
* @since 2.8.0 N°2508 - Include Obsolescence icon within list and autocomplete
* Get the HTML fragment corresponding to the ext key editing widget
* @param WebPage $oP The web page used for all the output
* @param array $aArgs Extra context arguments
* @return string The HTML fragment to be inserted into the page
*/
public function DisplaySelect(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, DBObjectset $oAllowedValues, $value, $bMandatory, $sFieldName, $sFormPrefix = '', $aArgs = array())
{
$sTitle = addslashes($sTitle);
$oPage->add_linked_script('../js/extkeywidget.js');
$oPage->add_linked_script('../js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
$bExtensions = true;
$sMessage = Dict::S('UI:Message:EmptyList:UseSearchForm');
$sAttrFieldPrefix = ($this->bSearchMode) ? '' : 'attr_';
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">";
$sFilter = addslashes($oAllowedValues->GetFilter()->ToOQL());
if($this->bSearchMode)
{
$sWizHelper = 'null';
$sWizHelperJSON = "''";
$sJSSearchMode = 'true';
}
else
{
if (isset($aArgs['wizHelper']))
{
$sWizHelper = $aArgs['wizHelper'];
}
else
{
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
}
$sWizHelperJSON = $sWizHelper.'.UpdateWizardToJSON()';
$sJSSearchMode = 'false';
}
if (is_null($oAllowedValues))
{
throw new Exception('Implementation: null value for allowed values definition');
}
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
// Don't automatically launch the search if the table is huge
$bDoSearch = !utils::IsHighCardinality($this->sTargetClass);
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
if (!$oAllowedValues->CountExceeds($iMaxComboLength))
{
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
$sHelpText = ''; //$this->oAttDef->GetHelpOnEdition();
//$sHTMLValue .= "<div class=\"field_select_wrapper\">\n";
$aOptions = [];
$sDisplayValue = "";
$aOption = [];
$aOption['value'] = "";
$aOption['label'] = Dict::S('UI:SelectOne');
array_push($aOptions,$aOption);
$oAllowedValues->Rewind();
$bAddingValue=false;
$aComplementAttributeSpec = MetaModel::GetComplementAttributeSpec($oAllowedValues->GetClass());
$sFormatAdditionalField = $aComplementAttributeSpec[0];
$aAdditionalField = $aComplementAttributeSpec[1];
if (count($aAdditionalField)>0)
{
$bAddingValue=true;
}
while($oObj = $oAllowedValues->Fetch())
{
$aOption=[];
$aOption['value'] = $oObj->GetKey();
$aOption['label'] = $oObj->GetName();//.'<span class=\"object-ref-icon fas fa-eye-slash object-obsolete fa-1x fa-fw\"></span>';
if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true') )
{
// When there is only once choice, select it by default
$sDisplayValue=$oObj->GetName();
if($value != $oObj->GetKey())
{
$oPage->add_ready_script(
<<<EOF
$('#$this->iId').attr('data-validate','dependencies');
EOF
);
}
}
else
{
if ((is_array($value) && in_array($oObj->GetKey(), $value)) || ($value == $oObj->GetKey()))
{
$sDisplayValue=$oObj->GetKey();
// $sHTMLValue.="<div class='item' data-value='".$oObj->GetKey)."'>".$oObj->GetName()."</div>";
}
}
if ($oObj->IsObsolete()){
$aOption['obsolescence_flag'] ="1";
}
if ($bAddingValue)
{
$aArguments = [];
foreach ($aAdditionalField as $sAdditionalField)
{
array_push($aArguments,$oObj->Get($sAdditionalField));
}
$aOption['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
}
array_push($aOptions,$aOption);
}
$sHTMLValue .= "<select title=\"$sHelpText\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" id=\"$this->iId\"></select>";
$sJsonOptions=json_encode($aOptions);
$oPage->add_ready_script(
<<<JS
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
oACWidget_{$this->iId}.AddSelectize('$sJsonOptions','$sDisplayValue');
$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
$('#$this->iId').bind('change', function() { $(this).trigger('extkeychange') } );
JS
);
}
else
{
// Too many choices, use an autocomplete
// Check that the given value is allowed
$oSearch = $oAllowedValues->GetFilter();
$oSearch->AddCondition('id', $value);
$oSet = new DBObjectSet($oSearch);
if ($oSet->Count() == 0)
{
$value = null;
}
if (is_null($value) || ($value == 0)) // Null values are displayed as ''
{
$sDisplayValue = isset($aArgs['sDefaultValue']) ? $aArgs['sDefaultValue'] : '';
}
else
{
$sDisplayValue = $this->GetObjectName($value);
}
$iMinChars = isset($aArgs['iMinChars']) ? $aArgs['iMinChars'] : 2; //@@@ $this->oAttDef->GetMinAutoCompleteChars();
// the input for the auto-complete
$sHTMLValue .= "<input class=\"field_autocomplete\" type=\"text\" id=\"label_$this->iId\" value=\"$sDisplayValue\"/>";
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_search_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.Search();\"><i class=\"fas fa-search\"></i></div></span>";
// another hidden input to store & pass the object's Id
$sHTMLValue .= "<input type=\"hidden\" id=\"$this->iId\" name=\"{$sAttrFieldPrefix}{$sFieldName}\" value=\"".htmlentities($value, ENT_QUOTES, 'UTF-8')."\" />\n";
$JSSearchMode = $this->bSearchMode ? 'true' : 'false';
// Scripts to start the autocomplete and bind some events to it
$oPage->add_ready_script(
<<<JS
oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}', $sJSSearchMode, $sJSDoSearch);
oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
oACWidget_{$this->iId}.AddAutocomplete($iMinChars, $sWizHelperJSON);
if ($('#ac_dlg_{$this->iId}').length == 0)
{
$('body').append('<div id="ac_dlg_{$this->iId}"></div>');
}
JS
);
}
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
{
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>";
$oPage->add_ready_script(
<<<JS
if ($('#ac_tree_{$this->iId}').length == 0)
{
$('body').append('<div id="ac_tree_{$this->iId}"></div>');
}
JS
);
}
if ($bCreate && $bExtensions)
{
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>";
$oPage->add_ready_script(
<<<JS
if ($('#ajax_{$this->iId}').length == 0)
{
$('body').append('<div id="ajax_{$this->iId}"></div>');
}
JS
);
}
$sHTMLValue .= "</div>";
$sHTMLValue .= "<span class=\"form_validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
return $sHTMLValue;
}
/**
* @since 2.8.0 N°2508 - Include Obsolescence icon within list and autocomplete
* Get the HTML fragment corresponding to the ext key editing widget
* @param WebPage $oP The web page used for all the output
* @param array $aArgs Extra context arguments
* @return string The HTML fragment to be inserted into the page
*/
public function DisplayRadio(WebPage $oPage, $iMaxComboLength, $bAllowTargetCreation, DBObjectset $oAllowedValues, $value, $sFieldName, $sDisplayStyle)
{
$oPage->add_linked_script('../js/forms-json-utils.js');
$bCreate = (!$this->bSearchMode) && (UserRights::IsActionAllowed($this->sTargetClass, UR_ACTION_BULK_MODIFY) && $bAllowTargetCreation);
$bExtensions = true;
$sAttrFieldPrefix = ($this->bSearchMode) ? '' : 'attr_';
$sHTMLValue = "<div class=\"field_input_zone field_input_extkey\">";
if (is_null($oAllowedValues))
{
throw new Exception('Implementation: null value for allowed values definition');
}
$oAllowedValues->SetShowObsoleteData(utils::ShowObsoleteData());
// We just need to compare the number of entries with MaxComboLength, so no need to get the real count.
if (!$oAllowedValues->CountExceeds($iMaxComboLength))
{
// Discrete list of values, use a SELECT or RADIO buttons depending on the config
$sValidationField = null;
$bVertical = ($sDisplayStyle != 'radio_horizontal');
$bExtensions = false;
$oAllowedValues->Rewind();
$aAllowedValues = array();
while($oObj = $oAllowedValues->Fetch())
{
$aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
}
$sHTMLValue .= $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", false /* $bMandatory will be placed manually */, $bVertical, $sValidationField);
$aEventsList[] ='change';
}
else
{
$sHTMLValue .= "unable to display. Too much values";
}
if ($bExtensions && MetaModel::IsHierarchicalClass($this->sTargetClass) !== false)
{
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_tree_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.HKDisplay();\"><i class=\"fas fa-sitemap\"></i></div></span>";
$oPage->add_ready_script(
<<<JS
if ($('#ac_tree_{$this->iId}').length == 0)
{
$('body').append('<div id="ac_tree_{$this->iId}"></div>');
}
JS
);
}
if ($bCreate && $bExtensions)
{
$sCallbackName = (MetaModel::IsAbstract($this->sTargetClass)) ? 'SelectObjectClass' : 'CreateObject';
$sHTMLValue .= "<span class=\"field_input_btn\"><div class=\"mini_button\" id=\"mini_add_{$this->iId}\" onClick=\"oACWidget_{$this->iId}.{$sCallbackName}();\"><i class=\"fas fa-plus\"></i></div></span>";
$oPage->add_ready_script(
<<<JS
if ($('#ajax_{$this->iId}').length == 0)
{
$('body').append('<div id="ajax_{$this->iId}"></div>');
}
JS
);
}
$sHTMLValue .= "</div>";
// Note: This test is no longer necessary as we changed the markup to extract validation decoration in the standard .field_input_xxx container
//if (($sDisplayStyle == 'select') || ($sDisplayStyle == 'list'))
//{
$sHTMLValue .= "<span class=\"form_validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
//}
return $sHTMLValue;
}
/**
* @deprecated Use DisplayBob
* Get the HTML fragment corresponding to the ext key editing widget
* @param WebPage $oP The web page used for all the output
* @param array $aArgs Extra context arguments
@@ -319,12 +625,7 @@ JS
);
}
$sHTMLValue .= "</div>";
// Note: This test is no longer necessary as we changed the markup to extract validation decoration in the standard .field_input_xxx container
//if (($sDisplayStyle == 'select') || ($sDisplayStyle == 'list'))
//{
$sHTMLValue .= "<span class=\"form_validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
//}
$sHTMLValue .= "<span class=\"form_validation\" id=\"v_{$this->iId}\"></span><span class=\"field_status\" id=\"fstatus_{$this->iId}\"></span>";
return $sHTMLValue;
}
@@ -433,19 +734,18 @@ EOF
// Current extkey value, so we can display event if it is not available anymore (eg. archived).
$iCurrentExtKeyId = (is_null($oObj) || $this->sAttCode === '') ? 0 : $oObj->Get($this->sAttCode);
$oValuesSet = new ValueSetObjects($sFilter, 'friendlyname'); // Bypass GetName() to avoid the encoding by htmlentities
$iMax = 150;
$oValuesSet->SetLimit($iMax);
$oValuesSet->SetSort(false);
$oValuesSet->SetModifierProperty('UserRightsGetSelectFilter', 'bSearchMode', $this->bSearchMode);
$oValuesSet->SetLimit($iMax);
$aValuesContains = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'start_with');
asort($aValuesContains);
$aValues = $aValuesContains;
if (sizeof($aValues) < $iMax)
{
$aValuesContains = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
$aValuesContains = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'contains');
asort($aValuesContains);
$iSize = sizeof($aValuesContains);
foreach ($aValuesContains as $sKey => $sFriendlyName)
@@ -462,7 +762,7 @@ EOF
}
elseif (!in_array($sContains, $aValues))
{
$aValuesEquals = $oValuesSet->GetValues(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'equals');
$aValuesEquals = $oValuesSet->GetValuesForAutocomplete(array('this' => $oObj, 'current_extkey_id' => $iCurrentExtKeyId), $sContains, 'equals');
$aValues = array_merge($aValuesEquals, $aValues);
}
@@ -471,9 +771,16 @@ EOF
case static::ENUM_OUTPUT_FORMAT_JSON:
$aJsonMap = array();
foreach ($aValues as $sKey => $sLabel)
foreach ($aValues as $sKey => $aValue)
{
$aJsonMap[] = array('value' => $sKey, 'label' => $sLabel);
if ($aValue['additional_field'] != '')
{
$aJsonMap[] = array('value' => $sKey, 'label' => $aValue['label'], 'obsolescence_flag' => $aValue['obsolescence_flag'], 'additional_field' => $aValue['additional_field']);
}
else
{
$aJsonMap[] = array('value' => $sKey, 'label' => $aValue['label'], 'obsolescence_flag' => $aValue['obsolescence_flag']);
}
}
$oP->SetContentType('application/json');
@@ -481,9 +788,9 @@ EOF
break;
case static::ENUM_OUTPUT_FORMAT_CSV:
foreach($aValues as $sKey => $sFriendlyName)
foreach($aValues as $sKey => $aValue)
{
$oP->add(trim($sFriendlyName)."\t".$sKey."\n");
$oP->add(trim($aValue['label'])."\t".$sKey."\n");
}
break;
default:

View File

@@ -39,6 +39,7 @@ class UILinksWidget
protected $m_sLinkedClass;
protected $m_sRemoteClass;
protected $m_bDuplicatesAllowed;
/** @var string[] list of editables attcodes */
protected $m_aEditableFields;
protected $m_aTableConfig;
@@ -46,7 +47,7 @@ class UILinksWidget
* UILinksWidget constructor.
*
* @param string $sClass
* @param string $sAttCode
* @param string $sAttCode AttributeLinkedSetIndirect attcode
* @param int $iInputId
* @param string $sNameSuffix
* @param bool $bDuplicatesAllowed
@@ -73,41 +74,36 @@ class UILinksWidget
/** @var AttributeExternalKey $oLinkingAttDef */
$oLinkingAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $this->m_sExtKeyToRemote);
$this->m_sRemoteClass = $oLinkingAttDef->GetTargetClass();
$sExtKeyToMe = $oAttDef->GetExtKeyToMe();
$sStateAttCode = MetaModel::GetStateAttributeCode($this->m_sClass);
$sDefaultState = MetaModel::GetDefaultState($this->m_sClass);
$this->m_aEditableFields = array();
$this->m_aTableConfig = array();
$this->m_aTableConfig['form::checkbox'] = array( 'label' => "<input class=\"select_all\" type=\"checkbox\" value=\"1\" onClick=\"CheckAll('#linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix} .selection', this.checked); oWidget".$this->m_iInputId.".OnSelectChange();\">", 'description' => Dict::S('UI:SelectAllToggle+'));
$this->m_aTableConfig['form::checkbox'] = array(
'label' => "<input class=\"select_all\" type=\"checkbox\" value=\"1\" onClick=\"CheckAll('#linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix} .selection', this.checked); oWidget".$this->m_iInputId.".OnSelectChange();\">",
'description' => Dict::S('UI:SelectAllToggle+'),
);
foreach(MetaModel::FlattenZList(MetaModel::GetZListItems($this->m_sLinkedClass, 'list')) as $sAttCode)
$aLnkAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectLinkClass($sClass, $sAttCode);
foreach ($aLnkAttDefsToDisplay as $oLnkAttDef)
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sAttCode);
if ($sStateAttCode == $sAttCode)
{
// State attribute is always hidden from the UI
}
else if ($oAttDef->IsWritable() && ($sAttCode != $sExtKeyToMe) && ($sAttCode != $this->m_sExtKeyToRemote) && ($sAttCode != 'finalclass'))
{
$iFlags = MetaModel::GetAttributeFlags($this->m_sLinkedClass, $sDefaultState, $sAttCode);
if ( !($iFlags & OPT_ATT_HIDDEN) && !($iFlags & OPT_ATT_READONLY) )
{
$this->m_aEditableFields[] = $sAttCode;
$this->m_aTableConfig[$sAttCode] = array( 'label' => $oAttDef->GetLabel(), 'description' => $oAttDef->GetDescription());
}
}
$sLnkAttCode = $oLnkAttDef->GetCode();
$this->m_aEditableFields[] = $sLnkAttCode;
$this->m_aTableConfig[$sLnkAttCode] = array('label' => $oLnkAttDef->GetLabel(), 'description' => $oLnkAttDef->GetDescription());
}
$this->m_aTableConfig['static::key'] = array( 'label' => MetaModel::GetName($this->m_sRemoteClass), 'description' => MetaModel::GetClassDescription($this->m_sRemoteClass));
foreach(MetaModel::GetZListItems($this->m_sRemoteClass, 'list') as $sFieldCode)
$this->m_aTableConfig['static::key'] = array(
'label' => MetaModel::GetName($this->m_sRemoteClass),
'description' => MetaModel::GetClassDescription($this->m_sRemoteClass),
);
$this->m_aEditableFields[] = $this->m_sExtKeyToRemote;
$aRemoteAttDefsToDisplay = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass);
foreach ($aRemoteAttDefsToDisplay as $oRemoteAttDef)
{
// TO DO: check the state of the attribute: hidden or visible ?
if ($sFieldCode != 'finalclass')
{
$oAttDef = MetaModel::GetAttributeDef($this->m_sRemoteClass, $sFieldCode);
$this->m_aTableConfig['static::'.$sFieldCode] = array( 'label' => $oAttDef->GetLabel(), 'description' => $oAttDef->GetDescription());
}
$sRemoteAttCode = $oRemoteAttDef->GetCode();
$this->m_aTableConfig['static::'.$sRemoteAttCode] = array(
'label' => $oRemoteAttDef->GetLabel(),
'description' => $oRemoteAttDef->GetDescription(),
);
}
}
@@ -116,7 +112,7 @@ class UILinksWidget
*
* @param WebPage $oP Web page used for the ouput
* @param DBObject $oLinkedObj Remote object
* @param mixed $linkObjOrId Either the object linked or a unique number for new link records to add
* @param DBObject|int $linkObjOrId Either the lnk object or a unique number for new link records to add
* @param array $aArgs Extra context arguments
* @param DBObject $oCurrentObj The object to which all the elements of the linked set refer to
* @param int $iUniqueId A unique identifier of new links
@@ -134,43 +130,39 @@ class UILinksWidget
$aRow = array();
$aFieldsMap = array();
$iKey = 0;
if(is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
if (is_object($linkObjOrId) && (!$linkObjOrId->IsNew()))
{
$iKey = $linkObjOrId->GetKey();
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
$iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote);
$sPrefix .= "[$iKey][";
$sNameSuffix = "]"; // To make a tabular form
$aArgs['prefix'] = $sPrefix;
$aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}{$iKey}";
$aArgs['this'] = $linkObjOrId;
if($bReadOnly)
{
$aRow['form::checkbox'] = "";
foreach($this->m_aEditableFields as $sFieldCode)
{
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
$aRow[$sFieldCode] = $sDisplayValue;
}
}
else
{
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
foreach($this->m_aEditableFields as $sFieldCode)
{
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$linkObjOrId->GetKey().']';
$sSafeId = utils::GetSafeId($sFieldId);
$sValue = $linkObjOrId->Get($sFieldCode);
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId, $sNameSuffix, 0, $aArgs).
'</div></div></div>';
$aFieldsMap[$sFieldCode] = $sSafeId;
}
}
if ($bReadOnly)
{
$aRow['form::checkbox'] = "";
foreach ($this->m_aEditableFields as $sFieldCode)
{
$sDisplayValue = $linkObjOrId->GetEditValue($sFieldCode);
$aRow[$sFieldCode] = $sDisplayValue;
}
}
else
{
$aRow['form::checkbox'] = "<input class=\"selection\" data-remote-id=\"$iRemoteObjKey\" data-link-id=\"$iKey\" data-unique-id=\"$iUniqueId\" type=\"checkbox\" onClick=\"oWidget".$this->m_iInputId.".OnSelectChange();\" value=\"$iKey\">";
foreach ($this->m_aEditableFields as $sFieldCode)
{
$sSafeFieldId = $this->GetFieldId($linkObjOrId->GetKey(), $sFieldCode);
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $linkObjOrId, $oP, $sNameSuffix, $sSafeFieldId);
$aFieldsMap[$sFieldCode] = $sSafeFieldId;
}
}
$sState = $linkObjOrId->GetState();
$sRemoteKeySafeFieldId = $this->GetFieldId($aArgs['this']->GetKey(), $this->m_sExtKeyToRemote);;
}
else
{
@@ -180,15 +172,18 @@ class UILinksWidget
// New link existing only in memory
$oNewLinkObj = $linkObjOrId;
$iRemoteObjKey = $oNewLinkObj->Get($this->m_sExtKeyToRemote);
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
$oNewLinkObj->Set($this->m_sExtKeyToMe,
$oCurrentObj); // Setting the extkey with the object also fills the related external fields
}
else
{
$iRemoteObjKey = $linkObjOrId;
$oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass);
$oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, $iRemoteObjKey);
$oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
$oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields
$oNewLinkObj->Set($this->m_sExtKeyToRemote,
$oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields
$oNewLinkObj->Set($this->m_sExtKeyToMe,
$oCurrentObj); // Setting the extkey with the object also fills the related external fields
}
$sPrefix .= "[-$iUniqueId][";
$sNameSuffix = "]"; // To make a tabular form
@@ -222,58 +217,133 @@ EOF
foreach($this->m_aEditableFields as $sFieldCode)
{
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.-$iUniqueId.']';
$sSafeId = utils::GetSafeId($sFieldId);
$sSafeFieldId = $this->GetFieldId($iUniqueId, $sFieldCode);
$this->AddRowForFieldCode($aRow, $sFieldCode, $aArgs, $oNewLinkObj, $oP, $sNameSuffix, $sSafeFieldId);
$aFieldsMap[$sFieldCode] = $sSafeFieldId;
$sValue = $oNewLinkObj->Get($sFieldCode);
$sDisplayValue = $oNewLinkObj->GetEditValue($sFieldCode);
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
$aRow[$sFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'.
cmdbAbstractObject::GetFormElementForField($oP, $this->m_sLinkedClass, $sFieldCode, $oAttDef, $sValue, $sDisplayValue, $sSafeId /* id */, $sNameSuffix, 0, $aArgs).
'</div></div></div>';
$aFieldsMap[$sFieldCode] = $sSafeId;
$oP->add_ready_script(<<<EOF
$oP->add_ready_script(
<<<JS
oWidget{$this->m_iInputId}.OnValueChange($iKey, $iUniqueId, '$sFieldCode', '$sValue');
EOF
);
JS
);
}
$sState = '';
$sRemoteKeySafeFieldId = $this->GetFieldId($iUniqueId, $this->m_sExtKeyToRemote);
}
if(!$bReadOnly)
{
$sExtKeyToMeId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToMe);
$aFieldsMap[$this->m_sExtKeyToMe] = $sExtKeyToMeId;
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToMeId\" value=\"".$oCurrentObj->GetKey()."\">";
if (!$bReadOnly)
{
$sExtKeyToMeId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToMe);
$aFieldsMap[$this->m_sExtKeyToMe] = $sExtKeyToMeId;
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToMeId\" value=\"".$oCurrentObj->GetKey()."\">";
$sExtKeyToRemoteId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToRemote);
$aFieldsMap[$this->m_sExtKeyToRemote] = $sExtKeyToRemoteId;
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToRemoteId\" value=\"$iRemoteObjKey\">";
}
$sExtKeyToRemoteId = utils::GetSafeId($sPrefix.$this->m_sExtKeyToRemote);
$aFieldsMap[$this->m_sExtKeyToRemote] = $sExtKeyToRemoteId;
$aRow['form::checkbox'] .= "<input type=\"hidden\" id=\"$sExtKeyToRemoteId\" value=\"$iRemoteObjKey\">";
}
// Adding fields from remote class
// all fields are embedded in a span + added to $aFieldsMap array so that we can refresh them after extkey change
$aRemoteFieldsMap = [];
foreach (MetaModel::GetZListItems($this->m_sRemoteClass, 'list') as $sFieldCode)
{
$sSafeFieldId = $this->GetFieldId($aArgs['this']->GetKey(), $sFieldCode);
$aRow['static::'.$sFieldCode] = "<span id='field_$sSafeFieldId'>".$oLinkedObj->GetAsHTML($sFieldCode).'</span>';
$aRemoteFieldsMap[$sFieldCode] = $sSafeFieldId;
}
// id field is needed so that remote object could be load server side
$aRemoteFieldsMap['id'] = $sRemoteKeySafeFieldId;
// Generate WizardHelper to update dependant fields
$this->AddWizardHelperInit($oP, $aArgs['wizHelper'], $this->m_sLinkedClass, $sState, $aFieldsMap);
//instantiate specific WizarHelper instance for remote class fields refresh
$bHasExtKeyUpdatingRemoteClassFields = (
array_key_exists('replaceDependenciesByRemoteClassFields', $aArgs)
&& ($aArgs['replaceDependenciesByRemoteClassFields'])
);
if ($bHasExtKeyUpdatingRemoteClassFields)
{
$this->AddWizardHelperInit($oP, $aArgs['wizHelperRemote'], $this->m_sRemoteClass, $sState, $aRemoteFieldsMap);
}
return $aRow;
}
private function AddRowForFieldCode(&$aRow, $sFieldCode, &$aArgs, $oLnk, $oP, $sNameSuffix, $sSafeFieldId): void
{
if (($sFieldCode === $this->m_sExtKeyToRemote))
{
// current field is the lnk extkey to the remote class
$aArgs['replaceDependenciesByRemoteClassFields'] = true;
$sRowFieldCode = 'static::key';
$aArgs['wizHelperRemote'] = $aArgs['wizHelper'].'_remote';
$aRemoteAttDefs = MetaModel::GetZListAttDefsFilteredForIndirectRemoteClass($this->m_sRemoteClass);
$aRemoteCodes = array_map(
function ($value) {
return $value->GetCode();
},
$aRemoteAttDefs
);
$aArgs['remoteCodes'] = $aRemoteCodes;
}
else
{
$aArgs['replaceDependenciesByRemoteClassFields'] = false;
$sRowFieldCode = $sFieldCode;
}
$sValue = $oLnk->Get($sFieldCode);
$sDisplayValue = $oLnk->GetEditValue($sFieldCode);
$oAttDef = MetaModel::GetAttributeDef($this->m_sLinkedClass, $sFieldCode);
$aRow[$sRowFieldCode] = '<div class="field_container" style="border:none;"><div class="field_data"><div class="field_value">'
.cmdbAbstractObject::GetFormElementForField(
$oP,
$this->m_sLinkedClass,
$sFieldCode,
$oAttDef,
$sValue,
$sDisplayValue,
$sSafeFieldId,
$sNameSuffix,
0,
$aArgs
)
.'</div></div></div>';
}
private function GetFieldId($iLnkId, $sFieldCode, $bSafe = true)
{
$sFieldId = $this->m_iInputId.'_'.$sFieldCode.'['.$iLnkId.']';
return ($bSafe) ? utils::GetSafeId($sFieldId) : $sFieldId;
}
private function AddWizardHelperInit($oP, $sWizardHelperVarName, $sWizardHelperClass, $sState, $aFieldsMap): void
{
$iFieldsCount = count($aFieldsMap);
$sJsonFieldsMap = json_encode($aFieldsMap);
$oP->add_script(
<<<EOF
var {$aArgs['wizHelper']} = new WizardHelper('{$this->m_sLinkedClass}', '', '$sState');
{$aArgs['wizHelper']}.SetFieldsMap($sJsonFieldsMap);
{$aArgs['wizHelper']}.SetFieldsCount($iFieldsCount);
EOF
<<<JS
var $sWizardHelperVarName = new WizardHelper('$sWizardHelperClass', '', '$sState');
$sWizardHelperVarName.SetFieldsMap($sJsonFieldsMap);
$sWizardHelperVarName.SetFieldsCount($iFieldsCount);
$sWizardHelperVarName.SetReturnNotEditableFields(true);
$sWizardHelperVarName.SetWizHelperJsVarName('$sWizardHelperVarName');
JS
);
$aRow['static::key'] = $oLinkedObj->GetHyperLink();
foreach(MetaModel::GetZListItems($this->m_sRemoteClass, 'list') as $sFieldCode)
{
$aRow['static::'.$sFieldCode] = $oLinkedObj->GetAsHTML($sFieldCode);
}
return $aRow;
}
/**
* Display one row of the whole form
*
* @param WebPage $oP
* @param array $aConfig
* @param array $aRow
* @param int $iRowId
*
* @return string
*/
protected function DisplayFormRow(WebPage $oP, $aConfig, $aRow, $iRowId)
@@ -309,7 +379,7 @@ EOF
}
$sHtml .= "</tr>\n";
$sHtml .= "</thead>\n";
// Content
$sHtml .= "</tbody>\n";
$sEmptyRowStyle = '';
@@ -318,16 +388,16 @@ EOF
$sEmptyRowStyle = 'style="display:none;"';
}
foreach($aData as $iRowId => $aRow)
foreach ($aData as $iRowId => $aRow)
{
$sHtml .= $this->DisplayFormRow($oP, $aConfig, $aRow, $iRowId);
}
}
$sHtml .= "<tr $sEmptyRowStyle id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_empty_row\"><td colspan=\"".count($aConfig)."\" style=\"text-align:center;\">".Dict::S('UI:Message:EmptyList:UseAdd')."</td></tr>";
$sHtml .= "</tbody>\n";
// Footer
$sHtml .= "</table>\n";
return $sHtml;
}
@@ -360,20 +430,21 @@ EOF
$bDoSearch = !utils::IsHighCardinality($this->m_sRemoteClass);
$sJSDoSearch = $bDoSearch ? 'true' : 'false';
$sWizHelper = 'oWizardHelper'.$sFormPrefix;
$oPage->add_ready_script(<<<EOF
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}', $sJSDoSearch);
oWidget{$this->m_iInputId}.Init();
EOF
$oPage->add_ready_script(<<<JS
oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}', $sJSDoSearch);
oWidget{$this->m_iInputId}.Init();
JS
);
while($oCurrentLink = $oValue->Fetch())
while ($oCurrentLink = $oValue->Fetch())
{
// We try to retrieve the remote object as usual
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote), false /* Must not be found */);
// We try to retrieve the remote object as usual
$oLinkedObj = MetaModel::GetObject($this->m_sRemoteClass, $oCurrentLink->Get($this->m_sExtKeyToRemote),
false /* Must not be found */);
// If successful, it means that we can edit its link
if($oLinkedObj !== null)
{
$bReadOnly = false;
if ($oLinkedObj !== null)
{
$bReadOnly = false;
}
// Else we retrieve it without restrictions (silos) and will display its link as readonly
else

View File

@@ -309,6 +309,7 @@ class utils
case 'context_param':
case 'parameter':
case 'field_name':
case 'transaction_id':
if (is_array($value))
{
$retValue = array();
@@ -768,19 +769,22 @@ class utils
return new Config();
}
public static function InitTimeZone() {
$oConfig = self::GetConfig();
public static function InitTimeZone($oConfig = null)
{
if (is_null($oConfig))
{
$oConfig = self::GetConfig();
}
$sItopTimeZone = $oConfig->Get('timezone');
if (!empty($sItopTimeZone))
{
date_default_timezone_set($sItopTimeZone);
}
else
{
// Leave as is... up to the admin to set a value somewhere...
// see http://php.net/manual/en/datetime.configuration.php#ini.date.timezone
}
// else
// {
// // Leave as is... up to the admin to set a value somewhere...
// // see http://php.net/manual/en/datetime.configuration.php#ini.date.timezone
// }
}
/**
@@ -1389,13 +1393,12 @@ class utils
// For instance fopen does not allow to work around the bug: http://stackoverflow.com/questions/18191672/php-curl-ssl-routinesssl23-get-server-helloreason1112
// by setting the SSLVERSION to 3 as done below.
$aHeaders = explode("\n", $sOptionnalHeaders);
// N°3267 - Webservices: Fix optional headers not being taken into account
// See https://www.php.net/curl_setopt CURLOPT_HTTPHEADER
$aHTTPHeaders = array();
foreach($aHeaders as $sHeaderString)
{
if(preg_match('/^([^:]): (.+)$/', $sHeaderString, $aMatches))
{
$aHTTPHeaders[$aMatches[1]] = $aMatches[2];
}
$aHTTPHeaders[] = trim($sHeaderString);
}
// Default options, can be overloaded/extended with the 4th parameter of this method, see above $aCurlOptions
$aOptions = array(
@@ -2090,6 +2093,41 @@ class utils
return COMPILATION_TIMESTAMP;
}
/**
* @return string eg : '2_7_0' ITOP_VERSION is '2.7.1-dev'
*/
public static function GetItopVersionWikiSyntax()
{
$sMinorVersion = self::GetItopMinorVersion();
return str_replace('.', '_', $sMinorVersion).'_0';
}
/**
* @return string eg 2.7 if ITOP_VERSION is '2.7.0-dev'
* @throws \Exception
*/
public static function GetItopMinorVersion()
{
$sPatchVersion = self::GetItopPatchVersion();
$aExplodedVersion = explode('.', $sPatchVersion);
if (empty($aExplodedVersion[0]) || empty($aExplodedVersion[1]))
{
throw new Exception('iTop version is wrongfully configured!');
}
return sprintf('%d.%d', $aExplodedVersion[0], $aExplodedVersion[1]);
}
/**
* @return string eg '2.7.0' if ITOP_VERSION is '2.7.0-dev'
*/
public static function GetItopPatchVersion()
{
$aExplodedVersion = explode('-', ITOP_VERSION);
return $aExplodedVersion[0];
}
/**
* Check if the given class if configured as a high cardinality class.
*
@@ -2190,7 +2228,7 @@ class utils
* @param string $sPath for example '/var/www/html/itop/data/backups/manual/itop_27-2019-10-03_15_35.tar.gz'
* @param string $sBasePath for example '/var/www/html/itop/data/'
*
* @return bool false if path :
* @return bool|string false if path :
* * invalid
* * not allowed
* * not contained in base path

View File

@@ -335,20 +335,41 @@ class WizardHelper
{
$sResult = $this->m_aData['m_oFieldsMap'][$sFieldName];
}
return $sResult;
}
public function GetReturnNotEditableFields()
{
return $this->m_aData['m_bReturnNotEditableFields'] ?? false;
}
/**
* @return string JS code to be executed for fields update
* @since 2.8.0 N°3198
*/
public function GetJsForUpdateFields()
{
$sWizardHelperJsVar = ($this->m_aData['m_sWizHelperJsVarName']) ?? 'oWizardHelper'.$this->GetFormPrefix();
$sWizardHelperJson = $this->ToJSON();
return <<<JS
{$sWizardHelperJsVar}.m_oData = {$sWizardHelperJson};
{$sWizardHelperJsVar}.UpdateFields();
JS;
}
static function ParseJsonSet($oMe, $sLinkClass, $sExtKeyToMe, $sJsonSet)
{
$aSet = json_decode($sJsonSet, true); // true means hash array instead of object
$oSet = CMDBObjectSet::FromScratch($sLinkClass);
foreach($aSet as $aLinkObj)
foreach ($aSet as $aLinkObj)
{
$oLink = MetaModel::NewObject($sLinkClass);
foreach($aLinkObj as $sAttCode => $value)
foreach ($aLinkObj as $sAttCode => $value)
{
$oAttDef = MetaModel::GetAttributeDef($sLinkClass, $sAttCode);
if (($oAttDef->IsExternalKey()) && ($value != '') && ($value > 0))
if (($oAttDef->IsExternalKey()) && ($value != '') && ($value > 0))
{
// For external keys: load the target object so that external fields
// get filled too

View File

@@ -2,7 +2,7 @@
"type": "project",
"license": "AGPLv3",
"require": {
"php": ">=7.2.0",
"php": ">=7.1.3",
"ext-ctype": "*",
"ext-dom": "*",
"ext-gd": "*",
@@ -51,7 +51,8 @@
"core",
"application",
"sources/application",
"sources/Composer"
"sources/Composer",
"sources/Controller"
],
"exclude-from-classmap": [
"core/dbobjectsearch.class.php",

View File

@@ -18,6 +18,7 @@
*/
use Combodo\iTop\Form\Field\LabelField;
use Combodo\iTop\Form\Field\TextAreaField;
use Combodo\iTop\Form\Validator\NotEmptyExtKeyValidator;
use Combodo\iTop\Form\Validator\Validator;
@@ -7466,6 +7467,12 @@ class AttributeExternalField extends AttributeDefinition
}
}
parent::MakeFormField($oObject, $oFormField);
if ($oFormField instanceof TextAreaField) {
if (method_exists($oRemoteAttDef, 'GetFormat')) {
/** @var \Combodo\iTop\Form\Field\TextAreaField $oFormField */
$oFormField->SetFormat($oRemoteAttDef->GetFormat());
}
}
// Manually setting for remote ExternalKey, otherwise, the id would be displayed.
if ($oRemoteAttDef instanceof AttributeExternalKey)
@@ -7483,6 +7490,16 @@ class AttributeExternalField extends AttributeDefinition
{
return false;
}
public function GetFormat()
{
$oRemoteAttDef = $this->GetExtAttDef();
if (method_exists($oRemoteAttDef, 'GetFormat')) {
/** @var \Combodo\iTop\Form\Field\TextAreaField $oFormField */
return $oRemoteAttDef->GetFormat();
}
return 'text';
}
}

View File

@@ -185,12 +185,9 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
static::DEFAULT_MODULE_SETTING_ENABLED
);
$sItopTimeZone = $this->getOConfig()->Get('timezone');
$timezone = new DateTimeZone($sItopTimeZone);
if (!$bEnabled)
{
return new DateTime('3000-01-01', $timezone);
return new DateTime('3000-01-01');
}
// 1st - Interpret the list of days as ordered numbers (monday = 1)
@@ -209,7 +206,7 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
throw new ProcessInvalidConfigException($this->GetModuleName().": wrong format for setting '".static::MODULE_SETTING_TIME."' (found '$sProcessTime')");
}
$oNow = new DateTime($sCurrentTime, $timezone);
$oNow = new DateTime($sCurrentTime);
$iNextPos = false;
$sDay = $oNow->format('N');
for ($iDay = (int) $sDay; $iDay <= 7; $iDay++)
@@ -244,7 +241,6 @@ abstract class AbstractWeeklyScheduledProcess implements iScheduledProcess
$oRet->modify('+'.$iMove.' days');
}
list($sHours, $sMinutes) = explode(':', $sProcessTime);
/** @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection non used new parameter in PHP 7.1 */
$oRet->setTime((int)$sHours, (int)$sMinutes);
return $oRet;

View File

@@ -26,6 +26,24 @@
*/
class BackgroundTask extends DBObject
{
protected $bDebug = false;
/**
* @return bool
*/
public function IsDebug()
{
return $this->bDebug;
}
/**
* @param bool $bDebug
*/
public function SetDebug($bDebug)
{
$this->bDebug = $bDebug;
}
public static function Init()
{
$aParams = array
@@ -54,7 +72,7 @@ class BackgroundTask extends DBObject
MetaModel::Init_AddAttribute(new AttributeDecimal("average_run_duration", array("allowed_values"=>null, "sql"=>"average_run_duration", "digits"=> 8, "decimals"=> 3, "default_value"=>"0", "is_null_allowed"=>true, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeBoolean("running", array("allowed_values"=>null, "sql"=>"running", "default_value"=>false, "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('active,paused'), "sql"=>"status", "default_value"=>'active', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeEnum("status", array("allowed_values"=>new ValueSetEnum('active,paused,removed'), "sql"=>"status", "default_value"=>'active', "is_null_allowed"=>false, "depends_on"=>array())));
MetaModel::Init_AddAttribute(new AttributeString("system_user", array("allowed_values"=>null, "sql"=>"system_user", "default_value"=>null, "is_null_allowed"=>true, "depends_on"=>array())));
}

View File

@@ -345,10 +345,10 @@ abstract class BulkExport
$this->oBulkExportResult->Set('format', $this->sFormatCode);
$this->oBulkExportResult->Set('search', $this->oSearch->serialize());
$this->oBulkExportResult->Set('chunk_size', $this->iChunkSize);
$this->oBulkExportResult->Set('temp_file_path', $this->sTmpFile);
$this->oBulkExportResult->Set('localize_output', $this->bLocalizeOutput);
}
$this->oBulkExportResult->Set('status_info', json_encode($this->GetStatusInfo()));
$this->oBulkExportResult->Set('temp_file_path', $this->sTmpFile);
utils::PushArchiveMode(false);
$ret = $this->oBulkExportResult->DBWrite();
utils::PopArchiveMode();
@@ -420,6 +420,11 @@ abstract class BulkExport
public function GetStatistics()
{
}
public function SetFields($sFields)
{
}
public function GetDownloadFileName()

View File

@@ -95,11 +95,17 @@ abstract class CMDBObject extends DBObject
protected static $m_oCurrChange = null;
protected static $m_sInfo = null; // null => the information is built in a standard way
protected static $m_sOrigin = null; // null => the origin is 'interactive'
/**
* Specify another change (this is mainly for backward compatibility)
* Specify the change to be used by the API to attach any CMDBChangeOp* object created
*
* @see SetTrackInfo if CurrentChange is null, then a new one will be create using trackinfo
*
* @param CMDBChange|null $oChange use null so that the API will recreate a new CMDBChange using TrackInfo & TrackOrigin
*
* @since 2.7.2 N°3219 can now reset CMDBChange by passing null
*/
public static function SetCurrentChange(CMDBChange $oChange)
public static function SetCurrentChange($oChange)
{
self::$m_oCurrChange = $oChange;
}
@@ -126,11 +132,15 @@ abstract class CMDBObject extends DBObject
/**
* Override the additional information (defaulting to user name)
* A call to this verb should replace every occurence of
* $oMyChange = MetaModel::NewObject("CMDBChange");
* $oMyChange = MetaModel::NewObject("CMDBChange");
* $oMyChange->Set("date", time());
* $oMyChange->Set("userinfo", 'this is done by ... for ...');
* $iChangeId = $oMyChange->DBInsert();
*/
*
* @see SetCurrentChange to specify a CMDBObject instance instead
*
* @param string $sInfo
*/
public static function SetTrackInfo($sInfo)
{
self::$m_sInfo = $sInfo;
@@ -138,8 +148,13 @@ abstract class CMDBObject extends DBObject
/**
* Provides information about the origin of the change
* @param $sOrigin String: one of: interactive, csv-interactive, csv-import.php, webservice-soap, webservice-rest, syncho-data-source, email-processing, custom-extension
*/
*
* @see SetTrackInfo
* @see SetCurrentChange to specify a CMDBObject instance instead
*
* @param $sOrigin String: one of: interactive, csv-interactive, csv-import.php, webservice-soap, webservice-rest, syncho-data-source,
* email-processing, custom-extension
*/
public static function SetTrackOrigin($sOrigin)
{
self::$m_sOrigin = $sOrigin;
@@ -488,7 +503,13 @@ abstract class CMDBObject extends DBObject
/**
* Helper to ultimately check user rights before writing (Insert, Update or Delete)
* The check should never fail, because the UI should prevent from such a usage
* Anyhow, if the user has found a workaround... the security gets enforced here
* Anyhow, if the user has found a workaround... the security gets enforced here
*
* @param $bSkipStrongSecurity
* @param $iActionCode
*
* @throws \SecurityException
* @deprecated in 2.8.0 will be removed in 2.9
*/
protected function CheckUserRights($bSkipStrongSecurity, $iActionCode)
{

View File

@@ -547,72 +547,64 @@ abstract class DBObject implements iDisplay
*/
public function Set($sAttCode, $value)
{
if ($sAttCode == 'finalclass')
{
if ($sAttCode == 'finalclass') {
// Ignore it - this attribute is set upon object creation and that's it
return false;
}
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
if (!$oAttDef->IsWritable())
{
if (!$oAttDef->IsWritable()) {
$sClass = get_class($this);
throw new Exception("Attempting to set the value on the read-only attribute $sClass::$sAttCode");
}
if ($this->m_bIsInDB && !$this->m_bFullyLoaded && !$this->m_bDirty)
{
if ($this->m_bIsInDB && !$this->m_bFullyLoaded && !$this->m_bDirty) {
// First time Set is called... ensure that the object gets fully loaded
// Otherwise we would lose the values on a further Reload
// + consistency does not make sense !
$this->Reload();
}
if ($oAttDef->IsExternalKey() && is_object($value))
{
if ($oAttDef->IsExternalKey() && is_object($value)) {
// Setting an external key with a whole object (instead of just an ID)
// let's initialize also the external fields that depend on it
// (useful when building objects in memory and not from a query)
/** @var \AttributeExternalKey $oAttDef */
if ((get_class($value) != $oAttDef->GetTargetClass()) && (!is_subclass_of($value, $oAttDef->GetTargetClass())))
{
if ((get_class($value) != $oAttDef->GetTargetClass()) && (!is_subclass_of($value, $oAttDef->GetTargetClass()))) {
throw new CoreUnexpectedValue("Trying to set the value of '$sAttCode', to an object of class '".get_class($value)."', whereas it's an ExtKey to '".$oAttDef->GetTargetClass()."'. Ignored");
}
foreach (MetaModel::ListAttributeDefs(get_class($this)) as $sCode => $oDef)
{
foreach (MetaModel::GetDependentAttributes(get_class($this), $sAttCode) as $sCode) {
$oDef = MetaModel::GetAttributeDef(get_class($this), $sCode);
/** @var \AttributeExternalField $oDef */
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode))
{
if ($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode)) {
/** @var \DBObject $value */
$this->m_aCurrValues[$sCode] = $value->Get($oDef->GetExtAttCode());
$this->m_aLoadedAtt[$sCode] = true;
}
elseif (in_array($sAttCode, $oDef->GetPrerequisiteAttributes(get_class($this))))
{
elseif ($oDef->IsBasedOnOQLExpression()) {
$this->m_aCurrValues[$sCode] = $this->GetDefaultValue($sCode);
unset($this->m_aLoadedAtt[$sCode]);
}
}
}
else if ($this->m_aCurrValues[$sAttCode] !== $value)
{
// Invalidate dependent fields so that they get reloaded in case they are needed (See Get())
//
foreach (MetaModel::GetDependentAttributes(get_class($this), $sAttCode) as $sCode)
{
$this->m_aCurrValues[$sCode] = $this->GetDefaultValue($sCode);
unset($this->m_aLoadedAtt[$sCode]);
} else {
if ($this->m_aCurrValues[$sAttCode] !== $value) {
// Invalidate dependent fields so that they get reloaded in case they are needed (See Get())
//
foreach (MetaModel::GetDependentAttributes(get_class($this), $sAttCode) as $sCode) {
$oDef = MetaModel::GetAttributeDef(get_class($this), $sCode);
if (($oDef->IsExternalField() && ($oDef->GetKeyAttCode() == $sAttCode)) || $oDef->IsBasedOnOQLExpression()) {
$this->m_aCurrValues[$sCode] = $this->GetDefaultValue($sCode);
unset($this->m_aLoadedAtt[$sCode]);
}
}
}
}
if ($oAttDef->IsLinkSet() && ($value != null))
{
if ($oAttDef->IsLinkSet() && ($value != null)) {
$realvalue = clone $this->m_aCurrValues[$sAttCode];
$realvalue->UpdateFromCompleteList($value);
}
else
{
} else {
$realvalue = $oAttDef->MakeRealValue($value, $this);
}
$this->_Set($sAttCode, $realvalue);

View File

@@ -443,7 +443,6 @@ class DBObjectSearch extends DBSearch
case '<|':
case '=|':
throw new CoreException('Deprecated operator, please consider using OQL (SQL) expressions like "(TO_DAYS(NOW()) - TO_DAYS(x)) AS AgeDays"', array('operator' => $sOpCode));
break;
case 'IN':
if (!is_array($value)) $value = array($value);
@@ -625,17 +624,32 @@ class DBObjectSearch extends DBSearch
public function AddCondition_FullText($sNeedle)
{
// Transform the full text condition into additional condition expression
$aFullTextFields = array();
foreach (MetaModel::ListAttributeDefs($this->GetClass()) as $sAttCode => $oAttDef)
{
$aAttCodes = [];
foreach (MetaModel::ListAttributeDefs($this->GetClass()) as $sAttCode => $oAttDef) {
if (!$oAttDef->IsScalar()) continue;
if ($oAttDef->IsExternalKey()) continue;
if (!$oAttDef->IsSearchable()) continue;
$aAttCodes[] = $sAttCode;
}
$this->AddCondition_FullTextOnAttributes($aAttCodes, $sNeedle);
}
/**
* @param array $aAttCodes array of attCodes to search into
* @param string $sNeedle one word to be searched
*
* @throws \CoreException
*/
public function AddCondition_FullTextOnAttributes(array $aAttCodes, $sNeedle)
{
$aFullTextFields = [];
foreach ($aAttCodes as $sAttCode) {
$aFullTextFields[] = new FieldExpression($sAttCode, $this->GetClassAlias());
}
$oTextFields = new CharConcatWSExpression(' ', $aFullTextFields);
$sQueryParam = 'needle';
$sQueryParam = str_replace('.', '', uniqid('needle_', true));
$oFlexNeedle = new CharConcatExpression(array(new ScalarExpression('%'), new VariableExpression($sQueryParam), new ScalarExpression('%')));
$oNewCond = new BinaryExpression($oTextFields, 'LIKE', $oFlexNeedle);
@@ -792,10 +806,11 @@ class DBObjectSearch extends DBSearch
* Helper to
* - convert a translation table (format optimized for the translation in an expression tree) into simple hash
* - compile over an eventually existing map
* - accept multiple translations for the same alias for unions
*
* @param array $aRealiasingMap Map to update
* @param array $aAliasTranslation Translation table resulting from calls to MergeWith_InNamespace
* @return void of <old-alias> => <new-alias>
* @return void of [old-alias][] => new-alias (@since 2.7.2)
*/
protected function UpdateRealiasingMap(&$aRealiasingMap, $aAliasTranslation)
{
@@ -803,17 +818,33 @@ class DBObjectSearch extends DBSearch
{
foreach ($aAliasTranslation as $sPrevAlias => $aRules)
{
if (isset($aRules['*']))
if (!isset($aRules['*']))
{
$sNewAlias = $aRules['*'];
$sOriginalAlias = array_search($sPrevAlias, $aRealiasingMap);
if ($sOriginalAlias !== false)
continue;
}
$sNewAlias = $aRules['*'];
$bOriginalFound = false;
$iIndex = 0;
foreach ($aRealiasingMap as $sOriginalAlias => $aAliases)
{
$iIndex = array_search($sPrevAlias, $aAliases);
if ($iIndex !== false)
{
$aRealiasingMap[$sOriginalAlias] = $sNewAlias;
$bOriginalFound = true;
break;
}
else
}
if ($bOriginalFound)
{
$aRealiasingMap[$sOriginalAlias][$iIndex] = $sNewAlias;
}
else
{
if (!isset($aRealiasingMap[$sPrevAlias]) || !in_array($sNewAlias, $aRealiasingMap[$sPrevAlias]))
{
$aRealiasingMap[$sPrevAlias] = $sNewAlias;
$aRealiasingMap[$sPrevAlias][] = $sNewAlias;
}
}
}
@@ -861,7 +892,7 @@ class DBObjectSearch extends DBSearch
/**
* Add a link to another filter, using an extkey already present in current filter
*
* @param DBObjectSearch $oFilter filter to join to
* @param DBObjectSearch $oFilter filter to join to (can be modified)
* @param string $sExtKeyAttCode extkey present in current filter, that allows to points to $oFilter
* @param int $iOperatorCode
* @param array $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed.
@@ -955,7 +986,7 @@ class DBObjectSearch extends DBSearch
}
/**
* @param DBObjectSearch $oFilter
* @param DBObjectSearch $oFilter (can be modified)
* @param $sForeignExtKeyAttCode
* @param int $iOperatorCode
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed

View File

@@ -222,6 +222,7 @@ class DBObjectSet implements iDBObjectSetIterator
if (!is_array($aAttToLoad))
{
$this->m_aAttToLoad = null;
trigger_error ( "OptimizeColumnLoad : wrong format actual :(".print_r($aAttToLoad, true)."). should be [alias=>[attributes]]", E_USER_WARNING );
return;
}
foreach ($aAttToLoad as $sAlias => $aAttCodes)
@@ -229,6 +230,7 @@ class DBObjectSet implements iDBObjectSetIterator
if (!is_array($aAttCodes))
{
$this->m_aAttToLoad = null;
trigger_error ( "OptimizeColumnLoad : wrong format actual :(".print_r($aAttToLoad, true)."). should be [alias=>[attributes]]", E_USER_WARNING );
return;
}
}
@@ -267,6 +269,7 @@ class DBObjectSet implements iDBObjectSetIterator
}
}
}
// Add the friendly name anytime
$oFriendlyNameAttDef = MetaModel::GetAttributeDef($sClass, 'friendlyname');
$aAttToLoadWithAttDef[$sClassAlias]['friendlyname'] = $oFriendlyNameAttDef;

View File

@@ -404,7 +404,9 @@ abstract class DBSearch
*/
abstract public function AddCondition_FullText($sFullText);
/**
abstract public function AddCondition_FullTextOnAttributes(array $aAttCodes, $sNeedle);
/**
* Perform a join, the remote class being matched by the mean of its primary key
*
* The join is performed
@@ -631,7 +633,7 @@ abstract class DBSearch
}
$sOql = $this->ToOql($bDevelopParams, $aContextParams);
return json_encode(array($sOql, $aQueryParams, $this->m_aModifierProperties));
return urlencode(json_encode(array($sOql, $aQueryParams, $this->m_aModifierProperties)));
}
/**
@@ -648,7 +650,7 @@ abstract class DBSearch
*/
static public function unserialize($sValue)
{
$aData = json_decode($sValue, true);
$aData = json_decode(urldecode($sValue), true);
if (is_null($aData))
{
throw new CoreException("Invalid filter parameter");
@@ -1112,6 +1114,8 @@ abstract class DBSearch
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
*
* @since 2.7.0 N°2555
*/
public function GetFirstResult($bMustHaveOneResultMax = true, $aOrderBy = array(), $aSearchParams = array())
{

View File

@@ -376,19 +376,26 @@ class DBUnionSearch extends DBSearch
}
}
/**
public function AddCondition_FullTextOnAttributes(array $aAttCodes, $sNeedle)
{
foreach ($this->aSearches as $oSearch)
{
$oSearch->AddCondition_FullTextOnAttributes($aAttCodes, $sNeedle);
}
}
/**
* @param DBObjectSearch $oFilter
* @param $sExtKeyAttCode
* @param int $iOperatorCode
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
* @throws CoreException
* @throws CoreWarning
* @param null $aRealiasingMap array of [old-alias][] => <new-alias>, for each alias that has changed (@since 2.7.2)
*/
public function AddCondition_PointingTo(DBObjectSearch $oFilter, $sExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
{
foreach ($this->aSearches as $oSearch)
{
$oSearch->AddCondition_PointingTo($oFilter, $sExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
$oConditionFilter = $oFilter->DeepClone();
$oSearch->AddCondition_PointingTo($oConditionFilter, $sExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
}
}
@@ -396,13 +403,14 @@ class DBUnionSearch extends DBSearch
* @param DBObjectSearch $oFilter
* @param $sForeignExtKeyAttCode
* @param int $iOperatorCode
* @param null $aRealiasingMap array of <old-alias> => <new-alias>, for each alias that has changed
* @param null $aRealiasingMap array of [old-alias][] => <new-alias>, for each alias that has changed (@since 2.7.2)
*/
public function AddCondition_ReferencedBy(DBObjectSearch $oFilter, $sForeignExtKeyAttCode, $iOperatorCode = TREE_OPERATOR_EQUALS, &$aRealiasingMap = null)
{
foreach ($this->aSearches as $oSearch)
{
$oSearch->AddCondition_ReferencedBy($oFilter, $sForeignExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
$oConditionFilter = $oFilter->DeepClone();
$oSearch->AddCondition_ReferencedBy($oConditionFilter, $sForeignExtKeyAttCode, $iOperatorCode, $aRealiasingMap);
}
}

View File

@@ -353,7 +353,8 @@ EOF
$fStartExcel = microtime(true);
$writer = new XLSXWriter();
$oDateTimeFormat = new DateTimeFormat($this->aStatusInfo['date_format']);
$sDateFormat = isset($this->aStatusInfo['date_format']) ? $this->aStatusInfo['date_format'] : (string)AttributeDateTime::GetFormat();
$oDateTimeFormat = new DateTimeFormat($sDateFormat);
$writer->setDateTimeFormat($oDateTimeFormat->ToExcel());
$oDateFormat = new DateTimeFormat($oDateTimeFormat->ToDateFormat());
$writer->setDateFormat($oDateFormat->ToExcel());

View File

@@ -129,8 +129,7 @@ abstract class RotatingLogFileNameBuilder implements iLogFileNameBuilder
public function CheckAndRotateLogFile()
{
$oConfig = utils::GetConfig();
$sItopTimeZone = $oConfig->Get('timezone');
$timezone = new DateTimeZone($sItopTimeZone);
utils::InitTimeZone($oConfig);
if ($this->GetLastModifiedDateForFile() === null)
{
@@ -145,11 +144,13 @@ abstract class RotatingLogFileNameBuilder implements iLogFileNameBuilder
return;
}
$oDateTime = DateTime::createFromFormat('U', $iLogDateLastModifiedTimeStamp);
$sItopTimeZone = $oConfig->Get('timezone');
$timezone = new DateTimeZone($sItopTimeZone);
$oDateTime->setTimezone($timezone);
$this->SetLastModifiedDateForFile($oDateTime);
}
$oNow = new DateTime('now', $timezone);
$oNow = new DateTime();
$bShouldRotate = $this->ShouldRotate($this->GetLastModifiedDateForFile(), $oNow);
if (!$bShouldRotate)
{
@@ -830,4 +831,4 @@ class LogFileRotationProcess implements iScheduledProcess
throw new ProcessException(self::class.' : The configured filename builder is invalid (log_filename_builder_impl="'.$sLogFileNameBuilder.'")');
}
}
}

View File

@@ -126,6 +126,13 @@ abstract class MetaModel
/** @var string */
protected static $m_sEnvironment = 'production';
/**
* MetaModel constructor.
*/
public function __construct()
{
}
/**
* @return array
*/
@@ -741,7 +748,51 @@ abstract class MetaModel
return array('%1$s', array($nameRawSpec));
}
}
/**
* @param string $sClass
*
* @return array
* @throws \CoreException
* @throws \DictExceptionMissingString
*/
final static public function GetComplementAttributeSpec($sClass)
{
self::_check_subclass($sClass);
if (!isset(self::$m_aClassParams[$sClass]["name_complement_for_select"]))
{
return array($sClass, array());
}
$nameRawSpec = self::$m_aClassParams[$sClass]["name_complement_for_select"];
if (is_array($nameRawSpec))
{
$sFormat = Dict::S("Class:$sClass/ComplementForSelect", '');
if (strlen($sFormat) == 0)
{
// Default to "%1$s %2$s..."
for($i = 1; $i <= count($nameRawSpec); $i++)
{
if (empty($sFormat))
{
$sFormat .= '%'.$i.'$s';
}
else
{
$sFormat .= ' %'.$i.'$s';
}
}
}
return array($sFormat, $nameRawSpec);
}
elseif (empty($nameRawSpec))
{
return array($sClass, array());
}
else
{
// string -> attcode
return array('%1$s', array($nameRawSpec));
}
}
/**
* Get the friendly name expression for a given class
*
@@ -1848,7 +1899,7 @@ abstract class MetaModel
* @param string $sClass
* @param string $sListCode
*
* @return array
* @return array list of attribute codes
*/
public static function GetZListItems($sClass, $sListCode)
{
@@ -1868,6 +1919,82 @@ abstract class MetaModel
return self::GetZListItems($sParentClass, $sListCode);
}
/**
* @param string $sRemoteClass
*
* @return \AttributeDefinition[] list of attdefs to display by default for the remote class
*
* @since 2.8.0 N°2334
*/
public static function GetZListAttDefsFilteredForIndirectRemoteClass($sRemoteClass)
{
$aAttCodesToPrint = [];
foreach (MetaModel::GetZListItems($sRemoteClass, 'list') as $sFieldCode)
{
//TODO: check the state of the attribute: hidden or visible ?
if ($sFieldCode == 'finalclass')
{
continue;
}
$oRemoteAttDef = MetaModel::GetAttributeDef($sRemoteClass, $sFieldCode);
$aAttCodesToPrint[] = $oRemoteAttDef;
}
return $aAttCodesToPrint;
}
/**
* @param string $sClass left class
* @param string $sAttCode AttributeLinkedSetIndirect attcode
*
* @return \AttributeDefinition[] list of attdefs to display by default for lnk class
*
* @throws \CoreException
* @since 2.8.0 N°2334
*/
public static function GetZListAttDefsFilteredForIndirectLinkClass($sClass, $sAttCode)
{
$aAttCodesToPrint = [];
$oLinkedSetAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode);
$sLinkedClass = $oLinkedSetAttDef->GetLinkedClass();
$sExtKeyToRemote = $oLinkedSetAttDef->GetExtKeyToRemote();
$sExtKeyToMe = $oLinkedSetAttDef->GetExtKeyToMe();
$sStateAttCode = MetaModel::GetStateAttributeCode($sClass);
$sDefaultState = MetaModel::GetDefaultState($sClass);
foreach (MetaModel::FlattenZList(MetaModel::GetZListItems($sLinkedClass, 'list')) as $sLnkAttCode)
{
$oLnkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sLnkAttCode);
if ($sStateAttCode == $sLnkAttCode)
{
// State attribute is always hidden from the UI
continue;
}
if (($sLnkAttCode == $sExtKeyToMe)
|| ($sLnkAttCode == $sExtKeyToRemote)
|| ($sLnkAttCode == 'finalclass'))
{
continue;
}
if (!($oLnkAttDef->IsWritable()))
{
continue;
}
$iFlags = MetaModel::GetAttributeFlags($sLinkedClass, $sDefaultState, $sLnkAttCode);
if (!($iFlags & OPT_ATT_HIDDEN) && !($iFlags & OPT_ATT_READONLY))
{
$aAttCodesToPrint[] = $oLnkAttDef;
}
}
return $aAttCodesToPrint;
}
/**
* @param string $sClass
* @param string $sListCode
@@ -2681,7 +2808,7 @@ abstract class MetaModel
$aInterfaces = array('iApplicationUIExtension', 'iPreferencesExtension', 'iApplicationObjectExtension', 'iLoginFSMExtension', 'iLoginUIExtension', 'iLogoutExtension', 'iQueryModifier', 'iOnClassInitialization', 'iPopupMenuExtension', 'iPageUIExtension', 'iPortalUIExtension', 'ModuleHandlerApiInterface', 'iNewsroomProvider', 'iModuleExtension');
foreach($aInterfaces as $sInterface)
{
self::$m_aExtensionClasses[$sInterface] = array();
self::$m_aExtensionClassNames[$sInterface] = array();
}
foreach(get_declared_classes() as $sPHPClass)
@@ -2692,11 +2819,7 @@ abstract class MetaModel
{
if ($oRefClass->implementsInterface($sInterface) && $oRefClass->isInstantiable())
{
if (is_null($oExtensionInstance))
{
$oExtensionInstance = new $sPHPClass;
}
self::$m_aExtensionClasses[$sInterface][$sPHPClass] = $oExtensionInstance;
self::$m_aExtensionClassNames[$sInterface][$sPHPClass] = $sPHPClass;
}
}
}
@@ -4068,7 +4191,7 @@ abstract class MetaModel
{
$oSearch = DBObjectSearch::FromOQL("SELECT Contact WHERE id = :id");
$oSet = new DBObjectSet($oSearch, array(), array('id' => UserRights::GetContactId()));
$oSet->OptimizeColumnLoad($aCurrentContact);
$oSet->OptimizeColumnLoad(['Contact' => $aCurrentContact]);
$oUser = $oSet->fetch();
foreach ($aCurrentContact as $sField)
{
@@ -5421,7 +5544,7 @@ abstract class MetaModel
{
$sIndexName = $sField;
$sColumns = '`'.$sField.'`';
if (!is_null($aLength[0]))
if (isset($aLength[0]))
{
$sColumns .= ' ('.$aLength[0].')';
}
@@ -6185,6 +6308,7 @@ abstract class MetaModel
// N°2478 utils has his own private attribute
// @see utils::GetConfig : it always call MetaModel, but to be sure we're doing this extra copy anyway O:)
utils::InitTimeZone($oConfiguration);
utils::SetConfig($oConfiguration);
// Set log ASAP
@@ -6225,19 +6349,6 @@ abstract class MetaModel
DBSearch::EnableQueryIndentation(self::$m_oConfig->Get('query_indentation_enabled'));
DBSearch::EnableOptimizeQuery(self::$m_oConfig->Get('query_optimization_enabled'));
// PHP timezone first...
//
$sPHPTimezone = self::$m_oConfig->Get('timezone');
if ($sPHPTimezone == '')
{
// Leave as is... up to the admin to set a value somewhere...
//$sPHPTimezone = date_default_timezone_get();
}
else
{
date_default_timezone_set($sPHPTimezone);
}
// Note: load the dictionary as soon as possible, because it might be
// needed when some error occur
$sAppIdentity = 'itop-'.MetaModel::GetEnvironmentId();
@@ -6281,7 +6392,7 @@ abstract class MetaModel
if (is_array($result))
{
// todo - verifier que toutes les classes mentionnees ici sont chargees dans InitClasses()
self::$m_aExtensionClasses = $result['m_aExtensionClasses'];
self::$m_aExtensionClassNames = $result['m_aExtensionClassNames'];
self::$m_Category2Class = $result['m_Category2Class'];
self::$m_aRootClasses = $result['m_aRootClasses'];
self::$m_aParentClasses = $result['m_aParentClasses'];
@@ -6318,7 +6429,7 @@ abstract class MetaModel
$oKPI = new ExecutionKPI();
$aCache = array();
$aCache['m_aExtensionClasses'] = self::$m_aExtensionClasses;
$aCache['m_aExtensionClassNames'] = self::$m_aExtensionClassNames;
$aCache['m_Category2Class'] = self::$m_Category2Class;
$aCache['m_aRootClasses'] = self::$m_aRootClasses; // array of "classname" => "rootclass"
$aCache['m_aParentClasses'] = self::$m_aParentClasses; // array of ("classname" => array of "parentclass")
@@ -6402,8 +6513,8 @@ abstract class MetaModel
return md5(APPROOT).'-'.self::$m_sEnvironment;
}
/** @var array */
protected static $m_aExtensionClasses = array();
/** @var array */
protected static $m_aExtensionClassNames = [];
/**
* @param string $sToInclude
@@ -7198,25 +7309,9 @@ abstract class MetaModel
*/
public static function EnumPlugins($sInterface, $sFilterInstanceOf = null)
{
if (!array_key_exists($sInterface, self::$m_aExtensionClasses))
{
return array();
}
$pluginManager = new PluginManager(self::$m_aExtensionClassNames);
if (is_null($sFilterInstanceOf))
{
return self::$m_aExtensionClasses[$sInterface];
}
$fFilterCallback = function ($instance) use ($sFilterInstanceOf)
{
return $instance instanceof $sFilterInstanceOf;
};
return array_filter(
self::$m_aExtensionClasses[$sInterface],
$fFilterCallback
);
return $pluginManager->EnumPlugins($sInterface, $sFilterInstanceOf);
}
/**
@@ -7227,16 +7322,9 @@ abstract class MetaModel
*/
public static function GetPlugins($sInterface, $sClassName)
{
$oInstance = null;
if (array_key_exists($sInterface, self::$m_aExtensionClasses))
{
if (array_key_exists($sClassName, self::$m_aExtensionClasses[$sInterface]))
{
return self::$m_aExtensionClasses[$sInterface][$sClassName];
}
}
$pluginManager = new PluginManager(self::$m_aExtensionClassNames);
return $oInstance;
return $pluginManager->GetPlugins($sInterface, $sClassName);
}
/**

View File

@@ -2235,7 +2235,15 @@ class ListExpression extends Expression
{
if ($oExpr instanceof VariableExpression)
{
$this->m_aExpressions[$idx] = $oExpr->GetAsScalar($aArgs);
$oVarExpr = $oExpr->GetAsScalar($aArgs);
if ($oVarExpr instanceof ListExpression)
{
$this->m_aExpressions = $oVarExpr->GetItems();
}
else
{
$this->m_aExpressions[$idx] = $oVarExpr;
}
}
else
{

View File

@@ -30,6 +30,9 @@ require_once('dbobjectiterator.php');
class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
{
const LINK_ALIAS = 'Link';
const REMOTE_ALIAS = 'Remote';
protected $sHostClass; // subclass of DBObject
protected $sAttCode; // xxxxxx_list
protected $sClass; // class of the links
@@ -786,11 +789,13 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
/**
* @param bool $bShowObsolete
*
* @return \DBObjectSet
* @return \DBObjectSet indirect relations will get `SELECT L,R ...` (l = lnk class, R = remote)
* @throws \CoreException
* @throws \CoreWarning
* @throws \MySQLException
* @throws \Exception
*
* @since 2.8.0 N°2334 returns both lnk and remote classes for indirect relations
*/
public function ToDBObjectSet($bShowObsolete = true)
{
@@ -802,7 +807,12 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
$sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
/** @var \AttributeExternalKey $oLinkingAttDef */
$oLinkingAttDef = MetaModel::GetAttributeDef($this->sClass, $sExtKeyToRemote);
// N°2334 add pointed class (SELECT L,R) to have all fields (lnk + remote) in display
// the pointed class is always present in the search, as generated by \AttributeLinkedSet::GetDefaultValue
$sTargetClass = $oLinkingAttDef->GetTargetClass();
$oRemoteClassSearch = new DBObjectSearch($sTargetClass);
if (!$bShowObsolete && MetaModel::IsObsoletable($sTargetClass))
{
$oNotObsolete = new BinaryExpression(
@@ -810,10 +820,24 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
'=',
new ScalarExpression(0)
);
$oNotObsoleteRemote = new DBObjectSearch($sTargetClass);
$oNotObsoleteRemote->AddConditionExpression($oNotObsolete);
$oLinkSearch->AddCondition_PointingTo($oNotObsoleteRemote, $sExtKeyToRemote);
$oRemoteClassSearch->AddConditionExpression($oNotObsolete);
}
if (!utils::IsArchiveMode() && MetaModel::IsArchivable($sTargetClass))
{
$oNotArchived = new BinaryExpression(
new FieldExpression('archive_flag', $sTargetClass),
'=',
new ScalarExpression(0)
);
$oRemoteClassSearch->AddConditionExpression($oNotArchived);
}
$oLinkSearch->AddCondition_PointingTo($oRemoteClassSearch, $sExtKeyToRemote);
$oLinkSearch->RenameAlias($oLinkSearch->GetClassAlias(), self::LINK_ALIAS);
$oLinkSearch->RenameAlias($sTargetClass, self::REMOTE_ALIAS);
$oLinkSearch->SetSelectedClasses([self::LINK_ALIAS, self::REMOTE_ALIAS]);
}
$oLinkSet = new DBObjectSet($oLinkSearch);
$oLinkSet->SetShowObsoleteData($bShowObsolete);
@@ -824,4 +848,4 @@ class ormLinkSet implements iDBObjectSetIterator, Iterator, SeekableIterator
return $oLinkSet;
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* @copyright Copyright (C) 2010-2020 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class PluginInstanciationManager
{
public function InstantiatePlugins($m_aExtensionClassNames, $sInterface)
{
$newPerInstanceClasses = array();
if (array_key_exists($sInterface, $m_aExtensionClassNames))
{
foreach ($m_aExtensionClassNames[$sInterface] as $sClassName)
{
if (class_exists($sClassName))
{
$class = new ReflectionClass($sClassName);
if ($class->isInstantiable())
{
$newPerInstanceClasses[$sClassName] = new $sClassName();
}
}
}
}
return $newPerInstanceClasses;
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* @copyright Copyright (C) 2010-2020 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0
*/
class PluginManager
{
private $m_aExtensionClassNames;
private static $m_aExtensionClasses;
private $m_pluginInstantiationManager;
public function __construct($m_aExtensionClassNames, $m_pluginInstanciationManager = null)
{
if (is_null(self::$m_aExtensionClasses)) {
self::$m_aExtensionClasses = [];
}
$this->m_aExtensionClassNames = $m_aExtensionClassNames;
if ($m_pluginInstanciationManager == null)
{
$this->m_pluginInstantiationManager = new PluginInstanciationManager();
}
else
{
$this->m_pluginInstantiationManager = $m_pluginInstanciationManager;
}
}
/**
* @param string $sInterface
* @param bool $bCanInstantiatePlugins internal use, let this value to true
* @param string|null $sFilterInstanceOf [optional] if given, only instance of this string will be returned
*
* @return array classes=>instance implementing the given interface
*/
public function EnumPlugins($sInterface, $sFilterInstanceOf = null, $bCanInstantiatePlugins = true)
{
$aPlugins = array();
if (array_key_exists($sInterface, self::$m_aExtensionClasses))
{
$aAllPlugins = array_values(self::$m_aExtensionClasses[$sInterface]);
if (is_null($sFilterInstanceOf))
{
return $aAllPlugins;
};
$aPlugins = array();
foreach ($aAllPlugins as $instance)
{
if ($instance instanceof $sFilterInstanceOf)
{
$aPlugins[] = $instance;
}
}
}
else
{
if ($bCanInstantiatePlugins && array_key_exists($sInterface, $this->m_aExtensionClassNames))
{
$this->InstantiatePlugins($sInterface);
return $this->EnumPlugins($sInterface, $sFilterInstanceOf, false);
}
}
return $aPlugins;
}
public function InstantiatePlugins($sInterface)
{
self::$m_aExtensionClasses[$sInterface] = $this->m_pluginInstantiationManager->InstantiatePlugins($this->m_aExtensionClassNames, $sInterface);
}
/**
* @param string $sInterface
* @param string $sClassName
* @param bool $bCanInstantiatePlugins internal use, let this value to true
*
* @return mixed the instance of the specified plug-ins for the given interface
*/
public function GetPlugins($sInterface, $sClassName, $bCanInstantiatePlugins = true)
{
$oInstance = null;
if (array_key_exists($sInterface, self::$m_aExtensionClasses))
{
if (array_key_exists($sClassName, self::$m_aExtensionClasses[$sInterface]))
{
return self::$m_aExtensionClasses[$sInterface][$sClassName];
}
}
else
{
if ($bCanInstantiatePlugins && array_key_exists($sInterface, $this->m_aExtensionClassNames))
{
$this->InstantiatePlugins($sInterface);
return $this->GetPlugins($sInterface, $sClassName, false);
}
}
return $oInstance;
}
}

View File

@@ -467,6 +467,18 @@ class CoreServices implements iRestServiceProvider
}
else
{
if (!$bExtendedOutput && RestUtils::GetOptionalParam($aParams, 'output_fields', '*') != '*')
{
$aFields = $aShowFields[$sClass];
//Id is not a valid attribute to optimize
if (in_array('id', $aFields))
{
unset($aFields[array_search('id', $aFields)]);
}
$aAttToLoad = array($oObjectSet->GetClassAlias() => $aFields);
$oObjectSet->OptimizeColumnLoad($aAttToLoad);
}
while ($oObject = $oObjectSet->Fetch())
{
$oResult->AddObject(0, '', $oObject, $aShowFields, $bExtendedOutput);

View File

@@ -365,29 +365,37 @@ EOF
{
throw new BulkExportMissingParameterException('fields');
}
else if(($sQueryId !== null) && ($sQueryId !== null))
else
{
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
$oQueries = new DBObjectSet($oSearch);
if ($oQueries->Count() > 0)
if (($sQueryId !== null) && ($sQueryId !== null))
{
$oQuery = $oQueries->Fetch();
if (($sFields === null) || ($sFields === ''))
$oSearch = DBObjectSearch::FromOQL('SELECT QueryOQL WHERE id = :query_id', array('query_id' => $sQueryId));
$oQueries = new DBObjectSet($oSearch);
if ($oQueries->Count() > 0)
{
// No 'fields' parameter supplied, take the fields from the query phrasebook definition
$sFields = trim($oQuery->Get('fields'));
if ($sFields === '')
$oQuery = $oQueries->Fetch();
if (($sFields === null) || ($sFields === ''))
{
throw new BulkExportMissingParameterException('fields');
// No 'fields' parameter supplied, take the fields from the query phrasebook definition
$sFields = trim($oQuery->Get('fields'));
if ($sFields === '')
{
throw new BulkExportMissingParameterException('fields');
}
}
}
}
else
{
throw BulkExportException('Invalid value for the parameter: query. There is no Query Phrasebook with id = '.$sQueryId, Dict::Format('Core:BulkExport:InvalidParameter_Query', $sQueryId));
else
{
throw BulkExportException('Invalid value for the parameter: query. There is no Query Phrasebook with id = '.$sQueryId, Dict::Format('Core:BulkExport:InvalidParameter_Query', $sQueryId));
}
}
}
$this->SetFields($sFields);
}
public function SetFields($sFields)
{
// Interpret (and check) the list of fields
//
$aSelectedClasses = $this->oSearch->GetSelectedClasses();

View File

@@ -220,7 +220,7 @@ class ValueSetObjects extends ValueSetDefinition
$this->m_sOperation = $sOperation;
$this->m_aValues = array();
if ($this->m_bAllowAllData)
{
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
@@ -348,6 +348,160 @@ class ValueSetObjects extends ValueSetDefinition
{
$this->m_bSort = $bSort;
}
public function GetValuesForAutocomplete($aArgs, $sContains = '', $sOperation = 'contains')
{
if (!$this->m_bIsLoaded || ($sContains != $this->m_sContains) || ($sOperation != $this->m_sOperation))
{
$this->LoadValuesForAutocomplete($aArgs, $sContains, $sOperation);
$this->m_bIsLoaded = true;
}
// The results are already filtered and sorted (on friendly name)
$aRet = $this->m_aValues;
return $aRet;
}
/**
* @param $aArgs
* @param string $sContains
* @param string $sOperation 'contains' or 'equals_start_with'
*
* @return bool
* @throws \CoreException
* @throws \OQLException
*/
protected function LoadValuesForAutocomplete($aArgs, $sContains = '', $sOperation = 'contains')
{
$this->m_sContains = $sContains;
$this->m_sOperation = $sOperation;
$this->m_aValues = array();
if ($this->m_bAllowAllData)
{
$oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr);
}
else
{
$oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr);
$oFilter->SetShowObsoleteData(utils::ShowObsoleteData());
}
if (!$oFilter) return false;
if (!is_null($this->m_oExtraCondition))
{
$oFilter = $oFilter->Intersect($this->m_oExtraCondition);
}
foreach($this->m_aModifierProperties as $sPluginClass => $aProperties)
{
foreach ($aProperties as $sProperty => $value)
{
$oFilter->SetModifierProperty($sPluginClass, $sProperty, $value);
}
}
//$oExpression = DBObjectSearch::GetPolymorphicExpression($oFilter->GetClass(), 'friendlyname');
$sClass = $oFilter->GetClass();
switch ($sOperation)
{
case 'equals':
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
$sClassAlias = $oFilter->GetClassAlias();
$aFilters = array();
$oValueExpr = new ScalarExpression($sContains);
foreach($aAttributes as $sAttribute)
{
$oNewFilter = $oFilter->DeepClone();
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
$oCondition = new BinaryExpression($oNameExpr, '=', $oValueExpr);
$oNewFilter->AddConditionExpression($oCondition);
$aFilters[] = $oNewFilter;
}
// Unions are much faster than OR conditions
$oFilter = new DBUnionSearch($aFilters);
break;
case 'start_with':
$aAttributes = MetaModel::GetFriendlyNameAttributeCodeList($sClass);
$sClassAlias = $oFilter->GetClassAlias();
$aFilters = array();
$oValueExpr = new ScalarExpression($sContains.'%');
foreach($aAttributes as $sAttribute)
{
$oNewFilter = $oFilter->DeepClone();
$oNameExpr = new FieldExpression($sAttribute, $sClassAlias);
$oCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
$oNewFilter->AddConditionExpression($oCondition);
$aFilters[] = $oNewFilter;
}
// Unions are much faster than OR conditions
$oFilter = new DBUnionSearch($aFilters);
break;
default:
$oValueExpr = new ScalarExpression('%'.$sContains.'%');
$oNameExpr = new FieldExpression('friendlyname', $oFilter->GetClassAlias());
$oNewCondition = new BinaryExpression($oNameExpr, 'LIKE', $oValueExpr);
$oFilter->AddConditionExpression($oNewCondition);
break;
}
$oObjects = new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs, null, $this->m_iLimit, 0, $this->m_bSort);
if (empty($this->m_sValueAttCode))
{
$aAttToLoad = array($oFilter->GetClassAlias() => array('friendlyname'));
}
else
{
$aAttToLoad = array($oFilter->GetClassAlias() => array($this->m_sValueAttCode));
}
$aComplementAttributeSpec = MetaModel::GetComplementAttributeSpec($sClass);
$sFormatAdditionalField = $aComplementAttributeSpec[0];
$aAdditionalField = $aComplementAttributeSpec[1];
if (count($aAdditionalField)>0)
{
$aAttToLoad = array_merge ($aAttToLoad, [$oFilter->GetClassAlias() => $aAdditionalField]);
}
$oObjects->OptimizeColumnLoad($aAttToLoad);
while ($oObject = $oObjects->Fetch())
{
$aData=[];
if (empty($this->m_sValueAttCode))
{
$aData['label'] = $oObject->GetName();
}
else
{
$aData['label'] = $oObject->Get($this->m_sValueAttCode);
}
if($oObject->IsObsolete())
{
$aData['obsolescence_flag']='1';
}
else
{
$aData['obsolescence_flag']='0';
}
if (count($aAdditionalField)>0)
{
$aArguments = [];
foreach ($aAdditionalField as $sAdditionalField)
{
array_push ($aArguments,$oObject->Get($sAdditionalField));
}
$aData['additional_field'] = vsprintf($sFormatAdditionalField, $aArguments);
}
else
{
$aData['additional_field']='';
}
$this->m_aValues[$oObject->GetKey()] = $aData;
}
return true;
}
}

View File

@@ -15,10 +15,7 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
$version: "v2.8.0";
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
$approot-relative: "../../../../" !default; // relative to env-***/branding/themes/***/main.css
// Base colors
$gray-base: #000 !default;
@@ -127,3 +124,8 @@ $highlight-item-color: $white !default;
$content-color: #eeeeee !default;
$default-font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif !default;
$icons-filter: hue-rotate(0deg) !default;
%font-awesome-prerequisites{
font-family: 'Font Awesome 5 Free';
font-weight: 600;
}

View File

@@ -2165,6 +2165,11 @@ fieldset .details>.field_container {
background: transparent;
border: 0;
}
.field_input_zone {
.selectize-input {
padding: 0px;
}
}
.field_container {
display: table;
width: 100%;
@@ -2257,6 +2262,7 @@ fieldset .details>.field_container {
.field_input_zone{
width: 100%; /* auto; */
align-items:center;
&.field_input_string,
&.field_input_password{
@@ -2390,7 +2396,7 @@ fieldset .details>.field_container {
}
&.field_input_extkey{
display: table;
display: inline-table;
width: 100%;
> .field_select_wrapper{
@@ -2874,13 +2880,34 @@ a.summary, a.summary:hover {
height: 12px;
}
.sort_none {
background: url($approot-relative + "images/bg.gif?v=" + $version) no-repeat center;
padding-right: 5px;
&::after {
@extend %font-awesome-prerequisites;
text-align: right;
content: '\f0dc';
color: $complement-color;
float: right;
}
}
.sort_asc {
background: url($approot-relative + "images/desc.gif?v=" + $version) no-repeat center;
padding-right: 5px;
&::after {
@extend %font-awesome-prerequisites;
text-align: right;
content: '\f0d8';
color: $complement-color;
float: right;
}
}
.sort_desc {
background: url($approot-relative + "images/asc.gif?v=" + $version) no-repeat center;
padding-right: 5px;
&::after {
@extend %font-awesome-prerequisites;
text-align: right;
content: '\f0d7';
color: $complement-color;
float: right;
}
}
.sort_hidden {
display: none;

View File

@@ -1,267 +0,0 @@
/*!
* Copyright (C) 2013-2020 Combodo SARL
*
* This file is part of iTop.
*
* iTop is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* iTop is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
*/
/* Helpers classes */
.center {
text-align: center;
}
/* Animations */
@keyframes progress_bar_color_ongoing {
from {
background-color: #FBD38D;
}
to {
background-color: #FEEBC8;
}
}
@-webkit-keyframes bg-pan-left {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
@keyframes bg-pan-left {
0% {
background-position: 100% 50%;
}
100% {
background-position: 0 50%;
}
}
/* Theme */
body {
background-color: #eee;
color: #1A202C;
margin: 0;
padding: 0;
font-size: 10pt;
font-family: Tahoma, Verdana, Arial, Helvetica, serif;
overflow-y: auto;
}
h1 {
color: #555555;
font-size: 16pt;
}
h2 {
color: #1A202C;
font-size: 14pt;
font-weight: normal;
}
h3 {
color: #1C94C4;
font-size: 12pt;
font-weight: bold;
}
a {
color: #1c94c4;
text-decoration: none;
}
a:hover {
color: #EA7D1E;
}
#header {
width: 600px;
margin-left: auto;
margin-right: auto;
margin-top: 50px;
padding: 20px;
background-color: #fff;
height: 54px;
border: 3px solid #CBD2D9;
border-bottom: none;
}
#header img {
border: 0;
vertical-align: middle;
margin-right: 20px;
}
#header h1 {
height: 54px;
margin: 0;
}
#setup {
width: 600px;
margin-left: auto;
margin-right: auto;
padding: 20px;
background-color: #fff;
border: 3px solid #CBD2D9;
border-top: none;
}
.next {
width: 100%;
text-align: right;
}
.v-spacer {
padding-top: 1em;
}
button {
margin-top: 1em;
padding-left: 1em;
padding-right: 1em;
}
p.info {
padding-left: 50px;
background: url(../images/info-mid.png) no-repeat left -5px;
min-height: 48px;
}
p.ok {
padding-left: 50px;
background: url(../images/clean-mid.png) no-repeat left -8px;
min-height: 48px;
}
p.warning {
padding-left: 50px;
background: url(../images/messagebox_warning-mid.png) no-repeat left -5px;
min-height: 48px;
}
p.error {
padding-left: 50px;
background: url(../images/stop-mid.png) no-repeat left -5px;
min-height: 48px;
}
label {
cursor: pointer;
}
td.label {
text-align: left;
}
label.read-only {
color: #666;
cursor: text;
}
td.input {
text-align: left;
}
table.formTable {
border: 0;
}
.wizlabel, .wizinput {
color: #000;
font-size: 10pt;
}
.wizhelp {
color: #333;
font-size: 8pt;
}
#progress {
border: none;
width: 210px;
height: 26px;
line-height: 26px;
text-align: center;
margin: 5px;
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06) !important;
border-radius: 2px;
background-color: #EDF2F7 !important;
}
#progress .progress {
color: #000000 !important;
/* !important to overload jQuery UI style */
background-image: linear-gradient(270deg, #FBD38D 50%, #FEEBC8 55%, #FBD38D 80%) !important;
/* !important to overload jQuery UI style */
animation: bg-pan-left 3s infinite both;
background-size: 600% 100%;
border-radius: inherit;
}
#progress .progress.progress-error {
background-image: none !important;
background-color: #F56565 !important;
/* !important to overload jQuery UI style */
animation: none;
}
h3.clickable {
background: url(../images/plus.gif) no-repeat left;
padding-left: 16px;
cursor: hand;
}
h3.clickable.open {
background: url(../images/minus.gif) no-repeat left;
padding-left: 16px;
cursor: hand;
}
.message {
color: #1A202C;
background-color: #F7FAFC;
border-left: 4px solid #4A5568;
padding: 10px;
}
.message > .message-title {
font-weight: bold;
margin-right: 5px;
}
.message ~ .message {
margin-top: 6px;
}
.message.message-valid {
color: #276749;
background-color: #F0FFF4;
border-color: #48BB78;
}
.message.message-warning {
color: #C05621;
background-color: #FFFAF0;
border-color: #ED8936;
}
.message.message-error {
color: #C53030;
background-color: #FFF5F5;
border-color: #E53E3E;
}
.text-valid {
color: #276749;
}
.text-warning {
color: #C05621;
}
.text-error {
color: #C53030;
}
fieldset {
border: none;
padding: 0;
margin: 30px 0 0 0;
}
fieldset > legend {
margin-top: 25px;
margin-bottom: 7px;
padding-bottom: 7px;
width: 100%;
color: #3C3C3C;
font-size: 11pt;
font-weight: bold;
border-bottom: 1px solid #D2D2D2;
}
.module-selection-banner img {
max-height: 48px;
}
.module-selection-body {
height: 28em;
overflow: auto;
box-shadow: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06) !important;
background-color: #F7FAFC;
padding: 10px;
}
.module-selection-body .wiz-choice:checked ~ .description #itop-ticket-mgmt-simple-ticket-enhanced-portal:not(:checked) ~ .description::after, .module-selection-body .wiz-choice:checked ~ .description #itop-ticket-mgmt-itil-enhanced-portal:not(:checked) ~ .description::after {
content: "Legacy portal is no longer part of iTop, by leaving this option unchecked your portal users won't be able to access iTop anymore.";
display: block;
margin-top: 0.5em;
font-weight: bold;
color: #e60000b8;
}

View File

@@ -16,6 +16,8 @@
* You should have received a copy of the GNU Affero General Public License
*/
/* integrityCheck: begin (do not remove/edit) */
/////////
// Colors
$content-border-color: #CBD2D9 !default;
@@ -314,3 +316,4 @@ fieldset{
}
}
/* integrityCheck: end (do not remove/edit) */

View File

@@ -0,0 +1,12 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2013 XXXXX
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'CAS:Error:UserNotAllowed' => 'Usuário não permitido',
'CAS:Login:SignIn' => 'Autenticar com CAS',
'CAS:Login:SignInTooltip' => 'Clique aqui para se autenticar no servidor CAS',
));

View File

@@ -1,12 +0,0 @@
<?php
/**
* Localized data
*
* @copyright Copyright (C) 2013 XXXXX
* @license http://opensource.org/licenses/AGPL-3.0
*/
Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'CAS:Error:UserNotAllowed' => 'User not allowed~~',
'CAS:Login:SignIn' => 'Sign in with CAS~~',
'CAS:Login:SignInTooltip' => 'Click here to authenticate yourself with the CAS server~~',
));

View File

@@ -496,7 +496,7 @@ class CASUserProvisioning
}
// Now synchronize the profiles
LoginWebPage::SynchroniseProfiles($oUser, $aProfiles, 'CAS/LDAP Synchro');
LoginWebPage::SynchronizeProfiles($oUser, $aProfiles, 'CAS/LDAP Synchro');
phpCAS::log("Info: the user '".$oUser->GetName()."' (id=".$oUser->GetKey().") now has the following profiles: '".implode("', '", $aProfiles)."'.");
if ($oUser->IsModified())

View File

@@ -16,7 +16,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
/**
* @author Hirofumi Kosaka <kosaka@rworks.jp>
* @author Hirofumi Kosaka <kosaka@rworks.jp>
* @copyright Copyright (C) 2010-2012 Combodo SARL
* @licence http://opensource.org/licenses/AGPL-3.0
*/

Some files were not shown because too many files have changed in this diff Show More